)(.*?)""".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 {
- """(.+?) - (.*?).+?.+?\((.+?), .+?(.+?)\)""".toRegex(DOT_MATCHES_ALL)
+ """(.+?)\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)
}
@@ -123,12 +151,21 @@ object Regexes {
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-z_]+)""".toRegex()
}
+ val LIBRUS_MESSAGE_ID by lazy {
+ """/wiadomosci/[0-9]+/[0-9]+/([0-9]+?)/""".toRegex()
+ }
@@ -155,6 +192,9 @@ object Regexes {
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()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
index db8186c9..c6938f7a 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/EdziennikTask.kt
@@ -5,29 +5,37 @@
package pl.szczodrzynski.edziennik.data.api.edziennik
import com.google.gson.JsonObject
-import pl.szczodrzynski.edziennik.App
-import pl.szczodrzynski.edziennik.R
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.Edudziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.Idziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.Mobidziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.Podlasie
import pl.szczodrzynski.edziennik.data.api.edziennik.template.Template
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.Vulcan
+import pl.szczodrzynski.edziennik.data.api.events.RegisterAvailabilityEvent
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.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.data.api.task.IApiTask
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
open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTask(profileId) {
companion object {
private const val TAG = "EdziennikTask"
+ var profile: Profile? = null
+ var loginStore: LoginStore? = null
+
fun firstLogin(loginStore: LoginStore) = EdziennikTask(-1, FirstLoginRequest(loginStore))
fun sync() = EdziennikTask(-1, SyncRequest())
fun syncProfile(profileId: Int, viewIds: List
>? = null, onlyEndpoints: List? = null, arguments: JsonObject? = null) = EdziennikTask(profileId, SyncProfileRequest(viewIds, onlyEndpoints, arguments))
@@ -36,8 +44,9 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
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, message: Message, attachmentId: Long, attachmentName: String) = EdziennikTask(profileId, AttachmentGetRequest(message, attachmentId, attachmentName))
+ 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
@@ -58,21 +67,65 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
// 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) {
- if (profile?.archived == true) {
- taskCallback.onError(ApiError(TAG, ERROR_PROFILE_ARCHIVED))
- return
+ 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
+ }
+
+ profile.registerName?.let { registerName ->
+ var status = app.config.sync.registerAvailability[registerName]
+ if (status == null || status.nextCheckAt < currentTimeUnix()) {
+ val api = SzkolnyApi(app)
+ api.runCatching({
+ val availability = getRegisterAvailability()
+ app.config.sync.registerAvailability = availability
+ status = availability[registerName]
+ }, onError = {
+ taskCallback.onError(it.toApiError(TAG))
+ return
+ })
+ }
+
+ if (status?.available != true
+ || status?.minVersionCode ?: BuildConfig.VERSION_CODE > BuildConfig.VERSION_CODE) {
+ if (EventBus.getDefault().hasSubscriberForEvent(RegisterAvailabilityEvent::class.java)) {
+ EventBus.getDefault().postSticky(
+ RegisterAvailabilityEvent(app.config.sync.registerAvailability)
+ )
+ }
+ cancel()
+ taskCallback.onCompleted()
+ return
+ }
+ }
}
+
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_IDZIENNIK -> Idziennik(app, profile, loginStore, taskCallback)
LOGIN_TYPE_EDUDZIENNIK -> Edudziennik(app, profile, loginStore, taskCallback)
+ LOGIN_TYPE_PODLASIE -> Podlasie(app, profile, loginStore, taskCallback)
LOGIN_TYPE_TEMPLATE -> Template(app, profile, loginStore, taskCallback)
else -> null
}
@@ -92,12 +145,14 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
is FirstLoginRequest -> edziennikInterface?.firstLogin()
is AnnouncementsReadRequest -> edziennikInterface?.markAllAnnouncementsAsRead()
is AnnouncementGetRequest -> edziennikInterface?.getAnnouncement(request.announcement)
- is AttachmentGetRequest -> edziennikInterface?.getAttachment(request.message, request.attachmentId, request.attachmentName)
+ 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()
}
@@ -113,6 +168,7 @@ open class EdziennikTask(override val profileId: Int, val request: Any) : IApiTa
data class MessageSendRequest(val recipients: List, val subject: String, val text: String)
class AnnouncementsReadRequest
data class AnnouncementGetRequest(val announcement: AnnouncementFull)
- data class AttachmentGetRequest(val message: Message, val attachmentId: Long, val attachmentName: String)
+ 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/Edudziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/Edudziennik.kt
index 7bc50511..23d9d3b1 100644
--- 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
@@ -9,6 +9,7 @@ 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
@@ -16,10 +17,10 @@ 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.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
@@ -94,9 +95,17 @@ class Edudziennik(val app: App, val profile: Profile?, val loginStore: LoginStor
}
}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {}
+ 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")
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
index 11f048b5..32ca353c 100644
--- 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
@@ -45,24 +45,25 @@ class EdudziennikWebAnnouncements(override val data: DataEdudziennik,
val addedDate = Date.fromIsoHm(dateString)
val announcementObject = Announcement(
- profileId,
- id,
- subject,
- null,
- startDate,
- null,
- teacher.id,
- longId
- )
+ profileId = profileId,
+ id = id,
+ subject = subject,
+ text = null,
+ startDate = startDate,
+ endDate = null,
+ teacherId = teacher.id,
+ addedDate = addedDate
+ ).also {
+ it.idString = longId
+ }
- data.announcementIgnoreList.add(announcementObject)
+ data.announcementList.add(announcementObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ANNOUNCEMENT,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
}
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
index 92545117..7fe18171 100644
--- 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
@@ -39,12 +39,12 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
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()
+ val symbol = type?.get(1)?.trim() ?: "?"
+ val name = type?.get(2)?.trim() ?: "nieznany rodzaj"
return@map Triple(
symbol,
name,
- when (name?.toLowerCase(Locale.ROOT)) {
+ when (name.toLowerCase(Locale.ROOT)) {
"obecność" -> Attendance.TYPE_PRESENT
"nieobecność" -> Attendance.TYPE_ABSENT
"spóźnienie" -> Attendance.TYPE_BELATED
@@ -52,7 +52,7 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
"dzień wolny" -> Attendance.TYPE_DAY_FREE
"brak zajęć" -> Attendance.TYPE_DAY_FREE
"oddelegowany" -> Attendance.TYPE_RELEASED
- else -> Attendance.TYPE_CUSTOM
+ else -> Attendance.TYPE_UNKNOWN
}
)
} ?: emptyList()
@@ -62,38 +62,42 @@ class EdudziennikWebAttendance(override val data: DataEdudziennik,
val lessonNumber = attendanceElement[2].toInt()
val attendanceSymbol = attendanceElement[3]
- val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
+ 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 (_, name, type) = attendanceTypes.firstOrNull { (symbol, _, _) -> symbol == attendanceSymbol }
+ 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,
- id,
- lesson?.displayTeacherId ?: -1,
- lesson?.displaySubjectId ?: -1,
- profile.currentSemester,
- name,
- date,
- lesson?.displayStartTime ?: startTime,
- type
- )
+ 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(type != Attendance.TYPE_PRESENT) {
+ if (baseType != Attendance.TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
id,
- profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN,
+ profile.empty || baseType == Attendance.TYPE_PRESENT_CUSTOM || baseType == Attendance.TYPE_UNKNOWN
))
}
}
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
index cf846fce..35c68478 100644
--- 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
@@ -39,17 +39,16 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
?: return@forEach
val eventObject = Event(
- profileId,
- id,
- date,
- null,
- title,
- -1,
- Event.TYPE_CLASS_EVENT,
- false,
- -1,
- -1,
- data.teamClass?.id ?: -1
+ 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)
@@ -58,8 +57,7 @@ class EdudziennikWebEvents(override val data: DataEdudziennik,
Metadata.TYPE_EVENT,
id,
profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
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
index 8eb7d04e..f6abf637 100644
--- 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
@@ -46,7 +46,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
if (dateString.isBlank()) return@forEach
val date = Date.fromY_m_d(dateString)
- val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
+ 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)
@@ -56,17 +56,16 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
val eventType = data.getEventType(eventTypeId, eventTypeName)
val eventObject = Event(
- profileId,
- id,
- date,
- startTime,
- topic,
- -1,
- eventType.id,
- false,
- -1,
- subject.id,
- data.teamClass?.id ?: -1
+ 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)
@@ -75,8 +74,7 @@ class EdudziennikWebExams(override val data: DataEdudziennik,
Metadata.TYPE_EVENT,
id,
profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
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
index 50557333..459f13aa 100644
--- 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
@@ -126,7 +126,8 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
comment = null,
semester = semester,
teacherId = teacher.id,
- subjectId = subject.id
+ subjectId = subject.id,
+ addedDate = addedDate
)
data.gradeList.add(gradeObject)
@@ -135,8 +136,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
@@ -168,8 +168,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
proposedGradeObject.id,
profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
@@ -201,8 +200,7 @@ class EdudziennikWebGrades(override val data: DataEdudziennik,
Metadata.TYPE_GRADE,
finalGradeObject.id,
profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
}
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
index 9d9a336a..169a5127 100644
--- 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
@@ -33,8 +33,8 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
if (doc.getElementsByClass("message").text().trim() != "Brak prac domowych") {
doc.getElementsByTag("tr").forEach { homeworkElement ->
val dateElement = homeworkElement.getElementsByClass("date").first().child(0)
- val id = EDUDZIENNIK_HOMEWORK_ID.find(dateElement.attr("href"))?.get(1)?.crc32()
- ?: return@forEach
+ 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)
@@ -43,36 +43,36 @@ class EdudziennikWebHomework(override val data: DataEdudziennik,
val subjectName = subjectElement.text()
val subject = data.getSubject(subjectId, subjectName)
- val lessons = data.app.db.timetableDao().getForDateNow(profileId, date)
+ 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()
+ val topic = homeworkElement.child(4).text()?.trim()
val eventObject = Event(
- profileId,
- id,
- date,
- startTime,
- topic,
- -1,
- Event.TYPE_HOMEWORK,
- false,
- teacher.id,
- subject.id,
- data.teamClass?.id ?: -1
+ 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,
- System.currentTimeMillis()
+ profile.empty
))
}
}
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
index 70c6849a..db8164c8 100644
--- 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
@@ -24,9 +24,9 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
webGet(TAG, data.schoolEndpoint + "Lucky", xhr = true) { text ->
text.toIntOrNull()?.also { luckyNumber ->
val luckyNumberObject = LuckyNumber(
- profileId,
- Date.getToday(),
- luckyNumber
+ profileId = profileId,
+ date = Date.getToday(),
+ number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@@ -35,8 +35,7 @@ class EdudziennikWebLuckyNumber(override val data: DataEdudziennik,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
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
index a111ef79..35a78168 100644
--- 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
@@ -41,12 +41,15 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
val description = noteElement.child(3).text()
val noticeObject = Notice(
- profileId,
- id,
- description,
- profile.currentSemester,
- Notice.TYPE_NEUTRAL,
- teacher.id
+ 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)
@@ -55,8 +58,7 @@ class EdudziennikWebNotes(override val data: DataEdudziennik,
Metadata.TYPE_NOTICE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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
index 3a31e208..94db15ef 100644
--- 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
@@ -124,8 +124,7 @@ class EdudziennikWebTimetable(override val data: DataEdudziennik,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
}
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
index e47c7842..a93632b1 100644
--- 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
@@ -59,7 +59,7 @@ class EdudziennikFirstLogin(val data: DataEdudziennik, val onSuccess: () -> Unit
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/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/Idziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/Idziennik.kt
index be0d0d1c..e1550632 100644
--- 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
@@ -8,20 +8,15 @@ import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikData
-import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetAttachment
-import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetMessage
-import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebGetRecipientList
-import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.IdziennikWebSendMessage
+import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web.*
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.firstlogin.IdziennikFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.login.IdziennikLogin
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikInterface
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.data.db.entity.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.entity.*
import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.utils.Utils.d
@@ -103,10 +98,17 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
override fun markAllAnnouncementsAsRead() {}
override fun getAnnouncement(announcement: AnnouncementFull) {}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
login(LOGIN_METHOD_IDZIENNIK_WEB) {
- IdziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
- completed()
+ if (owner is Message) {
+ IdziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
+ completed()
+ }
+ }
+ else if (owner is Event) {
+ IdziennikWebGetHomeworkAttachment(data, owner, attachmentId, attachmentName) {
+ completed()
+ }
}
}
}
@@ -119,6 +121,14 @@ class Idziennik(val app: App, val profile: Profile?, val loginStore: LoginStore,
}
}
+ override fun getEvent(eventFull: EventFull) {
+ login(LOGIN_METHOD_IDZIENNIK_WEB) {
+ IdziennikWebGetHomework(data, eventFull) {
+ completed()
+ }
+ }
+ }
+
override fun firstLogin() { IdziennikFirstLogin(data) { completed() } }
override fun cancel() {
d(TAG, "Cancelled")
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
index 907e1f50..b871cd37 100644
--- 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
@@ -229,6 +229,7 @@ open class IdziennikWeb(open val data: DataIdziennik, open val lastSync: Long?)
.apply {
parameters.forEach { (k, v) -> addParameter(k, v) }
}
+ .contentType("application/x-www-form-urlencoded")
.post()
.callback(callback)
.build()
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
index 0e000fb1..d5e59596 100644
--- 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
@@ -68,9 +68,9 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
val luckyNumberObject = LuckyNumber(
- data.profileId,
- luckyNumberDate,
- luckyNumber
+ profileId = data.profileId,
+ date = luckyNumberDate,
+ number = luckyNumber
)
data.luckyNumberList.add(luckyNumberObject)
@@ -80,8 +80,7 @@ class IdziennikApiCurrentRegister(override val data: DataIdziennik,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
+ data.profile?.empty ?: false
))
}
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
index c8d756fe..622068e2 100644
--- 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
@@ -11,8 +11,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_INBOX
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi
import pl.szczodrzynski.edziennik.data.db.entity.*
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.getBoolean
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.Utils.crc32
@@ -33,11 +33,11 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
return@apiGet
}
- json.asJsonObjectList()?.forEach { jMessage ->
- val subject = jMessage.getString("tytul")
- if (subject?.contains("(") == true && subject.startsWith("iDziennik - "))
+ json.asJsonObjectList().forEach { jMessage ->
+ val subject = jMessage.getString("tytul") ?: ""
+ if (subject.contains("(") && subject.startsWith("iDziennik - "))
return@forEach
- if (subject?.startsWith("Uwaga dla ucznia (klasa:") == true)
+ if (subject.startsWith("Uwaga dla ucznia (klasa:"))
return@forEach
val messageIdStr = jMessage.getString("id")
@@ -64,13 +64,13 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
rTeacher.setTeacherType(Teacher.TYPE_OTHER)
val message = Message(
- profileId,
- messageId,
- subject,
- body,
- if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
- rTeacher.id,
- -1
+ profileId = profileId,
+ id = messageId,
+ type = if (jMessage.getBoolean("rekordUsuniety") == true) TYPE_DELETED else TYPE_RECEIVED,
+ subject = subject,
+ body = body,
+ senderId = rTeacher.id,
+ addedDate = sentDate
)
val messageRecipient = MessageRecipient(
@@ -81,15 +81,14 @@ class IdziennikApiMessagesInbox(override val data: DataIdziennik,
/*messageId*/ messageId
)
- data.messageIgnoreList.add(message)
+ data.messageList.add(message)
data.messageRecipientList.add(messageRecipient)
data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
message.id,
readDate > 0,
- readDate > 0 || profile?.empty ?: false,
- sentDate
+ readDate > 0 || profile?.empty ?: false
))
}
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
index b0b17689..87b3264d 100644
--- 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
@@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNIK_API_MESSAGES_SENT
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikApi
import pl.szczodrzynski.edziennik.data.db.entity.Message
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.utils.Utils.crc32
@@ -46,13 +46,13 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
val sentDate = Date.fromIso(jMessage.get("dataWyslania").asString)
val message = Message(
- profileId,
- messageId,
- subject,
- body,
- TYPE_SENT,
- -1,
- -1
+ profileId = profileId,
+ id = messageId,
+ type = TYPE_SENT,
+ subject = subject,
+ body = body,
+ senderId = null,
+ addedDate = sentDate
)
for (recipientEl in jMessage.getAsJsonArray("odbiorcy")) {
@@ -76,8 +76,8 @@ class IdziennikApiMessagesSent(override val data: DataIdziennik,
data.messageRecipientIgnoreList.add(messageRecipient)
}
- data.messageIgnoreList.add(message)
- data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true, sentDate))
+ data.messageList.add(message)
+ data.metadataList.add(Metadata(profileId, Metadata.TYPE_MESSAGE, message.id, true, true))
}
data.setSyncNext(ENDPOINT_IDZIENNIK_API_MESSAGES_SENT, DAY, DRAWER_ITEM_MESSAGES)
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
index f8744efa..531cbeeb 100644
--- 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
@@ -52,14 +52,14 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
val startDate = jAnnouncement.getString("DataWydarzenia")?.replace("[^\\d]".toRegex(), "")?.toLongOrNull()?.let { Date.fromMillis(it) }
val announcementObject = Announcement(
- profileId,
- announcementId,
- jAnnouncement.get("Temat").asString,
- jAnnouncement.get("Tresc").asString,
- startDate,
- null,
- rTeacher.id,
- null
+ profileId = profileId,
+ id = announcementId,
+ subject = jAnnouncement.get("Temat").asString,
+ text = jAnnouncement.get("Tresc").asString,
+ startDate = startDate,
+ endDate = null,
+ teacherId = rTeacher.id,
+ addedDate = addedDate
)
data.announcementList.add(announcementObject)
data.metadataList.add(Metadata(
@@ -67,8 +67,7 @@ class IdziennikWebAnnouncements(override val data: DataIdziennik,
Metadata.TYPE_ANNOUNCEMENT,
announcementObject.id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
+ profile?.empty ?: false
))
}
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
index aa0a9998..e77c9eac 100644
--- 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
@@ -12,10 +12,18 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.ENDPOINT_IDZIENNI
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
-import pl.szczodrzynski.edziennik.data.db.entity.Attendance.*
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_ABSENT_EXCUSED
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_BELATED
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT_CUSTOM
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_RELEASED
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_UNKNOWN
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.getInt
import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
@@ -51,71 +59,97 @@ class IdziennikWebAttendance(override val data: DataIdziennik,
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())
+ val type = jAttendance.get("TypObecnosci").asInt
+
+ // skip "zajęcia nie odbyły się" and "Ferie"
+ if (type == 5 || type == 7)
continue
- val attendanceId = jAttendance.get("IdLesson").asString.crc16().toLong()
+ val date = Date.fromY_m_d(jAttendance.get("Data").asString)
+ val time = Time.fromH_m(jAttendance.get("OdDoGodziny").asString)
+ if (date.combineWith(time) > System.currentTimeMillis())
+ continue
+
+ val id = jAttendance.get("IdLesson").asString.crc16().toLong()
val rSubject = data.getSubject(jAttendance.get("Przedmiot").asString, jAttendance.get("IdPrzedmiot").asLong, "")
val rTeacher = data.getTeacherByFDotSpaceLast(jAttendance.get("PrzedmiotNauczyciel").asString)
- var attendanceName = "obecność"
- var attendanceType = Attendance.TYPE_CUSTOM
+ var baseType = TYPE_UNKNOWN
+ var typeName = "nieznany rodzaj"
+ var typeSymbol: String? = null
+ var typeColor: Long? = null
- when (attendanceTypeIdziennik) {
- 1 /* nieobecność usprawiedliwiona */ -> {
- attendanceName = "nieobecność usprawiedliwiona"
- attendanceType = TYPE_ABSENT_EXCUSED
+ /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosciUcznia_lmt637231494660000000.js */
+ /* https://iuczniowie.progman.pl/idziennik/mod_panelRodzica/obecnosci/obecnosci_lmt637231494660000000.css */
+ when (type) {
+ 1 -> {
+ baseType = TYPE_ABSENT_EXCUSED
+ typeName = "nieobecność usprawiedliwiona"
+ typeColor = 0xffffe099
}
- 2 /* spóźnienie */ -> {
- attendanceName = "spóźnienie"
- attendanceType = TYPE_BELATED
+ 2 -> {
+ baseType = TYPE_BELATED
+ typeName = "spóźnienie"
+ typeColor = 0xffffffaa
}
- 3 /* nieobecność nieusprawiedliwiona */ -> {
- attendanceName = "nieobecność nieusprawiedliwiona"
- attendanceType = TYPE_ABSENT
+ 3 -> {
+ baseType = TYPE_ABSENT
+ typeName = "nieobecność nieusprawiedliwiona"
+ typeColor = 0xffffad99
}
- 4 /* zwolnienie */, 9 /* zwolniony / obecny */ -> {
- attendanceType = TYPE_RELEASED
- if (attendanceTypeIdziennik == 4)
- attendanceName = "zwolnienie"
- if (attendanceTypeIdziennik == 9)
- attendanceName = "zwolnienie / obecność"
+ 4, 9 -> {
+ baseType = TYPE_RELEASED
+ if (type == 4) {
+ typeName = "zwolnienie"
+ typeColor = 0xffa8beff
+ }
+ if (type == 9) {
+ typeName = "zwolniony / obecny"
+ typeSymbol = "zb"
+ typeColor = 0xffff69b4
+ }
}
- 0 /* obecny */, 8 /* Wycieczka */ -> {
- attendanceType = TYPE_PRESENT
- if (attendanceTypeIdziennik == 8)
- attendanceName = "wycieczka"
+ 8 -> {
+ baseType = TYPE_PRESENT_CUSTOM
+ typeName = "wycieczka"
+ typeSymbol = "w"
+ typeColor = null
+ }
+ 0 -> {
+ baseType = TYPE_PRESENT
+ typeName = "obecny"
+ typeColor = 0xffccffcc
}
}
- val semester = profile?.dateToSemester(attendanceDate) ?: 1
+ val semester = profile?.dateToSemester(date) ?: 1
val attendanceObject = Attendance(
- profileId,
- attendanceId,
- rTeacher.id,
- rSubject.id,
- semester,
- attendanceName,
- attendanceDate,
- attendanceTime,
- attendanceType
- )
+ profileId = profileId,
+ id = id,
+ baseType = baseType,
+ typeName = typeName,
+ typeShort = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
+ typeSymbol = typeSymbol ?: data.app.attendanceManager.getTypeShort(baseType),
+ typeColor = typeColor?.toInt(),
+ date = date,
+ startTime = time,
+ semester = semester,
+ teacherId = rTeacher.id,
+ subjectId = rSubject.id
+ ).also {
+ it.lessonTopic = jAttendance.getString("PrzedmiotTemat")
+ it.lessonNumber = jAttendance.getInt("Godzina")
+ }
data.attendanceList.add(attendanceObject)
- if (attendanceObject.type != TYPE_PRESENT) {
+ if (attendanceObject.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
attendanceObject.id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN,
+ profile?.empty ?: false || baseType == TYPE_PRESENT_CUSTOM || baseType == TYPE_UNKNOWN
))
}
}
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
index 42202f4e..25c06945 100644
--- 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
@@ -66,9 +66,9 @@ class IdziennikWebExams(override val data: DataIdziennik,
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 topic = exam.getString("zakres")?.trim() ?: ""
- val lessonList = data.db.timetableDao().getForDateNow(profileId, examDate)
+ val lessonList = data.db.timetableDao().getAllForDateNow(profileId, examDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val eventType = when (exam.getString("rodzaj")?.toLowerCase(Locale.getDefault())) {
@@ -80,17 +80,16 @@ class IdziennikWebExams(override val data: DataIdziennik,
}
val eventObject = Event(
- profileId,
- id,
- examDate,
- startTime,
- topic,
- -1,
- eventType,
- false,
- teacherId,
- subjectId,
- data.teamClass?.id ?: -1
+ profileId = profileId,
+ id = id,
+ date = examDate,
+ time = startTime,
+ topic = topic,
+ color = null,
+ type = eventType,
+ teacherId = teacherId,
+ subjectId = subjectId,
+ teamId = data.teamClass?.id ?: -1
)
data.eventList.add(eventObject)
@@ -99,8 +98,7 @@ class IdziennikWebExams(override val data: DataIdziennik,
Metadata.TYPE_EVENT,
eventObject.id,
profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ profile?.empty ?: false
))
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt
index 562f527c..b7a462f6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetAttachment.kt
@@ -15,7 +15,7 @@ import pl.szczodrzynski.edziennik.utils.Utils
import java.io.File
class IdziennikWebGetAttachment(override val data: DataIdziennik,
- val message: Message,
+ val owner: Any,
val attachmentId: Long,
val attachmentName: String,
val onSuccess: () -> Unit
@@ -25,6 +25,8 @@ class IdziennikWebGetAttachment(override val data: DataIdziennik,
}
init {
+ val message = owner as Message
+
val messageId = "\\[META:([A-z0-9]+);([0-9-]+)]".toRegex().find(message.body ?: "")?.get(2) ?: -1
val targetFile = File(Utils.getStorageDir(), attachmentName)
@@ -34,29 +36,29 @@ class IdziennikWebGetAttachment(override val data: DataIdziennik,
), { 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()
}) { written, _ ->
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/idziennik/data/web/IdziennikWebGetHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomework.kt
new file mode 100644
index 00000000..12d804db
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomework.kt
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-1.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA
+import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK
+import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.getBoolean
+import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.getString
+
+class IdziennikWebGetHomework(override val data: DataIdziennik,
+ val event: EventFull,
+ val onSuccess: () -> Unit
+) : IdziennikWeb(data, null) {
+ companion object {
+ private const val TAG = "IdziennikWebGetHomework"
+ }
+
+ init {
+ webApiGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK, mapOf(
+ "idP" to data.registerId,
+ "idPD" to event.id
+ )) { result ->
+ val json = result.getJsonObject("d") ?: run {
+ data.error(ApiError(TAG, ERROR_IDZIENNIK_WEB_REQUEST_NO_DATA)
+ .withApiResponse(result))
+ return@webApiGet
+ }
+
+ val homework = json.getJsonObject("praca") ?: return@webApiGet
+
+ if (homework.getBoolean("zalacznik", false)) {
+ event.attachmentIds = mutableListOf(event.id)
+ event.attachmentNames = mutableListOf("Załącznik do zadania")
+ }
+ else {
+ event.attachmentIds = mutableListOf()
+ event.attachmentNames = mutableListOf()
+ }
+ event.homeworkBody = homework.getString("tresc")
+
+ data.eventList.add(event)
+ data.eventListReplace = true
+
+ EventBus.getDefault().postSticky(EventGetEvent(event))
+ onSuccess()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt
new file mode 100644
index 00000000..f4a60f98
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetHomeworkAttachment.kt
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-1.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.web
+
+import com.google.gson.JsonObject
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT
+import pl.szczodrzynski.edziennik.data.api.Regexes
+import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
+import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.set
+import pl.szczodrzynski.edziennik.utils.Utils
+import java.io.File
+
+class IdziennikWebGetHomeworkAttachment(override val data: DataIdziennik,
+ val owner: Any,
+ val attachmentId: Long,
+ val attachmentName: String,
+ val onSuccess: () -> Unit
+) : IdziennikWeb(data, null) {
+ companion object {
+ const val TAG = "IdziennikWebGetHomeworkAttachment"
+ }
+
+ init {
+ val homework = owner as Event
+
+ /*val request = Request.Builder()
+ .url("")
+ .build()
+ data.app.http.newCall(request).enqueue(object : Callback {
+ override fun onFailure(call: Call, e: IOException) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withThrowable(e))
+ }
+
+ override fun onResponse(call: Call, response: Response) {
+ val filename = response.header("content-disposition")?.substringAfter("\"")?.substringBeforeLast("\"")
+
+ val file: File = File(Utils.getStorageDir(), filename)
+ val sink = file.sink().buffer()
+ response.body()?.source()?.let {
+ sink.writeAll(it)
+ }
+ sink.close()
+ }
+ })*/
+
+ webGet(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT) { text ->
+ val hiddenFields = JsonObject()
+ Regexes.IDZIENNIK_LOGIN_HIDDEN_FIELDS.findAll(text).forEach {
+ hiddenFields[it[1]] = it[2]
+ }
+
+ webGetFile(TAG, IDZIENNIK_WEB_GET_HOMEWORK_ATTACHMENT, Utils.getStorageDir(), mapOf(
+ "__VIEWSTATE" to hiddenFields.getString("__VIEWSTATE", ""),
+ "__VIEWSTATEGENERATOR" to hiddenFields.getString("__VIEWSTATEGENERATOR", ""),
+ "__EVENTVALIDATION" to hiddenFields.getString("__EVENTVALIDATION", ""),
+ "__EVENTTARGET" to "ctl00\$cphContent\$bt_pobraniePliku",
+ "ctl00\$dxComboUczniowie" to data.registerId,
+ "ctl00\$cphContent\$idPracyDomowej" to attachmentId
+ ), { file ->
+ val event = AttachmentGetEvent(
+ profileId,
+ owner,
+ attachmentId,
+ AttachmentGetEvent.TYPE_FINISHED,
+ file.absolutePath
+ )
+
+ val attachmentDataFile = File(Utils.getStorageDir(), ".${profileId}_${event.ownerId}_${event.attachmentId}")
+ Utils.writeStringToFile(attachmentDataFile, event.fileName)
+
+ homework.attachmentNames = mutableListOf(file.name)
+ data.eventList.add(homework)
+ data.eventListReplace = true
+
+ EventBus.getDefault().postSticky(event)
+ onSuccess()
+
+ }) { written, _ ->
+ val event = AttachmentGetEvent(
+ profileId,
+ owner,
+ attachmentId,
+ AttachmentGetEvent.TYPE_PROGRESS,
+ bytesWritten = written
+ )
+
+ EventBus.getDefault().postSticky(event)
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt
index dfe9fba3..bd1808df 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGetMessage.kt
@@ -10,8 +10,8 @@ import pl.szczodrzynski.edziennik.data.api.IDZIENNIK_WEB_GET_MESSAGE
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.DataIdziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
@@ -50,7 +50,11 @@ class IdziennikWebGetMessage(override val data: DataIdziennik,
message.recipients?.clear()
when (message.type) {
TYPE_RECEIVED -> {
- val recipientObject = MessageRecipientFull(profileId, -1, message.id)
+ val recipientObject = MessageRecipientFull(
+ profileId = profileId,
+ id = -1,
+ messageId = message.id
+ )
val readDateString = it.getString("DataOdczytania")
recipientObject.readDate = if (readDateString.isNullOrBlank()) System.currentTimeMillis()
@@ -67,7 +71,11 @@ class IdziennikWebGetMessage(override val data: DataIdziennik,
val recipientName = recipient.getString("NazwaOdbiorcy") ?: return@forEach
val teacher = data.getTeacherByLastFirst(recipientName)
- val recipientObject = MessageRecipientFull(profileId, teacher.id, message.id)
+ val recipientObject = MessageRecipientFull(
+ profileId = profileId,
+ id = teacher.id,
+ messageId = message.id
+ )
recipientObject.readDate = recipient.getLong("Status") ?: return@forEach
recipientObject.fullName = teacher.fullName
@@ -86,14 +94,14 @@ class IdziennikWebGetMessage(override val data: DataIdziennik,
Metadata.TYPE_MESSAGE,
message.id,
message.seen,
- message.notified,
- message.addedDate
+ message.notified
))
}
- EventBus.getDefault().postSticky(MessageGetEvent(message))
-
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/idziennik/data/web/IdziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebGrades.kt
index b3237c82..90e17401 100644
--- 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
@@ -63,6 +63,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$gradeColor")
}
+ val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
+
val gradeObject = Grade(
profileId = profileId,
id = id,
@@ -76,7 +78,9 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null,
semester = semester,
teacherId = teacher.id,
- subjectId = subject.id)
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
when (grade.getInt("Typ")) {
0 -> {
@@ -100,6 +104,8 @@ class IdziennikWebGrades(override val data: DataIdziennik,
colorInt = Color.parseColor("#$historyColor")
}
+ val addedDate = historyItem.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
+
val historyObject = Grade(
profileId = profileId,
id = gradeObject.id * -1,
@@ -113,19 +119,18 @@ class IdziennikWebGrades(override val data: DataIdziennik,
comment = null,
semester = historyItem.getInt("Semestr") ?: 1,
teacherId = teacher.id,
- subjectId = subject.id)
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
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
+ true
))
}
// update the current grade's value with an average of all historical grades and itself
@@ -147,8 +152,6 @@ class IdziennikWebGrades(override val data: DataIdziennik,
}
}
- val addedDate = grade.getString("Data_wystaw")?.let { Date.fromY_m_d(it).inMillis } ?: System.currentTimeMillis()
-
data.gradeList.add(gradeObject)
data.metadataList.add(
Metadata(
@@ -156,8 +159,7 @@ class IdziennikWebGrades(override val data: DataIdziennik,
Metadata.TYPE_GRADE,
id,
data.profile.empty,
- data.profile.empty,
- addedDate
+ data.profile.empty
))
}
}
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
index 345e7da4..10b4a0c3 100644
--- 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
@@ -52,13 +52,14 @@ class IdziennikWebHomework(override val data: DataIdziennik,
json.getJsonArray("ListK")?.asJsonObjectList()?.forEach { homework ->
val id = homework.getLong("_recordId") ?: return@forEach
val eventDate = Date.fromY_m_d(homework.getString("dataO") ?: return@forEach)
+ val addedDate = Date.fromY_m_d(homework.getString("dataZ") ?: return@forEach)
val subjectName = homework.getString("przed") ?: return@forEach
val subjectId = data.getSubject(subjectName, null, subjectName).id
val teacherName = homework.getString("usr") ?: return@forEach
val teacherId = data.getTeacherByLastFirst(teacherName).id
- val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
+ val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.displayStartTime
- val topic = homework.getString("tytul") ?: ""
+ val topic = homework.getString("tytul")?.trim() ?: ""
val seen = when (profile?.empty) {
true -> true
@@ -67,17 +68,17 @@ class IdziennikWebHomework(override val data: DataIdziennik,
val eventObject = Event(
- profileId,
- id,
- eventDate,
- startTime,
- topic,
- -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)
@@ -86,8 +87,7 @@ class IdziennikWebHomework(override val data: DataIdziennik,
Metadata.TYPE_HOMEWORK,
eventObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
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
index dcc560d5..64108bfd 100644
--- 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
@@ -13,9 +13,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice
-import pl.szczodrzynski.edziennik.data.db.entity.Notice.*
+import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEGATIVE
+import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_NEUTRAL
+import pl.szczodrzynski.edziennik.data.db.entity.Notice.Companion.TYPE_POSITIVE
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonObject
+import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.models.Date
class IdziennikWebNotices(override val data: DataIdziennik,
@@ -53,20 +56,24 @@ class IdziennikWebNotices(override val data: DataIdziennik,
}
val noticeObject = Notice(
- profileId,
- noticeId,
- jNotice.get("Tresc").asString,
- jNotice.get("Semestr").asInt,
- nType,
- rTeacher.id)
+ profileId = profileId,
+ id = noticeId,
+ type = nType,
+ semester = jNotice.get("Semestr").asInt,
+ text = jNotice.getString("Tresc") ?: "",
+ category = null,
+ points = null,
+ teacherId = rTeacher.id,
+ addedDate = addedDate.inMillis
+ )
+
data.noticeList.add(noticeObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_NOTICE,
noticeObject.id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
+ profile?.empty ?: false
))
}
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
index fe5a0156..b23e9f98 100644
--- 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
@@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.idziennik.data.IdziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Grade
+import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_DESCRIPTIVE
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_PROPOSED
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_YEAR_PROPOSED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
@@ -20,7 +21,6 @@ import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
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,
override val lastSync: Long?,
@@ -39,77 +39,105 @@ class IdziennikWebProposedGrades(override val data: DataIdziennik,
.withApiResponse(result))
return@webApiGet
}
+ val manager = data.app.gradesManager
json.getJsonArray("Przedmioty")?.asJsonObjectList()?.forEach { subject ->
val subjectName = subject.getString("Przedmiot") ?: return@forEach
val subjectObject = data.getSubject(subjectName, null, subjectName)
val semester1Proposed = subject.getString("OcenaSem1") ?: ""
- val semester1Value = getWordGradeValue(semester1Proposed)
+ val semester1Value = manager.getGradeValue(semester1Proposed)
val semester1Id = subjectObject.id * (-100) - 1
+ val semester1Type =
+ if (semester1Value == 0f) TYPE_DESCRIPTIVE
+ else TYPE_SEMESTER1_PROPOSED
+ val semester1Name = when {
+ semester1Value == 0f -> " "
+ semester1Value % 1.0f == 0f -> semester1Value.toInt().toString()
+ else -> semester1Value.toString()
+ }
+ val semester1Color =
+ if (semester1Value == 0f) 0xff536dfe.toInt()
+ else -1
val semester2Proposed = subject.getString("OcenaSem2") ?: ""
- val semester2Value = getWordGradeValue(semester2Proposed)
+ val semester2Value = manager.getGradeValue(semester2Proposed)
val semester2Id = subjectObject.id * (-100) - 2
+ val semester2Type =
+ if (semester2Value == 0f) TYPE_DESCRIPTIVE
+ else TYPE_YEAR_PROPOSED
+ val semester2Name = when {
+ semester2Value == 0f -> " "
+ semester2Value % 1.0f == 0f -> semester2Value.toInt().toString()
+ else -> semester2Value.toString()
+ }
+ val semester2Color =
+ if (semester2Value == 0f) 0xffff4081.toInt()
+ else -1
if (semester1Proposed != "") {
- val gradeObject = Grade(
- profileId = profileId,
- id = semester1Id,
- name = semester1Value.toString(),
- type = TYPE_SEMESTER1_PROPOSED,
- value = semester1Value.toFloat(),
- weight = 0f,
- color = -1,
- category = null,
- description = null,
- comment = null,
- semester = 1,
- teacherId = -1,
- subjectId = subjectObject.id
- )
-
- 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 = profileId,
- id = semester2Id,
- name = semester2Value.toString(),
- type = TYPE_YEAR_PROPOSED,
- value = semester2Value.toFloat(),
- weight = 0f,
- color = -1,
- category = null,
- description = null,
- comment = null,
- semester = 2,
- teacherId = -1,
- subjectId = subjectObject.id
- )
-
val addedDate = if (data.profile.empty)
data.profile.dateSemester1Start.inMillis
else
System.currentTimeMillis()
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = semester1Id,
+ name = semester1Name,
+ type = semester1Type,
+ value = semester1Value,
+ weight = 0f,
+ color = semester1Color,
+ category = if (semester1Value == 0f) "Ocena opisowa semestralna" else null,
+ description = if (semester1Value == 0f) semester1Proposed else null,
+ comment = null,
+ semester = 1,
+ teacherId = -1,
+ subjectId = subjectObject.id,
+ addedDate = addedDate
+ )
+
data.gradeList.add(gradeObject)
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_GRADE,
gradeObject.id,
profile.empty,
+ profile.empty
+ ))
+ }
+
+ if (semester2Proposed != "") {
+ val addedDate = if (data.profile.empty)
+ data.profile.dateSemester2Start.inMillis
+ else
+ System.currentTimeMillis()
+
+ val gradeObject = Grade(
+ profileId = profileId,
+ id = semester2Id,
+ name = semester2Name,
+ type = semester2Type,
+ value = semester2Value,
+ weight = 0f,
+ color = semester2Color,
+ category = if (semester2Value == 0f) "Ocena opisowa końcoworoczna" else null,
+ description = if (semester2Value == 0f) semester2Proposed else null,
+ comment = null,
+ semester = 2,
+ teacherId = -1,
+ subjectId = subjectObject.id,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_GRADE,
+ gradeObject.id,
profile.empty,
- addedDate
+ profile.empty
))
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt
index 9a997a32..343ebcac 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebSendMessage.kt
@@ -57,9 +57,9 @@ class IdziennikWebSendMessage(override val data: DataIdziennik,
}
IdziennikApiMessagesSent(data, null) {
- val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
+ 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, metadata?.addedDate)
+ val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/data/web/IdziennikWebTimetable.kt
index 066346cd..e7d293c4 100644
--- 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
@@ -165,8 +165,7 @@ class IdziennikWebTimetable(override val data: DataIdziennik,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
}
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
index 892c12c8..1a07c609 100644
--- 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
@@ -89,7 +89,7 @@ class IdziennikFirstLogin(val data: DataIdziennik, val onSuccess: () -> Unit) {
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/idziennik/login/IdziennikLoginWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/idziennik/login/IdziennikLoginWeb.kt
index e15f9410..a2fd4d03 100644
--- 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
@@ -70,13 +70,21 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
data.webSelectedRegister = registerId
}
+ // for profiles created after archiving
+ data.schoolYearId = Regexes.IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR.find(text)?.let {
+ it[1].toIntOrNull()
+ } ?: data.schoolYearId
+ data.profile?.studentClassName = Regexes.IDZIENNIK_LOGIN_FIRST_STUDENT.findAll(text)
+ .firstOrNull { it[1].toIntOrNull() == data.registerId }
+ ?.let { "${it[5]} ${it[6]}" } ?: data.profile?.studentClassName
+
data.profile?.let { profile ->
Regexes.IDZIENNIK_WEB_LUCKY_NUMBER.find(text)?.also {
val number = it[1].toIntOrNull() ?: return@also
val luckyNumberObject = LuckyNumber(
- data.profileId,
- Date.getToday(),
- number
+ profileId = data.profileId,
+ date = Date.getToday(),
+ number = number
)
data.luckyNumberList.add(luckyNumberObject)
@@ -86,8 +94,7 @@ class IdziennikLoginWeb(val data: DataIdziennik, val onSuccess: () -> Unit) {
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
}
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 80a85a9f..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
@@ -120,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.
@@ -129,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.
@@ -138,8 +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); mApiCode = value }
+ set(value) { profile?.putStudentData("accountCode", value); mApiCode = value }
/**
* A JST login PIN.
* Used only during first login in JST mode.
@@ -147,8 +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); mApiPin = value }
+ set(value) { profile?.putStudentData("accountPin", value); mApiPin = value }
/**
* A Synergia API access token.
@@ -277,4 +275,10 @@ class DataLibrus(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
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 0a1ed593..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
@@ -13,7 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.Librus
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.data.messages.LibrusMessagesGetMessage
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.LibrusSynergiaMarkAllAnnouncementsAsRead
+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.LibrusLogin
import pl.szczodrzynski.edziennik.data.api.interfaces.EdziennikCallback
@@ -24,6 +24,7 @@ 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
@@ -88,9 +89,8 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun getMessage(message: MessageFull) {
login(LOGIN_METHOD_LIBRUS_MESSAGES) {
- LibrusMessagesGetMessage(data, message) {
- completed()
- }
+ if (data.messagesLoginSuccessful) LibrusMessagesGetMessage(data, message) { completed() }
+ else LibrusSynergiaGetMessage(data, message) { completed() }
}
}
@@ -118,11 +118,22 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
- login(LOGIN_METHOD_LIBRUS_MESSAGES) {
- LibrusMessagesGetAttachment(data, message, attachmentId, attachmentName) {
- 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()
}
}
@@ -134,6 +145,14 @@ class Librus(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
}
+ 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")
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 98caab4e..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
@@ -50,6 +50,8 @@ 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
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/LibrusData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusData.kt
index bf1fdab4..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,6 +8,7 @@ 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.entity.Message
@@ -201,17 +202,27 @@ class LibrusData(val data: DataLibrus, val onSuccess: () -> Unit) {
data.startProgress(R.string.edziennik_progress_endpoint_student_info)
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)
+ }
/**
* MESSAGES
*/
ENDPOINT_LIBRUS_MESSAGES_RECEIVED -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
- LibrusMessagesGetList(data, type = Message.TYPE_RECEIVED, lastSync = lastSync, 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, lastSync = lastSync, 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(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 bccaa1f9..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
@@ -252,10 +252,11 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
.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?) {
@@ -291,9 +292,14 @@ open class LibrusMessages(open val data: DataLibrus, open val lastSync: Long?) {
}
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/LibrusSynergia.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/LibrusSynergia.kt
index e201ca8f..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
@@ -35,7 +35,7 @@ open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
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, open val lastSync: Long?) {
}
}
-
try {
onSuccess(text)
} catch (e: Exception) {
@@ -90,4 +89,44 @@ open class LibrusSynergia(open val data: DataLibrus, open val lastSync: Long?) {
.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
index d40c1a9a..23cfceb4 100644
--- 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
@@ -37,8 +37,7 @@ class LibrusApiAnnouncementMarkAsRead(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT,
announcement.id,
announcement.seen,
- announcement.notified,
- announcement.addedDate
+ 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 8256b859..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
@@ -38,15 +38,17 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
val read = announcement.getBoolean("WasRead") ?: false
val announcementObject = Announcement(
- profileId,
- id,
- subject,
- text,
- startDate,
- endDate,
- teacherId,
- longId
- )
+ 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.setSeenMetadataList.add(Metadata(
@@ -54,8 +56,7 @@ class LibrusApiAnnouncements(override val data: DataLibrus,
Metadata.TYPE_ANNOUNCEMENT,
id,
read,
- profile.empty || read,
- addedDate
+ profile.empty || read
))
}
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 d7cbc00c..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
@@ -26,25 +26,39 @@ class LibrusApiAttendanceTypes(override val data: DataLibrus,
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)
+ 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 3727788d..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
@@ -13,7 +13,6 @@ 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
-import pl.szczodrzynski.edziennik.utils.models.Time
class LibrusApiAttendances(override val data: DataLibrus,
override val lastSync: Long?,
@@ -42,9 +41,9 @@ class LibrusApiAttendances(override val data: DataLibrus,
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[type] ?: null
- val topic = typeObject?.name ?: ""
+
+ val typeId = attendance.getJsonObject("Type")?.getLong("Id") ?: return@forEach
+ val type = data.attendanceTypes[typeId] ?: null
val startTime = data.lessonRanges.get(lessonNo)?.startTime
@@ -52,29 +51,34 @@ class LibrusApiAttendances(override val data: DataLibrus,
data.librusLessons.singleOrNull { it.lessonId == lessonId }
else null
- val attendanceObject = Attendance(
- profileId,
- id,
- teacherId ?: lesson?.teacherId ?: -1,
- lesson?.subjectId ?: -1,
- semester,
- topic,
- lessonDate,
- startTime ?: Time(0, 0, 0),
- typeObject?.type ?: Attendance.TYPE_CUSTOM
- )
-
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
))
}
}
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 5a374ec9..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
@@ -55,7 +55,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null,
semester = 1,
teacherId = -1,
- subjectId = 1
+ subjectId = 1,
+ addedDate = profile.getSemesterStart(1).inMillis
)
data.gradeList.add(semester1StartGradeObject)
@@ -64,8 +65,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
semester1StartGradeObject.id,
true,
- true,
- profile.getSemesterStart(1).inMillis
+ true
))
}
@@ -83,7 +83,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = null,
semester = 2,
teacherId = -1,
- subjectId = 1
+ subjectId = 1,
+ addedDate = profile.getSemesterStart(2).inMillis
)
data.gradeList.add(semester2StartGradeObject)
@@ -92,8 +93,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
semester2StartGradeObject.id,
true,
- true,
- profile.getSemesterStart(2).inMillis
+ true
))
}
@@ -155,7 +155,8 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
comment = if (text != null) description.join(" - ") else null,
semester = semester,
teacherId = teacherId,
- subjectId = 1
+ subjectId = 1,
+ addedDate = addedDate
).apply {
valueMax = valueTo
}
@@ -166,8 +167,7 @@ class LibrusApiBehaviourGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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
index 42e318e0..8cc4f1c1 100644
--- 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
@@ -65,7 +65,8 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = addedDate
)
data.gradeList.add(gradeObject)
@@ -74,8 +75,7 @@ class LibrusApiDescriptiveGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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 a04c2863..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
@@ -35,7 +35,7 @@ class LibrusApiEvents(override val data: DataLibrus,
events?.forEach { event ->
val id = event.getLong("Id") ?: return@forEach
val eventDate = Date.fromY_m_d(event.getString("Date"))
- val topic = event.getString("Content") ?: ""
+ 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
@@ -46,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)
@@ -67,8 +73,7 @@ class LibrusApiEvents(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate
+ profile?.empty ?: false
))
}
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 7ff42fde..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
@@ -79,7 +79,8 @@ class LibrusApiGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = addedDate
)
grade.getJsonObject("Improvement")?.also {
@@ -98,8 +99,7 @@ class LibrusApiGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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 16d66c6f..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
@@ -34,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)
@@ -53,8 +53,7 @@ class LibrusApiHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
+ profile?.empty ?: false
))
}
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 5a52cd69..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
@@ -33,9 +33,9 @@ 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())
@@ -50,8 +50,7 @@ class LibrusApiLuckyNumber(override val data: DataLibrus,
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ profile?.empty ?: false
))
}
}
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 e05cbfd7..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
@@ -46,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)
@@ -61,8 +64,7 @@ class LibrusApiNotices(override val data: DataLibrus,
Metadata.TYPE_NOTICE,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- addedDate.inMillis
+ profile?.empty ?: false
))
}
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
index fae45318..9da2c435 100644
--- 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
@@ -56,7 +56,8 @@ class LibrusApiPointGrades(override val data: DataLibrus,
comment = null,
semester = semester,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = addedDate
).apply {
valueMax = category?.valueTo ?: 0f
}
@@ -67,8 +68,7 @@ class LibrusApiPointGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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 3a58d8e1..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
@@ -39,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)
@@ -59,8 +58,7 @@ class LibrusApiPtMeetings(override val data: DataLibrus,
Metadata.TYPE_EVENT,
id,
profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ profile?.empty ?: false
))
}
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 04c44efb..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
@@ -43,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)
@@ -59,9 +59,8 @@ class LibrusApiTeacherFreeDays(override val data: DataLibrus,
profileId,
Metadata.TYPE_TEACHER_ABSENCE,
id,
- profile?.empty ?: false,
- profile?.empty ?: false,
- System.currentTimeMillis()
+ true,
+ profile?.empty ?: false
))
}
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
index cf020425..7b7c8c6f 100644
--- 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
@@ -60,7 +60,8 @@ class LibrusApiTextGrades(override val data: DataLibrus,
comment = grade.getString("Phrase") /* whatever it is */,
semester = semester,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = addedDate
)
data.gradeList.add(gradeObject)
@@ -69,8 +70,7 @@ class LibrusApiTextGrades(override val data: DataLibrus,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
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 7c1eec61..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
@@ -198,8 +198,7 @@ class LibrusApiTimetables(override val data: DataLibrus,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
data.lessonList.add(lessonObject)
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 f7234891..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,22 +4,12 @@
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.entity.Message
-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 LibrusMessagesGetAttachment(override val data: DataLibrus,
@@ -37,8 +27,6 @@ class LibrusMessagesGetAttachment(override val data: DataLibrus,
override val coroutineContext: CoroutineContext
get() = job + Dispatchers.Default
- private var getAttachmentCheckKeyTries = 0
-
init {
messagesGet(TAG, "GetFileDownloadLink", parameters = mapOf(
"fileId" to attachmentId,
@@ -46,81 +34,8 @@ class LibrusMessagesGetAttachment(override val data: DataLibrus,
"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 f4aa2b3a..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
@@ -12,7 +12,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.ENDPOINT_LIBRUS_MESS
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.entity.*
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
+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
@@ -78,7 +78,7 @@ class LibrusMessagesGetList(override val data: DataLibrus,
val senderId = when (type) {
TYPE_RECEIVED -> recipientId
- else -> -1
+ else -> null
}
val receiverId = when (type) {
@@ -92,13 +92,13 @@ class LibrusMessagesGetList(override val data: DataLibrus,
}
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(
@@ -109,15 +109,19 @@ class LibrusMessagesGetList(override val data: DataLibrus,
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.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
notified,
- notified,
- sentDate
+ notified
))
}
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 824fdc5e..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,8 +9,8 @@ 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.entity.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+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
@@ -102,11 +102,10 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
}
val messageRecipientObject = MessageRecipientFull(
- profileId,
- -1,
- -1,
- readDate,
- messageObject.id
+ profileId = profileId,
+ id = -1,
+ messageId = messageObject.id,
+ readDate = readDate
)
messageRecipientObject.fullName = profile.accountName ?: profile.studentNameLong ?: ""
@@ -132,11 +131,10 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
}
val messageRecipientObject = MessageRecipientFull(
- profileId,
- receiverId,
- -1,
- readDate,
- messageObject.id
+ profileId = profileId,
+ id = receiverId,
+ messageId = messageObject.id,
+ readDate = readDate
)
messageRecipientObject.fullName = "$receiverFirstName $receiverLastName"
@@ -152,14 +150,15 @@ class LibrusMessagesGetMessage(override val data: DataLibrus,
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/LibrusMessagesSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/data/messages/LibrusMessagesSendMessage.kt
index 02215dea..d568135e 100644
--- 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
@@ -48,9 +48,9 @@ class LibrusMessagesSendMessage(override val data: DataLibrus,
}
LibrusMessagesGetList(data, type = Message.TYPE_SENT, lastSync = null) {
- val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.id == id }
+ 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, metadata?.addedDate)
+ 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/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 87cd88cf..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
@@ -42,8 +42,6 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
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()
@@ -60,46 +58,26 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
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()*/
-
- var description = ""
-
- graphElements.forEach { graphEl ->
- graphEl.select("td[title]")?.also {
- val title = it.attr("title")
- val r = "Temat: (.*?)Data udostępnienia: (.*?)Termin wykonania: (.*?)Treść: (.*)"
- .toRegex(RegexOption.DOT_MATCHES_ALL).find(title) ?: return@forEach
- val gTopic = r[1].trim()
- val gAddedDate = Date.fromY_m_d(r[2].trim())
- val gEventDate = Date.fromY_m_d(r[3].trim())
- if (gTopic == topic && gAddedDate == addedDate && gEventDate == eventDate) {
- description = r[4].replace("".toRegex(), "\n").trim()
- return@forEach
- }
- }
- }
-
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)
@@ -108,8 +86,7 @@ class LibrusSynergiaHomework(override val data: DataLibrus,
Metadata.TYPE_HOMEWORK,
id,
seen,
- seen,
- addedDate.inMillis
+ seen
))
}
}
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/firstlogin/LibrusFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/librus/firstlogin/LibrusFirstLogin.kt
index f693c41a..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
@@ -33,7 +33,7 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
val accounts = json.getJsonArray("accounts")
if (accounts == null || accounts.size() < 1) {
- EventBus.getDefault().post(FirstLoginFinishedEvent(listOf(), data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(), data.loginStore))
onSuccess()
return@portalGet
}
@@ -81,7 +81,7 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
profileList.add(profile)
}
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
onSuccess()
}
}
@@ -116,14 +116,15 @@ class LibrusFirstLogin(val data: DataLibrus, val onSuccess: () -> Unit) {
).apply {
studentData["isPremium"] = account?.getBoolean("IsPremium") == true || account?.getBoolean("IsPremiumDemo") == true
studentData["accountId"] = account.getInt("Id") ?: 0
- studentData["accountLogin"] = login
+ 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 fe155abe..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"
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 ba8bcf76..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
@@ -10,6 +10,7 @@ import im.wangchao.mhttp.body.MediaTypeUtils
import im.wangchao.mhttp.callback.TextCallbackHandler
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
@@ -35,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)
}
}
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 166a4ae5..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
@@ -66,7 +66,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
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)
+ 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)
@@ -127,7 +127,7 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
.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))
@@ -146,12 +146,14 @@ class LibrusLoginPortal(val data: DataLibrus, val onSuccess: () -> Unit) {
}
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)
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 5e08f6c4..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
@@ -8,20 +8,17 @@ import com.google.gson.JsonObject
import pl.szczodrzynski.edziennik.App
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.MobidziennikWebGetRecipientList
-import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebSendMessage
+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.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.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
@@ -105,9 +102,9 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
override fun markAllAnnouncementsAsRead() {}
override fun getAnnouncement(announcement: AnnouncementFull) {}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
login(LOGIN_METHOD_MOBIDZIENNIK_WEB) {
- MobidziennikWebGetAttachment(data, message, attachmentId, attachmentName) {
+ MobidziennikWebGetAttachment(data, owner, attachmentId, attachmentName) {
completed()
}
}
@@ -121,6 +118,14 @@ class Mobidziennik(val app: App, val profile: Profile?, val loginStore: LoginSto
}
}
+ 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")
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 d056fc4b..7396ac52 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,7 @@ 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_API2_MAIN = 3000
val MobidziennikFeatures = listOf(
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 be68de4d..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
@@ -6,7 +6,10 @@ 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.entity.Attendance
-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) {
@@ -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 f5cb912b..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
@@ -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/MobidziennikApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiGrades.kt
index 609c895c..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
@@ -79,7 +79,9 @@ class MobidziennikApiGrades(val data: DataMobidziennik, rows: List) {
comment = null,
semester = semester,
teacherId = teacherId,
- subjectId = subjectId)
+ subjectId = subjectId,
+ addedDate = addedDate
+ )
if (data.profile?.empty == true) {
addedDate = data.profile.dateSemester1Start.inMillis
@@ -92,8 +94,7 @@ 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++
}
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 4c5b4e03..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,6 +4,7 @@
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
@@ -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 f1d9aed2..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
@@ -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/MobidziennikApiTeams.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api/MobidziennikApiTeams.kt
index 8fd5677b..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
@@ -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
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 6a7ce02d..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
@@ -8,9 +8,9 @@ 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.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.Lesson
import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.keys
import pl.szczodrzynski.edziennik.singleOrNull
@@ -44,7 +44,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
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]
@@ -97,8 +97,7 @@ class MobidziennikApiTimetable(val data: DataMobidziennik, rows: List) {
Metadata.TYPE_LESSON_CHANGE,
it.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
data.lessonList += it
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 5e1445ec..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
@@ -17,9 +17,9 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
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)
@@ -29,8 +29,7 @@ class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String)
Metadata.TYPE_LUCKY_NUMBER,
luckyNumberObject.date.value.toLong(),
true,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
+ data.profile?.empty ?: false
))
} catch (_: Exception){}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt
index c56c56d9..349c2ea7 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebAttendance.kt
@@ -11,7 +11,13 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBID
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.*
+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
@@ -71,10 +77,25 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
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)) {
@@ -83,67 +104,52 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
}
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()
- Regexes.MOBIDZIENNIK_ATTENDANCE_RANGE.findAll(table).let { ranges ->
- val count = ranges.count()
- // verify the lesson count is the same as dates & entries
- if (count != lessonDates.count() || count != entries.count())
+
+ 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
- ranges.forEach { range ->
- val lessonDate = dateIterator.next()
- val entry = entriesIterator.next()
- if (entry.isBlank())
- return@forEach
- val startTime = Time.fromH_m(range[1])
- val entryIterator = entry.iterator()
- range[2].split(" / ").mapNotNull { Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it) }.forEachIndexed { index, lesson ->
- val topic = lesson[2]
- if (topic.startsWith("Lekcja odwołana: ") || !entryIterator.hasNext())
- return@forEachIndexed
- val subjectName = lesson[1]
- //val team = lesson[3]
- val teacherName = lesson[4].fixName()
+ val startTime = Time.fromH_m(range[1])
- val teacherId = data.teacherList.singleOrNull { it.fullNameLastFirst == teacherName }?.id ?: -1
- val subjectId = data.subjectList.singleOrNull { it.longName == subjectName }?.id ?: -1
-
- val type = when (entryIterator.nextChar()) {
- '.' -> TYPE_PRESENT
- '|' -> TYPE_ABSENT
- '+' -> TYPE_ABSENT_EXCUSED
- 's' -> TYPE_BELATED
- 'z' -> TYPE_RELEASED
- else -> TYPE_PRESENT
- }
- val semester = data.profile?.dateToSemester(lessonDate) ?: 1
-
- val id = lessonDate.combineWith(startTime) / 6L * 10L + (lesson[0].hashCode() and 0xFFFF) + index
-
- val attendanceObject = Attendance(
- data.profileId,
- id,
- teacherId,
- subjectId,
- semester,
- topic,
- lessonDate,
- startTime,
- type)
-
- data.attendanceList.add(attendanceObject)
- if (type != TYPE_PRESENT) {
- data.metadataList.add(
- Metadata(
- data.profileId,
- Metadata.TYPE_ATTENDANCE,
- id,
- data.profile?.empty ?: false,
- data.profile?.empty ?: false,
- System.currentTimeMillis()
- ))
- }
- }
+ range[2].split(" / ").mapNotNull {
+ Regexes.MOBIDZIENNIK_ATTENDANCE_LESSON.find(it)
+ }.forEachIndexed { index, lesson ->
+ processEntry(
+ index,
+ lesson,
+ lessonDate,
+ startTime,
+ entry,
+ types,
+ typeSymbols
+ )
}
}
}
@@ -153,4 +159,97 @@ class MobidziennikWebAttendance(override val data: DataMobidziennik,
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(" - ")
+ //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 isCounted = true
+ val baseType = when (typeSymbol) {
+ "." -> TYPE_PRESENT
+ "|" -> TYPE_ABSENT
+ "+" -> TYPE_ABSENT_EXCUSED
+ "s" -> TYPE_BELATED
+ "z" -> TYPE_RELEASED
+ else -> {
+ isCounted = false
+ when (typeSymbol) {
+ "e" -> TYPE_PRESENT_CUSTOM
+ "en" -> TYPE_ABSENT
+ "ep" -> TYPE_PRESENT_CUSTOM
+ else -> TYPE_UNKNOWN
+ }
+ }
+ }
+ val typeName = types?.get(typeSymbol) ?: ""
+ val typeColor = when (typeSymbol) {
+ "e" -> 0xff673ab7
+ "en" -> 0xffec407a
+ "ep" -> 0xff4caf50
+ else -> null
+ }?.toInt()
+
+ val typeShort = if (isCounted)
+ 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
+ it.isCounted = isCounted
+ }
+
+ 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 9664a68b..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
@@ -61,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)
@@ -90,8 +89,8 @@ 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 */
))
}
}
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 80803441..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,12 +8,14 @@ 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.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 owner: Any,
val attachmentId: Long,
val attachmentName: String,
val onSuccess: () -> Unit
@@ -25,25 +27,40 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
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()
@@ -51,13 +68,13 @@ class MobidziennikWebGetAttachment(override val data: DataMobidziennik,
// 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 5b462e57..105c0943 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
@@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Message
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
+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
@@ -61,19 +61,17 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
}
val recipient = MessageRecipientFull(
- profileId,
- -1,
- -1,
- readDate,
- message.id
+ profileId = profileId,
+ id = -1,
+ messageId = message.id,
+ readDate = readDate
)
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()
@@ -100,11 +98,10 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
}
val recipient = MessageRecipientFull(
- profileId,
- receiverId,
- -1,
- readDate,
- message.id
+ profileId = profileId,
+ id = receiverId,
+ messageId = message.id,
+ readDate = readDate
)
recipient.fullName = teacher?.fullName ?: "?"
@@ -142,14 +139,15 @@ class MobidziennikWebGetMessage(override val data: DataMobidziennik,
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/MobidziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt
index de058c91..9f5fab95 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
@@ -125,7 +125,8 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
comment = null,
semester = gradeSemester,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = gradeAddedDateMillis
)
gradeObject.classAverage = gradeClassAverage
@@ -137,8 +138,7 @@ class MobidziennikWebGrades(override val data: DataMobidziennik,
Metadata.TYPE_GRADE,
gradeObject.id,
profile.empty,
- profile.empty,
- gradeAddedDateMillis
+ profile.empty
))
}
}
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 61c9222e..4e8f900a 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
@@ -10,8 +10,8 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
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.entity.Message
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+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
@@ -54,12 +54,12 @@ 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().fixName()
- senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1
+ senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id
data.messageRecipientList.add(MessageRecipient(profileId, -1, id))
} else {
// TYPE_SENT, so multiple recipients possible
@@ -72,17 +72,17 @@ class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
}
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 expect more than
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 ee5cbd24..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
@@ -52,33 +52,32 @@ class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
val senderEl = item.select("td:eq(2)").first()
val senderName = senderEl.ownText().fixName()
- val senderId = data.teacherList.singleOrNull { it.fullNameLastFirst == senderName }?.id ?: -1
+ 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.messageList.add(message)
data.setSeenMetadataList.add(
Metadata(
profileId,
Metadata.TYPE_MESSAGE,
message.id,
isRead,
- isRead || profile?.empty ?: false,
- addedDate
+ isRead || profile?.empty ?: false
))
}
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
index 8e7123c3..543df329 100644
--- 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
@@ -73,27 +73,26 @@ class MobidziennikWebMessagesSent(override val data: DataMobidziennik,
val addedDate = Date.fromIsoHm(addedDateEl.text())
val message = Message(
- profileId,
- id,
- subject,
- null,
- Message.TYPE_SENT,
- -1,
- -1
+ profileId = profileId,
+ id = id,
+ type = Message.TYPE_SENT,
+ subject = subject,
+ body = null,
+ senderId = null,
+ addedDate = addedDate
)
if (hasAttachments)
- message.setHasAttachments()
+ message.hasAttachments = true
- data.messageIgnoreList.add(message)
+ data.messageList.add(message)
data.setSeenMetadataList.add(
Metadata(
profileId,
Metadata.TYPE_MESSAGE,
message.id,
true,
- true,
- addedDate
+ true
))
}
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
index 074fb83e..89178b8b 100644
--- 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
@@ -43,9 +43,9 @@ class MobidziennikWebSendMessage(override val data: DataMobidziennik,
// TODO create MobidziennikWebMessagesSent and replace this
MobidziennikWebMessagesAll(data, null) {
- val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
+ 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, metadata?.addedDate)
+ 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/firstlogin/MobidziennikFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/firstlogin/MobidziennikFirstLogin.kt
index 4857bd09..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
@@ -85,7 +85,7 @@ class MobidziennikFirstLogin(val data: DataMobidziennik, val onSuccess: () -> Un
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/podlasie/DataPodlasie.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/DataPodlasie.kt
new file mode 100644
index 00000000..d117c139
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/DataPodlasie.kt
@@ -0,0 +1,119 @@
+/*
+ * 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)
+
+ fun getSubject(name: String): Subject {
+ val id = name.crc32()
+ return subjectList.singleOrNull { it.id == id } ?: run {
+ val subject = Subject(profileId, id, name, name)
+ subjectList.put(id, subject)
+ subject
+ }
+ }
+
+ fun getTeacher(firstName: String, lastName: String): Teacher {
+ val name = "$firstName $lastName".fixName()
+ return teacherList.singleOrNull { it.fullName == name } ?: run {
+ val id = name.crc32()
+ val teacher = Teacher(profileId, id, firstName, lastName)
+ teacherList.put(id, teacher)
+ teacher
+ }
+ }
+
+ fun getTeam(name: String? = null): Team {
+ if (name == "cała klasa" || name == null) return teamClass ?: run {
+ val id = className!!.crc32()
+ val teamCode = "$schoolShortName:$className"
+ val team = Team(profileId, id, className, Team.TYPE_CLASS, teamCode, -1)
+ teamList.put(id, team)
+ return team
+ } else {
+ val id = name.crc32()
+ val teamCode = "$schoolShortName:$name"
+ val team = Team(profileId, id, name, Team.TYPE_VIRTUAL, teamCode, -1)
+ teamList.put(id, team)
+ return team
+ }
+ }
+}
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..7c4575aa
--- /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(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..d5696567
--- /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) {
+ init {
+ rows.forEach { grade ->
+ val id = grade.getLong("ExternalId") ?: return@forEach
+ val name = grade.getString("Mark") ?: return@forEach
+ val value = data.app.gradesManager.getGradeValue(name)
+ val weight = grade.getFloat("Weight") ?: 0f
+ val includeToAverage = grade.getInt("IncludeToAverage") != 0
+ val color = grade.getString("Color")?.let { Color.parseColor(it) } ?: -1
+ val category = grade.getString("Category") ?: ""
+ val comment = grade.getString("Comment") ?: ""
+ val semester = grade.getString("TermShortcut")?.length ?: data.currentSemester
+
+ val teacherFirstName = grade.getString("TeacherFirstName") ?: return@forEach
+ val teacherLastName = grade.getString("TeacherLastName") ?: return@forEach
+ val teacher = data.getTeacher(teacherFirstName, teacherLastName)
+
+ val subjectName = grade.getString("SchoolSubject") ?: return@forEach
+ val subject = data.getSubject(subjectName)
+
+ val addedDate = grade.getString("ReceivedDate")?.let { Date.fromY_m_d(it).inMillis }
+ ?: System.currentTimeMillis()
+
+ val gradeObject = Grade(
+ profileId = data.profileId,
+ id = id,
+ name = name,
+ type = Grade.TYPE_NORMAL,
+ value = value,
+ weight = if (includeToAverage) weight else 0f,
+ color = color,
+ category = category,
+ description = null,
+ comment = comment,
+ semester = semester,
+ teacherId = teacher.id,
+ subjectId = subject.id,
+ addedDate = addedDate
+ )
+
+ data.gradeList.add(gradeObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_GRADE,
+ id,
+ data.profile?.empty ?: false,
+ data.profile?.empty ?: false
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Grades.allWithType(Grade.TYPE_NORMAL))
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiHomework.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiHomework.kt
new file mode 100644
index 00000000..6ab53328
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiHomework.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-14
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import com.google.gson.JsonObject
+import pl.szczodrzynski.edziennik.crc32
+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.get
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class PodlasieApiHomework(val data: DataPodlasie, val rows: List) {
+ init {
+ rows.reversed().forEach { homework ->
+ val id = homework.getString("ExternalId")?.crc32() ?: return@forEach
+ val topic = homework.getString("Title")?.replace(""", "\"") ?: ""
+ val description = homework.getString("Message")?.replace(""", "\"") ?: ""
+ val date = Date.getToday()
+ val addedDate = System.currentTimeMillis()
+
+ val eventObject = Event(
+ profileId = data.profileId,
+ id = id,
+ date = date,
+ time = null,
+ topic = topic,
+ color = null,
+ type = Event.TYPE_HOMEWORK,
+ teacherId = -1,
+ subjectId = -1,
+ teamId = data.teamClass?.id ?: -1,
+ addedDate = addedDate
+ ).apply {
+ homeworkBody = description
+ }
+
+ eventObject.attachmentIds = mutableListOf()
+ eventObject.attachmentNames = mutableListOf()
+ homework.getString("Attachments")?.split(',')?.onEach { url ->
+ val filename = "&filename=(.*?)&".toRegex().find(url)?.get(1) ?: return@onEach
+ val ext = "&ext=(.*?)&".toRegex().find(url)?.get(1) ?: return@onEach
+ eventObject.attachmentIds?.add(url.crc32())
+ eventObject.attachmentNames?.add("$filename.$ext:$url")
+ }
+
+ data.eventList.add(eventObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_HOMEWORK,
+ id,
+ data.profile?.empty ?: false,
+ data.profile?.empty ?: false
+ ))
+ }
+
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiLuckyNumber.kt
new file mode 100644
index 00000000..725ec727
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiLuckyNumber.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-13
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+class PodlasieApiLuckyNumber(val data: DataPodlasie, val luckyNumber: Int) {
+ init {
+ val luckyNumberObject = LuckyNumber(
+ profileId = data.profileId,
+ date = Date.getToday(),
+ number = luckyNumber
+ )
+
+ data.luckyNumberList.add(luckyNumberObject)
+ data.metadataList.add(
+ Metadata(
+ data.profileId,
+ Metadata.TYPE_LUCKY_NUMBER,
+ luckyNumberObject.date.value.toLong(),
+ true,
+ data.profile?.empty ?: false
+ ))
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiMain.kt
new file mode 100644
index 00000000..6fe77b5c
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiMain.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.api
+
+import pl.szczodrzynski.edziennik.asJsonObjectList
+import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT
+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.PodlasieApi
+import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getJsonArray
+
+class PodlasieApiMain(override val data: DataPodlasie,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit) : PodlasieApi(data, lastSync) {
+ companion object {
+ const val TAG = "PodlasieApiTimetable"
+ }
+
+ init {
+ apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json ->
+ data.getTeam() // Save the class team when it doesn't exist.
+
+ json.getInt("LuckyNumber")?.let { PodlasieApiLuckyNumber(data, it) }
+ json.getJsonArray("Teacher")?.asJsonObjectList()?.let { PodlasieApiTeachers(data, it) }
+ json.getJsonArray("Timetable")?.asJsonObjectList()?.let { PodlasieApiTimetable(data, it) }
+ json.getJsonArray("Marks")?.asJsonObjectList()?.let { PodlasieApiGrades(data, it) }
+ json.getJsonArray("MarkFinal")?.asJsonObjectList()?.let { PodlasieApiFinalGrades(data, it) }
+ json.getJsonArray("News")?.asJsonObjectList()?.let { PodlasieApiEvents(data, it) }
+ json.getJsonArray("Tasks")?.asJsonObjectList()?.let { PodlasieApiHomework(data, it) }
+
+ data.setSyncNext(ENDPOINT_PODLASIE_API_MAIN, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_PODLASIE_API_MAIN)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTeachers.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTeachers.kt
new file mode 100644
index 00000000..ca1fa7b4
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTeachers.kt
@@ -0,0 +1,40 @@
+/*
+ * 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.db.entity.Teacher
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getLong
+import pl.szczodrzynski.edziennik.getString
+
+class PodlasieApiTeachers(val data: DataPodlasie, val rows: List) {
+ init {
+ rows.forEach { teacher ->
+ val id = teacher.getLong("ExternalId") ?: return@forEach
+ val firstName = teacher.getString("FirstName") ?: return@forEach
+ val lastName = teacher.getString("LastName") ?: return@forEach
+ val isEducator = teacher.getInt("Educator") == 1
+
+ val teacherObject = Teacher(
+ profileId = data.profileId,
+ id = id,
+ name = firstName,
+ surname = lastName,
+ loginId = null
+ )
+
+ data.teacherList.put(id, teacherObject)
+
+ val teamClass = data.teamClass
+ if (isEducator && teamClass != null) {
+ data.teamList.put(teamClass.id, teamClass.apply {
+ teacherId = id
+ })
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTimetable.kt
new file mode 100644
index 00000000..a9a12d5d
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/data/api/PodlasieApiTimetable.kt
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+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.Lesson
+import pl.szczodrzynski.edziennik.getInt
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.models.Date
+import pl.szczodrzynski.edziennik.utils.models.Time
+import pl.szczodrzynski.edziennik.utils.models.Week
+
+class PodlasieApiTimetable(val data: DataPodlasie, rows: List) {
+ init {
+ 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)
+
+ val days = mutableListOf()
+ var startDate: Date? = null
+ var endDate: Date? = null
+
+ rows.forEach { lesson ->
+ val date = lesson.getString("Date")?.let { Date.fromY_m_d(it) } ?: return@forEach
+
+ if ((date > weekEnd || date < weekStart) && data.profile?.empty != true) return@forEach
+ if (startDate == null) startDate = date.clone()
+ endDate = date.clone()
+ if (date.value !in days) days += date.value
+
+ val lessonNumber = lesson.getInt("LessonNumber") ?: return@forEach
+ val startTime = lesson.getString("TimeFrom")?.let { Time.fromH_m_s(it) }
+ ?: return@forEach
+ val endTime = lesson.getString("TimeTo")?.let { Time.fromH_m_s(it) } ?: return@forEach
+ val subject = lesson.getString("SchoolSubject")?.let { data.getSubject(it) }
+ ?: return@forEach
+
+ val teacherFirstName = lesson.getString("TeacherFirstName") ?: return@forEach
+ val teacherLastName = lesson.getString("TeacherLastName") ?: return@forEach
+ val teacher = data.getTeacher(teacherFirstName, teacherLastName)
+
+ val team = lesson.getString("Group")?.let { data.getTeam(it) } ?: return@forEach
+ val classroom = lesson.getString("Room")
+
+ Lesson(data.profileId, -1).also {
+ it.type = Lesson.TYPE_NORMAL
+ it.date = date
+ it.lessonNumber = lessonNumber
+ it.startTime = startTime
+ it.endTime = endTime
+ it.subjectId = subject.id
+ it.teacherId = teacher.id
+ it.teamId = team.id
+ it.classroom = classroom
+
+ it.id = it.buildId()
+ data.lessonList += it
+ }
+ }
+
+ if (startDate != null && endDate != null) {
+ if (weekEnd > endDate!!) endDate = weekEnd
+
+ while (startDate!! <= endDate!!) {
+ if (startDate!!.value !in days) {
+ val lessonDate = startDate!!.clone()
+ data.lessonList += Lesson(data.profileId, lessonDate.value.toLong()).apply {
+ type = Lesson.TYPE_NO_LESSONS
+ date = lessonDate
+ }
+ }
+ startDate!!.stepForward(0, 0, 1)
+ }
+ }
+
+ data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd))
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt
new file mode 100644
index 00000000..9b92d541
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/firstlogin/PodlasieFirstLogin.kt
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.firstlogin
+
+import org.greenrobot.eventbus.EventBus
+import pl.szczodrzynski.edziennik.*
+import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_PODLASIE
+import pl.szczodrzynski.edziennik.data.api.PODLASIE_API_USER_ENDPOINT
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.data.PodlasieApi
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login.PodlasieLoginApi
+import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
+
+class PodlasieFirstLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
+ companion object {
+ const val TAG = "PodlasieFirstLogin"
+ }
+
+ private val api = PodlasieApi(data, null)
+
+ init {
+ val loginStoreId = data.loginStore.id
+ val loginStoreType = LOGIN_TYPE_PODLASIE
+
+ PodlasieLoginApi(data) {
+ api.apiGet(TAG, PODLASIE_API_USER_ENDPOINT) { json ->
+ val uuid = json.getString("Uuid")
+ val login = json.getString("Login")
+ val firstName = json.getString("FirstName")
+ val lastName = json.getString("LastName")
+ val studentNameLong = "$firstName $lastName".fixName()
+ val studentNameShort = studentNameLong.getShortName()
+ val schoolName = json.getString("SchoolName")
+ val className = json.getString("SchoolClass")
+ val schoolYear = json.getString("ActualSchoolYear")?.replace(' ', '/')
+ val semester = json.getString("ActualTermShortcut")?.length
+ val apiUrl = json.getString("URL")
+
+ val profile = Profile(
+ loginStoreId,
+ loginStoreId,
+ loginStoreType,
+ studentNameLong,
+ login,
+ studentNameLong,
+ studentNameShort,
+ null
+ ).apply {
+ studentData["studentId"] = uuid
+ studentData["studentLogin"] = login
+ studentData["schoolName"] = schoolName
+ studentData["className"] = className
+ studentData["schoolYear"] = schoolYear
+ studentData["currentSemester"] = semester ?: 1
+ studentData["apiUrl"] = apiUrl
+
+ schoolYear?.split('/')?.get(0)?.toInt()?.let {
+ studentSchoolYearStart = it
+ }
+ studentClassName = className
+ }
+
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(profile), data.loginStore))
+ onSuccess()
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLogin.kt
new file mode 100644
index 00000000..406bb997
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLogin.kt
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login
+
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_PODLASIE_API
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.utils.Utils
+
+class PodlasieLogin(val data: DataPodlasie, val onSuccess: () -> Unit) {
+ companion object {
+ const val TAG = "PodlasieLogin"
+ }
+
+ private var cancelled = false
+
+ init {
+ nextLoginMethod(onSuccess)
+ }
+
+ private fun nextLoginMethod(onSuccess: () -> Unit) {
+ if (data.targetLoginMethodIds.isEmpty()) {
+ onSuccess()
+ return
+ }
+ if (cancelled) {
+ onSuccess()
+ return
+ }
+ useLoginMethod(data.targetLoginMethodIds.removeAt(0)) { usedMethodId ->
+ data.progress(data.progressStep)
+ if (usedMethodId != -1)
+ data.loginMethods.add(usedMethodId)
+ nextLoginMethod(onSuccess)
+ }
+ }
+
+ private fun useLoginMethod(loginMethodId: Int, onSuccess: (usedMethodId: Int) -> Unit) {
+ // this should never be true
+ if (data.loginMethods.contains(loginMethodId)) {
+ onSuccess(-1)
+ return
+ }
+ Utils.d(TAG, "Using login method $loginMethodId")
+ when (loginMethodId) {
+ LOGIN_METHOD_PODLASIE_API -> {
+ data.startProgress(R.string.edziennik_progress_login_podlasie_api)
+ PodlasieLoginApi(data) { onSuccess(loginMethodId) }
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLoginApi.kt
new file mode 100644
index 00000000..6eb70d06
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/podlasie/login/PodlasieLoginApi.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-5-12
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.login
+
+import pl.szczodrzynski.edziennik.data.api.ERROR_LOGIN_DATA_MISSING
+import pl.szczodrzynski.edziennik.data.api.edziennik.podlasie.DataPodlasie
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+
+class PodlasieLoginApi(val data: DataPodlasie, val onSuccess: () -> Unit) {
+ companion object {
+ const val TAG = "PodlasieLoginApi"
+ }
+
+ init { run {
+ if (data.isApiLoginValid()) {
+ onSuccess()
+ } else {
+ data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
+ }
+ }}
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/Template.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/Template.kt
index 9048bbcf..843d36e9 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/Template.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/template/Template.kt
@@ -16,10 +16,10 @@ import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.api.prepare
import pl.szczodrzynski.edziennik.data.api.templateLoginMethods
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
@@ -79,7 +79,7 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
}
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
}
@@ -87,6 +87,10 @@ class Template(val app: App, val profile: Profile?, val loginStore: LoginStore,
}
+ override fun getEvent(eventFull: EventFull) {
+
+ }
+
override fun firstLogin() {
TemplateFirstLogin(data) {
completed()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt
index d326ebd4..4b397f5d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/DataVulcan.kt
@@ -17,9 +17,14 @@ import pl.szczodrzynski.edziennik.values
class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app, profile, loginStore) {
+ fun isWebMainLoginValid() = webExpiryTime-30 > currentTimeUnix()
+ && webAuthCookie.isNotNullNorEmpty()
+ && webHost.isNotNullNorEmpty()
+ && webType.isNotNullNorEmpty()
+ && symbol.isNotNullNorEmpty()
fun isApiLoginValid() = currentSemesterEndDate-30 > currentTimeUnix()
- && apiCertificateKey.isNotNullNorEmpty()
- && apiCertificatePrivate.isNotNullNorEmpty()
+ && apiFingerprint[symbol].isNotNullNorEmpty()
+ && apiPrivateKey[symbol].isNotNullNorEmpty()
&& symbol.isNotNullNorEmpty()
override fun satisfyLoginMethods() {
@@ -40,7 +45,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
id,
name,
Team.TYPE_CLASS,
- "$schoolName:$name",
+ "$schoolCode:$name",
-1
)
teamList.put(id, teamObject)
@@ -48,7 +53,7 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
}
}
- override fun generateUserCode() = "$schoolName:$studentId"
+ override fun generateUserCode() = "$schoolCode:$studentId"
/**
* A UONET+ client symbol.
@@ -59,8 +64,8 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
*/
private var mSymbol: String? = null
var symbol: String?
- get() { mSymbol = mSymbol ?: loginStore.getLoginData("deviceSymbol", null); return mSymbol }
- set(value) { loginStore.putLoginData("deviceSymbol", value); mSymbol = value }
+ get() { mSymbol = mSymbol ?: profile?.getStudentData("symbol", null); return mSymbol }
+ set(value) { profile?.putStudentData("symbol", value); mSymbol = value }
/**
* Group symbol/number of the student's school.
@@ -75,16 +80,26 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
set(value) { profile?.putStudentData("schoolSymbol", value) ?: return; mSchoolSymbol = value }
/**
- * A school ID consisting of the [symbol] and [schoolSymbol].
+ * Short name of the school, used in some places.
+ *
+ * ListaUczniow/JednostkaSprawozdawczaSkrot, e.g. "SP Wilkow"
+ */
+ private var mSchoolShort: String? = null
+ var schoolShort: String?
+ get() { mSchoolShort = mSchoolShort ?: profile?.getStudentData("schoolShort", null); return mSchoolShort }
+ set(value) { profile?.putStudentData("schoolShort", value) ?: return; mSchoolShort = value }
+
+ /**
+ * A school code consisting of the [symbol] and [schoolSymbol].
*
* [symbol]_[schoolSymbol]
*
* e.g. "poznan_000088"
*/
- 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 mSchoolCode: String? = null
+ var schoolCode: String?
+ get() { mSchoolCode = mSchoolCode ?: profile?.getStudentData("schoolName", null); return mSchoolCode }
+ set(value) { profile?.putStudentData("schoolName", value) ?: return; mSchoolCode = value }
/**
* ID of the student.
@@ -124,6 +139,15 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
get() { mStudentSemesterId = mStudentSemesterId ?: profile?.getStudentData("studentSemesterId", 0); return mStudentSemesterId ?: 0 }
set(value) { profile?.putStudentData("studentSemesterId", value) ?: return; mStudentSemesterId = value }
+ private var mSemester1Id: Int? = null
+ var semester1Id: Int
+ get() { mSemester1Id = mSemester1Id ?: profile?.getStudentData("semester1Id", 0); return mSemester1Id ?: 0 }
+ set(value) { profile?.putStudentData("semester1Id", value) ?: return; mSemester1Id = value }
+ private var mSemester2Id: Int? = null
+ var semester2Id: Int
+ get() { mSemester2Id = mSemester2Id ?: profile?.getStudentData("semester2Id", 0); return mSemester2Id ?: 0 }
+ set(value) { profile?.putStudentData("semester2Id", value) ?: return; mSemester2Id = value }
+
/**
* ListaUczniow/OkresNumer, e.g. 1 or 2
*/
@@ -154,45 +178,34 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
* After first login only 3 first characters are stored here.
* This is later used to determine the API URL address.
*/
- private var mApiToken: String? = null
- var apiToken: String?
- get() { mApiToken = mApiToken ?: loginStore.getLoginData("deviceToken", null); return mApiToken }
- set(value) { loginStore.putLoginData("deviceToken", value); mApiToken = value }
+ private var mApiToken: Map? = null
+ var apiToken: Map = mapOf()
+ get() { mApiToken = mApiToken ?: loginStore.getLoginData("apiToken", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiToken ?: mapOf() }
+ set(value) { loginStore.putLoginData("apiToken", app.gson.toJson(value)); mApiToken = value }
/**
* A mobile API registration PIN.
*
* After first login, this is removed and/or set to null.
*/
- private var mApiPin: String? = null
- var apiPin: String?
- get() { mApiPin = mApiPin ?: loginStore.getLoginData("devicePin", null); return mApiPin }
- set(value) { loginStore.putLoginData("devicePin", value); mApiPin = value }
+ private var mApiPin: Map? = null
+ var apiPin: Map = mapOf()
+ get() { mApiPin = mApiPin ?: loginStore.getLoginData("apiPin", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPin ?: mapOf() }
+ set(value) { loginStore.putLoginData("apiPin", app.gson.toJson(value)); mApiPin = value }
- private var mApiCertificateKey: String? = null
- var apiCertificateKey: String?
- get() { mApiCertificateKey = mApiCertificateKey ?: loginStore.getLoginData("certificateKey", null); return mApiCertificateKey }
- set(value) { loginStore.putLoginData("certificateKey", value); mApiCertificateKey = value }
+ private var mApiFingerprint: Map? = null
+ var apiFingerprint: Map = mapOf()
+ get() { mApiFingerprint = mApiFingerprint ?: loginStore.getLoginData("apiFingerprint", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiFingerprint ?: mapOf() }
+ set(value) { loginStore.putLoginData("apiFingerprint", app.gson.toJson(value)); mApiFingerprint = value }
- /**
- * This is not meant for normal usage.
- *
- * It provides a backward compatibility (<4.0) in order
- * to migrate and use private keys instead of PFX.
- */
- private var mApiCertificatePfx: String? = null
- var apiCertificatePfx: String?
- get() { mApiCertificatePfx = mApiCertificatePfx ?: loginStore.getLoginData("certificatePfx", null); return mApiCertificatePfx }
- set(value) { loginStore.putLoginData("certificatePfx", value); mApiCertificatePfx = value }
-
- private var mApiCertificatePrivate: String? = null
- var apiCertificatePrivate: String?
- get() { mApiCertificatePrivate = mApiCertificatePrivate ?: loginStore.getLoginData("certificatePrivate", null); return mApiCertificatePrivate }
- set(value) { loginStore.putLoginData("certificatePrivate", value); mApiCertificatePrivate = value }
+ private var mApiPrivateKey: Map? = null
+ var apiPrivateKey: Map = mapOf()
+ get() { mApiPrivateKey = mApiPrivateKey ?: loginStore.getLoginData("apiPrivateKey", null)?.let { app.gson.fromJson(it, field.toMutableMap()::class.java) }; return mApiPrivateKey ?: mapOf() }
+ set(value) { loginStore.putLoginData("apiPrivateKey", app.gson.toJson(value)); mApiPrivateKey = value }
val apiUrl: String?
get() {
- val url = when (apiToken?.substring(0, 3)) {
+ val url = when (apiToken[symbol]?.substring(0, 3)) {
"3S1" -> "https://lekcjaplus.vulcan.net.pl"
"TA1" -> "https://uonetplus-komunikacja.umt.tarnow.pl"
"OP1" -> "https://uonetplus-komunikacja.eszkola.opolskie.pl"
@@ -217,4 +230,95 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
get() {
return "$apiUrl$schoolSymbol/"
}
+
+ /* __ __ _ ______ _____ _ _
+ \ \ / / | | | ____/ ____| | | (_)
+ \ \ /\ / /__| |__ | |__ | (___ | | ___ __ _ _ _ __
+ \ \/ \/ / _ \ '_ \ | __| \___ \ | | / _ \ / _` | | '_ \
+ \ /\ / __/ |_) | | | ____) | | |___| (_) | (_| | | | | |
+ \/ \/ \___|_.__/ |_| |_____/ |______\___/ \__, |_|_| |_|
+ __/ |
+ |__*/
+ /**
+ * Federation Services login type.
+ * This might be one of: cufs, adfs, adfslight.
+ */
+ var webType: String?
+ get() { mWebType = mWebType ?: loginStore.getLoginData("webType", null); return mWebType }
+ set(value) { loginStore.putLoginData("webType", value); mWebType = value }
+ private var mWebType: String? = null
+
+ /**
+ * Web server providing the federation services login.
+ * If this is present, WEB_MAIN login is considered as available.
+ */
+ var webHost: String?
+ get() { mWebHost = mWebHost ?: loginStore.getLoginData("webHost", null); return mWebHost }
+ set(value) { loginStore.putLoginData("webHost", value); mWebHost = value }
+ private var mWebHost: String? = null
+
+ /**
+ * An ID used in ADFS & ADFSLight login types.
+ */
+ var webAdfsId: String?
+ get() { mWebAdfsId = mWebAdfsId ?: loginStore.getLoginData("webAdfsId", null); return mWebAdfsId }
+ set(value) { loginStore.putLoginData("webAdfsId", value); mWebAdfsId = value }
+ private var mWebAdfsId: String? = null
+
+ /**
+ * A domain override for ADFS Light.
+ */
+ var webAdfsDomain: String?
+ get() { mWebAdfsDomain = mWebAdfsDomain ?: loginStore.getLoginData("webAdfsDomain", null); return mWebAdfsDomain }
+ set(value) { loginStore.putLoginData("webAdfsDomain", value); mWebAdfsDomain = value }
+ private var mWebAdfsDomain: String? = null
+
+ var webIsHttpCufs: Boolean
+ get() { mWebIsHttpCufs = mWebIsHttpCufs ?: loginStore.getLoginData("webIsHttpCufs", false); return mWebIsHttpCufs ?: false }
+ set(value) { loginStore.putLoginData("webIsHttpCufs", value); mWebIsHttpCufs = value }
+ private var mWebIsHttpCufs: Boolean? = null
+
+ var webIsScopedAdfs: Boolean
+ get() { mWebIsScopedAdfs = mWebIsScopedAdfs ?: loginStore.getLoginData("webIsScopedAdfs", false); return mWebIsScopedAdfs ?: false }
+ set(value) { loginStore.putLoginData("webIsScopedAdfs", value); mWebIsScopedAdfs = value }
+ private var mWebIsScopedAdfs: Boolean? = null
+
+ var webEmail: String?
+ get() { mWebEmail = mWebEmail ?: loginStore.getLoginData("webEmail", null); return mWebEmail }
+ set(value) { loginStore.putLoginData("webEmail", value); mWebEmail = value }
+ private var mWebEmail: String? = null
+ var webUsername: String?
+ get() { mWebUsername = mWebUsername ?: loginStore.getLoginData("webUsername", null); return mWebUsername }
+ set(value) { loginStore.putLoginData("webUsername", value); mWebUsername = value }
+ private var mWebUsername: String? = null
+ var webPassword: String?
+ get() { mWebPassword = mWebPassword ?: loginStore.getLoginData("webPassword", null); return mWebPassword }
+ set(value) { loginStore.putLoginData("webPassword", value); mWebPassword = value }
+ private var mWebPassword: String? = null
+
+ /**
+ * Expiry time of a certificate POSTed to a LoginEndpoint of the specific symbol.
+ * If the time passes, the certificate needs to be POSTed again (if valid)
+ * or re-generated.
+ */
+ var webExpiryTime: Long
+ get() { mWebExpiryTime = mWebExpiryTime ?: profile?.getStudentData("webExpiryTime", 0L); return mWebExpiryTime ?: 0L }
+ set(value) { profile?.putStudentData("webExpiryTime", value); mWebExpiryTime = value }
+ private var mWebExpiryTime: Long? = null
+
+ /**
+ * EfebSsoAuthCookie retrieved after posting a certificate
+ */
+ var webAuthCookie: String?
+ get() { mWebAuthCookie = mWebAuthCookie ?: profile?.getStudentData("webAuthCookie", null); return mWebAuthCookie }
+ set(value) { profile?.putStudentData("webAuthCookie", value); mWebAuthCookie = value }
+ private var mWebAuthCookie: String? = null
+
+ /**
+ * Permissions needed to get JSONs from home page
+ */
+ var webPermissions: String?
+ get() { mWebPermissions = mWebPermissions ?: profile?.getStudentData("webPermissions", null); return mWebPermissions }
+ set(value) { profile?.putStudentData("webPermissions", value); mWebPermissions = value }
+ private var mWebPermissions: String? = null
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt
index 4e6def85..9761343c 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/Vulcan.kt
@@ -5,26 +5,31 @@
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan
import com.google.gson.JsonObject
+import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.App
-import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.helper.OneDriveDownloadAttachment
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanData
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiAttachments
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiMessagesChangeStatus
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiSendMessage
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin.VulcanFirstLogin
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLogin
+import pl.szczodrzynski.edziennik.data.api.events.AttachmentGetEvent
+import pl.szczodrzynski.edziennik.data.api.events.EventGetEvent
+import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
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.api.prepareFor
-import pl.szczodrzynski.edziennik.data.api.vulcanLoginMethods
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
import pl.szczodrzynski.edziennik.utils.Utils.d
+import java.io.File
class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, val callback: EdziennikCallback) : EdziennikInterface {
companion object {
@@ -87,8 +92,29 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
override fun getMessage(message: MessageFull) {
login(LOGIN_METHOD_VULCAN_API) {
- VulcanApiMessagesChangeStatus(data, message) {
- completed()
+ if (message.attachmentIds != null) {
+ VulcanApiMessagesChangeStatus(data, message) {
+ completed()
+ }
+ return@login
+ }
+ val list = data.app.db.messageDao().getAllNow(data.profileId)
+ VulcanApiAttachments(data, list, message, MessageFull::class) { _ ->
+ list.forEach {
+ if (it.attachmentIds == null)
+ it.attachmentIds = mutableListOf()
+ data.messageList.add(it)
+ }
+ data.messageListReplace = true
+
+ if (message.seen) {
+ EventBus.getDefault().postSticky(MessageGetEvent(message))
+ completed()
+ return@VulcanApiAttachments
+ }
+ VulcanApiMessagesChangeStatus(data, message) {
+ completed()
+ }
}
}
}
@@ -101,20 +127,67 @@ class Vulcan(val app: App, val profile: Profile?, val loginStore: LoginStore, va
}
}
- override fun markAllAnnouncementsAsRead() {
+ override fun markAllAnnouncementsAsRead() {}
+ override fun getAnnouncement(announcement: AnnouncementFull) {}
+ override fun getRecipientList() {}
+ override fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String) {
+ val fileUrl = attachmentName.substringAfter(":")
+ if (attachmentName == fileUrl) {
+ data.error(ApiError(TAG, ERROR_ONEDRIVE_DOWNLOAD))
+ return
+ }
+
+ OneDriveDownloadAttachment(
+ app,
+ 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 getAnnouncement(announcement: AnnouncementFull) {
-
- }
-
- override fun getAttachment(message: Message, attachmentId: Long, attachmentName: String) {
-
- }
-
- override fun getRecipientList() {
+ override fun getEvent(eventFull: EventFull) {
+ login(LOGIN_METHOD_VULCAN_API) {
+ val list = data.app.db.eventDao().getAllNow(data.profileId).filter { !it.addedManually }
+ VulcanApiAttachments(data, list, eventFull, EventFull::class) { _ ->
+ list.forEach {
+ it.homeworkBody = ""
+ data.eventList.add(it)
+ }
+ data.eventListReplace = true
+ EventBus.getDefault().postSticky(EventGetEvent(eventFull))
+ completed()
+ }
+ }
}
override fun firstLogin() { VulcanFirstLogin(data) { completed() } }
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt
index d1f11822..ab032e0c 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/VulcanFeatures.kt
@@ -19,6 +19,7 @@ const val ENDPOINT_VULCAN_API_NOTICES = 1070
const val ENDPOINT_VULCAN_API_ATTENDANCE = 1080
const val ENDPOINT_VULCAN_API_MESSAGES_INBOX = 1090
const val ENDPOINT_VULCAN_API_MESSAGES_SENT = 1100
+const val ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS = 2010
val VulcanFeatures = listOf(
// timetable
@@ -61,6 +62,13 @@ val VulcanFeatures = listOf(
!data.app.config.sync.tokenVulcanList.contains(data.profileId)
},
+ /**
+ * Lucky number - using WEB Main.
+ */
+ Feature(LOGIN_TYPE_VULCAN, FEATURE_LUCKY_NUMBER, listOf(
+ ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS to LOGIN_METHOD_VULCAN_WEB_MAIN
+ ), listOf(LOGIN_METHOD_VULCAN_WEB_MAIN)).withShouldSync { data -> data.shouldSyncLuckyNumber() },
+
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
ENDPOINT_VULCAN_API_UPDATE_SEMESTER to LOGIN_METHOD_VULCAN_API,
ENDPOINT_VULCAN_API_DICTIONARIES to LOGIN_METHOD_VULCAN_API
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt
index 172be3c0..c500e3e7 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanApi.kt
@@ -106,11 +106,11 @@ open class VulcanApi(open val data: DataVulcan, open val lastSync: Long?) {
Request.builder()
.url(url)
.userAgent(VULCAN_API_USER_AGENT)
- .addHeader("RequestCertificateKey", data.apiCertificateKey)
+ .addHeader("RequestCertificateKey", data.apiFingerprint[data.symbol])
.addHeader("RequestSignatureValue",
try {
signContent(
- data.apiCertificatePrivate ?: "",
+ data.apiPrivateKey[data.symbol] ?: "",
finalPayload.toString()
)
} catch (e: Exception) {e.printStackTrace();""})
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt
index 9ab94c30..491e8ea6 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanData.kt
@@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.*
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web.VulcanWebLuckyNumber
import pl.szczodrzynski.edziennik.utils.Utils
class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
@@ -86,6 +87,10 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
data.startProgress(R.string.edziennik_progress_endpoint_messages_outbox)
VulcanApiMessagesSent(data, lastSync, onSuccess)
}
+ ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
+ VulcanWebLuckyNumber(data, lastSync, onSuccess)
+ }
else -> onSuccess(endpointId)
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt
new file mode 100644
index 00000000..39433657
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/VulcanWebMain.kt
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-17.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data
+
+import com.google.gson.JsonArray
+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.droidsonroids.jspoon.Jspoon
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.isNotNullNorBlank
+import pl.szczodrzynski.edziennik.utils.Utils
+import pl.szczodrzynski.edziennik.utils.models.Date
+import java.io.File
+import java.net.HttpURLConnection
+
+open class VulcanWebMain(open val data: DataVulcan, open val lastSync: Long?) {
+ companion object {
+ const val TAG = "VulcanWebMain"
+ const val WEB_MAIN = 0
+ const val WEB_OLD = 1
+ const val WEB_NEW = 2
+ const val WEB_MESSAGES = 3
+ const val STATE_SUCCESS = 0
+ const val STATE_NO_REGISTER = 1
+ const val STATE_LOGGED_OUT = 2
+ }
+
+ val profileId
+ get() = data.profile?.id ?: -1
+
+ val profile
+ get() = data.profile
+
+ private val certificateAdapter by lazy {
+ Jspoon.create().adapter(CufsCertificate::class.java)
+ }
+
+ fun saveCertificate(xml: String) {
+ val file = File(data.app.filesDir, "cert_"+(data.webUsername ?: data.webEmail)+".xml")
+ file.writeText(xml)
+ }
+
+ fun readCertificate(): String? {
+ val file = File(data.app.filesDir, "cert_"+(data.webUsername ?: data.webEmail)+".xml")
+ if (file.canRead())
+ return file.readText()
+ return null
+ }
+
+ fun parseCertificate(xml: String): CufsCertificate {
+ val xmlParsed = xml
+ .replace("<[a-z]+?:".toRegex(), "<")
+ .replace("[a-z]+?:".toRegex(), "")
+ .replace("\\sxmlns.*?=\".+?\"".toRegex(), "")
+
+ return certificateAdapter.fromHtml(xmlParsed).also {
+ it.xml = xml
+ }
+ }
+
+ fun postCertificate(certificate: CufsCertificate, symbol: String, onResult: (symbol: String, state: Int) -> Unit): Boolean {
+ // check if the certificate is valid
+ if (Date.fromIso(certificate.expiryDate) < System.currentTimeMillis())
+ return false
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (response?.headers()?.get("Location")?.contains("LoginEndpoint.aspx") == true
+ || response?.headers()?.get("Location")?.contains("?logout=true") == true) {
+ onResult(symbol, STATE_LOGGED_OUT)
+ return
+ }
+ if (text?.contains("LoginEndpoint.aspx?logout=true") == true) {
+ onResult(symbol, STATE_NO_REGISTER)
+ return
+ }
+ if (!validateCallback(text, response, jsonResponse = false)) {
+ return
+ }
+ data.webExpiryTime = Date.fromIso(certificate.expiryDate) / 1000L
+ onResult(symbol, STATE_SUCCESS)
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url("https://uonetplus.${data.webHost}/$symbol/LoginEndpoint.aspx")
+ .withClient(data.app.httpLazy)
+ .userAgent(SYSTEM_USER_AGENT)
+ .post()
+ .addParameter("wa", "wsignin1.0")
+ .addParameter("wctx", certificate.targetUrl)
+ .addParameter("wresult", certificate.xml)
+ .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
+ .allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN)
+ .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
+ .allowErrorCode(HttpURLConnection.HTTP_UNAVAILABLE)
+ .allowErrorCode(429)
+ .callback(callback)
+ .build()
+ .enqueue()
+
+ return true
+ }
+
+ fun getStartPage(symbol: String = data.symbol ?: "default", postErrors: Boolean = true, onSuccess: (html: String, schoolSymbols: List) -> Unit) {
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (!validateCallback(text, response, jsonResponse = false) || text == null) {
+ return
+ }
+
+ if (postErrors) {
+ when {
+ text.contains("status absolwenta") -> ERROR_VULCAN_WEB_GRADUATE_ACCOUNT
+ else -> null
+ }?.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withResponse(response)
+ .withApiResponse(text))
+ return
+ }
+ }
+
+ data.webPermissions = Regexes.VULCAN_WEB_PERMISSIONS.find(text)?.let { it[1] }
+
+ val schoolSymbols = mutableListOf()
+ val clientUrl = "://uonetplus-uczen.${data.webHost}/$symbol/"
+ var clientIndex = text.indexOf(clientUrl)
+ var count = 0
+ while (clientIndex != -1 && count < 100) {
+ val startIndex = clientIndex + clientUrl.length
+ val endIndex = text.indexOf('/', startIndex = startIndex)
+ val schoolSymbol = text.substring(startIndex, endIndex)
+ schoolSymbols += schoolSymbol
+ clientIndex = text.indexOf(clientUrl, startIndex = endIndex)
+ count++
+ }
+ schoolSymbols.removeAll {
+ it.toLowerCase() == "default"
+ || !it.matches(Regexes.VULCAN_WEB_SYMBOL_VALIDATE)
+ }
+
+ if (postErrors && schoolSymbols.isEmpty()) {
+ data.error(ApiError(TAG, ERROR_VULCAN_WEB_NO_SCHOOLS)
+ .withResponse(response)
+ .withApiResponse(text))
+ return
+ }
+
+ onSuccess(text, schoolSymbols)
+ }
+
+ override fun onFailure(response: Response?, throwable: Throwable?) {
+ data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
+ .withResponse(response)
+ .withThrowable(throwable))
+ }
+ }
+
+ Request.builder()
+ .url("https://uonetplus.${data.webHost}/$symbol/Start.mvc/Index")
+ .userAgent(SYSTEM_USER_AGENT)
+ .get()
+ .allowErrorCode(HttpURLConnection.HTTP_BAD_REQUEST)
+ .allowErrorCode(HttpURLConnection.HTTP_FORBIDDEN)
+ .allowErrorCode(HttpURLConnection.HTTP_UNAUTHORIZED)
+ .allowErrorCode(HttpURLConnection.HTTP_UNAVAILABLE)
+ .allowErrorCode(429)
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+
+ private fun validateCallback(text: String?, response: Response?, jsonResponse: Boolean = true): Boolean {
+ if (text == null) {
+ data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
+ .withResponse(response))
+ return false
+ }
+
+ if (response?.code() !in 200..302 || (jsonResponse && !text.startsWith("{"))) {
+ when {
+ text.contains("The custom error module") -> ERROR_VULCAN_WEB_429
+ else -> ERROR_VULCAN_WEB_OTHER
+ }.let { errorCode ->
+ data.error(ApiError(TAG, errorCode)
+ .withApiResponse(text)
+ .withResponse(response))
+ return false
+ }
+ }
+
+ val cookies = data.app.cookieJar.getAll(data.webHost ?: "vulcan.net.pl")
+ val authCookie = cookies["EfebSsoAuthCookie"]
+ if ((authCookie == null || authCookie == "null") && data.webAuthCookie != null) {
+ data.app.cookieJar.set(data.webHost ?: "vulcan.net.pl", "EfebSsoAuthCookie", data.webAuthCookie)
+ }
+ else if (authCookie.isNotNullNorBlank() && authCookie != "null" && authCookie != data.webAuthCookie) {
+ data.webAuthCookie = authCookie
+ }
+ return true
+ }
+
+ fun webGetJson(
+ tag: String,
+ webType: Int,
+ endpoint: String,
+ method: Int = POST,
+ parameters: Map = emptyMap(),
+ onSuccess: (json: JsonObject, response: Response?) -> Unit
+ ) {
+ val url = "https://" + when (webType) {
+ WEB_MAIN -> "uonetplus"
+ WEB_OLD -> "uonetplus-opiekun"
+ WEB_NEW -> "uonetplus-uczen"
+ WEB_MESSAGES -> "uonetplus-uzytkownik"
+ else -> "uonetplus"
+ } + ".${data.webHost}/${data.symbol}/$endpoint"
+
+ Utils.d(tag, "Request: Vulcan/WebMain - $url")
+
+ val payload = JsonObject()
+ parameters.map { (name, value) ->
+ when (value) {
+ is JsonObject -> payload.add(name, value)
+ is JsonArray -> payload.add(name, value)
+ is String -> payload.addProperty(name, value)
+ is Int -> payload.addProperty(name, value)
+ is Long -> payload.addProperty(name, value)
+ is Float -> payload.addProperty(name, value)
+ is Char -> payload.addProperty(name, value)
+ is Boolean -> payload.addProperty(name, value)
+ }
+ }
+
+ val callback = object : TextCallbackHandler() {
+ override fun onSuccess(text: String?, response: Response?) {
+ if (!validateCallback(text, response))
+ return
+
+ try {
+ val json = JsonParser().parse(text).asJsonObject
+ onSuccess(json, response)
+ } catch (e: Exception) {
+ data.error(ApiError(tag, EXCEPTION_VULCAN_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(url)
+ .userAgent(SYSTEM_USER_AGENT)
+ .apply {
+ when (method) {
+ GET -> get()
+ POST -> post()
+ }
+ }
+ .setJsonBody(payload)
+ .allowErrorCode(429)
+ .callback(callback)
+ .build()
+ .enqueue()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt
new file mode 100644
index 00000000..a7b2b23b
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttachments.kt
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-6.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api
+
+import pl.szczodrzynski.edziennik.asJsonObjectList
+import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS
+import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.data.db.full.MessageFull
+import pl.szczodrzynski.edziennik.getJsonArray
+import pl.szczodrzynski.edziennik.getLong
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.utils.models.Date
+import kotlin.reflect.KClass
+
+class VulcanApiAttachments(override val data: DataVulcan,
+ val list: List<*>,
+ val owner: Any?,
+ val ownerClass: KClass<*>,
+ val onSuccess: (list: List<*>) -> Unit
+) : VulcanApi(data, null) {
+ companion object {
+ const val TAG = "VulcanApiAttachments"
+ }
+
+ init { run {
+ val endpoint = when (ownerClass) {
+ MessageFull::class -> VULCAN_API_ENDPOINT_MESSAGES_ATTACHMENTS
+ EventFull::class -> VULCAN_API_ENDPOINT_HOMEWORK_ATTACHMENTS
+ else -> null
+ } ?: return@run
+
+ val idName = when (ownerClass) {
+ MessageFull::class -> "IdWiadomosc"
+ EventFull::class -> "IdZadanieDomowe"
+ else -> null
+ } ?: return@run
+
+ val startDate = profile?.getSemesterStart(profile?.currentSemester ?: 1)?.inUnix ?: 0
+ val endDate = Date.getToday().stepForward(0, 1, 0).inUnix
+
+ apiGet(TAG, endpoint, parameters = mapOf(
+ "DataPoczatkowa" to startDate,
+ "DataKoncowa" to endDate,
+ "LoginId" to data.studentLoginId,
+ "IdUczen" to data.studentId
+ )) { json, _ ->
+
+ json.getJsonArray("Data")?.asJsonObjectList()?.forEach { attachment ->
+ val id = attachment.getLong("Id") ?: return@forEach
+ val itemId = attachment.getLong(idName) ?: return@forEach
+ val url = attachment.getString("Url") ?: return@forEach
+ val fileName = "${attachment.getString("NazwaPliku")}:$url"
+
+ list.forEach {
+ if (it is MessageFull
+ && it.profileId == profileId
+ && it.id == itemId
+ && it.attachmentIds?.contains(id) != true) {
+ if (it.attachmentIds == null)
+ it.attachmentIds = mutableListOf()
+ if (it.attachmentNames == null)
+ it.attachmentNames = mutableListOf()
+ it.attachmentIds?.add(id)
+ it.attachmentNames?.add(fileName)
+ }
+
+ if (it is EventFull
+ && it.profileId == profileId
+ && it.id == itemId
+ && it.attachmentIds?.contains(id) != true) {
+ if (it.attachmentIds == null)
+ it.attachmentIds = mutableListOf()
+ if (it.attachmentNames == null)
+ it.attachmentNames = mutableListOf()
+ it.attachmentIds?.add(id)
+ it.attachmentNames?.add(fileName)
+ }
+
+ if (owner is MessageFull
+ && it is MessageFull
+ && owner.profileId == it.profileId
+ && owner.id == it.id) {
+ owner.attachmentIds = it.attachmentIds
+ owner.attachmentNames = it.attachmentNames
+ }
+
+ if (owner is EventFull
+ && it is EventFull
+ && owner.profileId == it.profileId
+ && owner.id == it.id) {
+ owner.attachmentIds = it.attachmentIds
+ owner.attachmentNames = it.attachmentNames
+ }
+ }
+ }
+
+ /*if (owner is MessageFull) {
+ list.forEach {
+ (it as? MessageFull)?.let { message ->
+ data.messageList.add(message)
+ }
+ }
+ data.messageListReplace = true
+ }
+
+ if (owner is EventFull) {
+ list.forEach {
+ (it as? EventFull)?.let { it1 ->
+ it1.homeworkBody = ""
+ data.eventList.add(it1)
+ }
+ }
+ data.eventListReplace = true
+ }*/
+
+ onSuccess(list)
+ }
+ }}
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt
index 2ec240a4..2814a1cf 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiAttendance.kt
@@ -7,8 +7,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_ATTENDANCE
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Attendance
-import pl.szczodrzynski.edziennik.data.db.entity.Attendance.TYPE_PRESENT
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance.Companion.TYPE_PRESENT
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.utils.models.Date
@@ -25,57 +26,85 @@ class VulcanApiAttendance(override val data: DataVulcan,
data.db.attendanceTypeDao().getAllNow(profileId).toSparseArray(data.attendanceTypes) { it.id }
}
- val startDate: String = profile.getSemesterStart(profile.currentSemester).stringY_m_d
- val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
+ val semesterId = data.studentSemesterId
+ val semesterNumber = data.studentSemesterNumber
+ if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
+ getAttendance(profile, semesterId - 1, semesterNumber - 1) {
+ getAttendance(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+ }
+ else {
+ getAttendance(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+
+ } ?: onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) }
+
+ private fun finish() {
+ data.setSyncNext(ENDPOINT_VULCAN_API_ATTENDANCE, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE)
+ }
+
+ private fun getAttendance(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
+ val startDate = profile.getSemesterStart(semesterNumber).stringY_m_d
+ val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d
apiGet(TAG, VULCAN_API_ENDPOINT_ATTENDANCE, parameters = mapOf(
"DataPoczatkowa" to startDate,
"DataKoncowa" to endDate,
"IdOddzial" to data.studentClassId,
"IdUczen" to data.studentId,
- "IdOkresKlasyfikacyjny" to data.studentSemesterId
+ "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ ->
json.getJsonObject("Data")?.getJsonArray("Frekwencje")?.forEach { attendanceEl ->
val attendance = attendanceEl.asJsonObject
- val attendanceCategory = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach)
+ val type = data.attendanceTypes.get(attendance.getLong("IdKategoria") ?: return@forEach)
?: return@forEach
- val type = attendanceCategory.type
-
val id = (attendance.getInt("Dzien") ?: 0) + (attendance.getInt("Numer") ?: 0)
val lessonDateMillis = Date.fromY_m_d(attendance.getString("DzienTekst")).inMillis
val lessonDate = Date.fromMillis(lessonDateMillis)
+ val startTime = data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime
- val lessonSemester = profile.dateToSemester(lessonDate)
+ val lessonSemester = semesterNumber
val attendanceObject = Attendance(
- profileId,
- id.toLong(),
- -1,
- attendance.getLong("IdPrzedmiot") ?: -1,
- lessonSemester,
- attendance.getString("PrzedmiotNazwa") + attendanceCategory.name.let { " - $it" },
- lessonDate,
- data.lessonRanges.get(attendance.getInt("Numer") ?: 0)?.startTime,
- type)
+ profileId = profileId,
+ id = id.toLong(),
+ baseType = type.baseType,
+ typeName = type.typeName,
+ typeShort = type.typeShort,
+ typeSymbol = type.typeSymbol,
+ typeColor = type.typeColor,
+ date = lessonDate,
+ startTime = startTime,
+ semester = lessonSemester,
+ teacherId = -1,
+ subjectId = attendance.getLong("IdPrzedmiot") ?: -1,
+ addedDate = lessonDate.combineWith(startTime)
+ ).also {
+ it.lessonNumber = attendance.getInt("Numer")
+ it.isCounted = it.baseType != Attendance.TYPE_RELEASED
+ }
data.attendanceList.add(attendanceObject)
- if (attendanceObject.type != TYPE_PRESENT) {
+ if (type.baseType != TYPE_PRESENT) {
data.metadataList.add(Metadata(
profileId,
Metadata.TYPE_ATTENDANCE,
attendanceObject.id,
- profile.empty,
- profile.empty,
- attendanceObject.lessonDate.combineWith(attendanceObject.startTime)
+ profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN,
+ profile.empty || type.baseType == Attendance.TYPE_PRESENT_CUSTOM || type.baseType == Attendance.TYPE_UNKNOWN
))
}
}
- data.setSyncNext(ENDPOINT_VULCAN_API_ATTENDANCE, SYNC_ALWAYS)
- onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE)
+ onSuccess()
}
- } ?: onSuccess(ENDPOINT_VULCAN_API_ATTENDANCE) }
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt
index 76f53cf5..2dc9f6bc 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiDictionaries.kt
@@ -114,11 +114,11 @@ class VulcanApiDictionaries(override val data: DataVulcan,
private fun saveAttendanceType(attendanceType: JsonObject) {
val id = attendanceType.getLong("Id") ?: return
- val name = attendanceType.getString("Nazwa") ?: ""
+ val typeName = attendanceType.getString("Nazwa") ?: ""
val absent = attendanceType.getBoolean("Nieobecnosc") ?: false
val excused = attendanceType.getBoolean("Usprawiedliwione") ?: false
- val type = if (absent) {
+ val baseType = if (absent) {
if (excused)
Attendance.TYPE_ABSENT_EXCUSED
else
@@ -137,15 +137,35 @@ class VulcanApiDictionaries(override val data: DataVulcan,
else if (present)
Attendance.TYPE_PRESENT
else
- Attendance.TYPE_CUSTOM
+ Attendance.TYPE_UNKNOWN
+ }
+
+ val (typeColor, typeSymbol) = when (id.toInt()) {
+ 1 -> 0xffffffff to "●" // obecność
+ 2 -> 0xffffa687 to "—" // nieobecność
+ 3 -> 0xfffcc150 to "u" // nieobecność usprawiedliwiona
+ 4 -> 0xffede049 to "s" // spóźnienie
+ 5 -> 0xffbbdd5f to "su" // spóźnienie usprawiedliwione
+ 6 -> 0xffa9c9fd to "ns" // nieobecny z przyczyn szkolnych
+ 7 -> 0xffddbbe5 to "z" // zwolniony
+ 8 -> 0xffffffff to "" // usunięty wpis
+ else -> null to "?"
+ }
+
+ val typeShort = when (id.toInt()) {
+ 6 -> "ns" // nieobecny z przyczyn szkolnych
+ 8 -> "" // usunięty wpis
+ else -> data.app.attendanceManager.getTypeShort(baseType)
}
val attendanceTypeObject = AttendanceType(
profileId,
id,
- name,
- type,
- -1
+ baseType,
+ typeName,
+ typeShort,
+ typeSymbol,
+ typeColor?.toInt()
)
data.attendanceTypes.put(id, attendanceTypeObject)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt
index c55dac5d..6f045828 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiEvents.kt
@@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getBoolean
import pl.szczodrzynski.edziennik.getJsonArray
@@ -31,11 +32,43 @@ class VulcanApiEvents(override val data: DataVulcan,
init { data.profile?.also { profile ->
- val startDate: String = when (profile.empty) {
- true -> profile.getSemesterStart(profile.currentSemester).stringY_m_d
+ val semesterId = data.studentSemesterId
+ val semesterNumber = data.studentSemesterNumber
+ if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
+ getEvents(profile, semesterId - 1, semesterNumber - 1) {
+ getEvents(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+ }
+ else {
+ getEvents(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+
+ } ?: onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) }
+
+ private fun finish() {
+ when (isHomework) {
+ true -> {
+ data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
+ data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
+ }
+ false -> {
+ data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
+ data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
+ }
+ }
+ onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS)
+ }
+
+ private fun getEvents(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
+ val startDate = when (profile.empty) {
+ true -> profile.getSemesterStart(semesterNumber).stringY_m_d
else -> Date.getToday().stepForward(0, -1, 0).stringY_m_d
}
- val endDate: String = profile.getSemesterEnd(profile.currentSemester).stringY_m_d
+ val endDate = profile.getSemesterEnd(semesterNumber).stringY_m_d
val endpoint = when (isHomework) {
true -> VULCAN_API_ENDPOINT_HOMEWORK
@@ -46,7 +79,7 @@ class VulcanApiEvents(override val data: DataVulcan,
"DataKoncowa" to endDate,
"IdOddzial" to data.studentClassId,
"IdUczen" to data.studentId,
- "IdOkresKlasyfikacyjny" to data.studentSemesterId
+ "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ ->
val events = json.getJsonArray("Data")
@@ -57,9 +90,9 @@ class VulcanApiEvents(override val data: DataVulcan,
val eventDate = Date.fromY_m_d(event.getString("DataTekst") ?: return@forEach)
val subjectId = event.getLong("IdPrzedmiot") ?: -1
val teacherId = event.getLong("IdPracownik") ?: -1
- val topic = event.getString("Opis") ?: ""
+ val topic = event.getString("Opis")?.trim() ?: ""
- val lessonList = data.db.timetableDao().getForDateNow(profileId, eventDate)
+ val lessonList = data.db.timetableDao().getAllForDateNow(profileId, eventDate)
val startTime = lessonList.firstOrNull { it.subjectId == subjectId }?.startTime
val type = when (isHomework) {
@@ -72,17 +105,16 @@ class VulcanApiEvents(override val data: DataVulcan,
val teamId = event.getLong("IdOddzial") ?: data.teamClass?.id ?: -1
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
)
data.eventList.add(eventObject)
@@ -91,22 +123,11 @@ class VulcanApiEvents(override val data: DataVulcan,
if (isHomework) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT,
id,
profile.empty,
- profile.empty,
- System.currentTimeMillis()
+ profile.empty
))
}
- when (isHomework) {
- true -> {
- data.toRemove.add(DataRemoveModel.Events.futureWithType(Event.TYPE_HOMEWORK))
- data.setSyncNext(ENDPOINT_VULCAN_API_HOMEWORK, SYNC_ALWAYS)
- }
- false -> {
- data.toRemove.add(DataRemoveModel.Events.futureExceptType(Event.TYPE_HOMEWORK))
- data.setSyncNext(ENDPOINT_VULCAN_API_EVENTS, SYNC_ALWAYS)
- }
- }
- onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS)
+ onSuccess()
}
- } ?: onSuccess(if (isHomework) ENDPOINT_VULCAN_API_HOMEWORK else ENDPOINT_VULCAN_API_EVENTS) }
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt
index f62778fc..9a354ea5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiGrades.kt
@@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_NORMAL
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import java.text.DecimalFormat
import kotlin.math.roundToInt
@@ -27,9 +28,33 @@ class VulcanApiGrades(override val data: DataVulcan,
init { data.profile?.also { profile ->
+ val semesterId = data.studentSemesterId
+ val semesterNumber = data.studentSemesterNumber
+ if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
+ getGrades(profile, semesterId - 1, semesterNumber - 1) {
+ getGrades(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+ }
+ else {
+ getGrades(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+
+ } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES) }
+
+ private fun finish() {
+ data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, TYPE_NORMAL))
+ data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_VULCAN_API_GRADES)
+ }
+
+ private fun getGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_GRADES, parameters = mapOf(
"IdUczen" to data.studentId,
- "IdOkresKlasyfikacyjny" to data.studentSemesterId
+ "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ ->
val grades = json.getJsonArray("Data")
@@ -99,9 +124,10 @@ class VulcanApiGrades(override val data: DataVulcan,
category = category,
description = finalDescription,
comment = null,
- semester = data.studentSemesterNumber,
+ semester = semesterNumber,
teacherId = teacherId,
- subjectId = subjectId
+ subjectId = subjectId,
+ addedDate = addedDate
)
data.gradeList.add(gradeObject)
@@ -110,15 +136,11 @@ class VulcanApiGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE,
id,
profile.empty,
- profile.empty,
- addedDate
-
+ profile.empty
))
}
- data.toRemove.add(DataRemoveModel.Grades.semesterWithType(data.studentSemesterNumber, Grade.TYPE_NORMAL))
- data.setSyncNext(ENDPOINT_VULCAN_API_GRADES, SYNC_ALWAYS)
- onSuccess(ENDPOINT_VULCAN_API_GRADES)
+ onSuccess()
}
- } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES) }
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt
index 3a72c963..b0b7795d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesChangeStatus.kt
@@ -9,7 +9,7 @@ import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_MESSAGES_CHANGE_S
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
@@ -37,8 +37,7 @@ class VulcanApiMessagesChangeStatus(override val data: DataVulcan,
Metadata.TYPE_MESSAGE,
messageObject.id,
true,
- true,
- messageObject.addedDate
+ true
))
messageObject.seen = true
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt
index e78b157e..dea913c5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesInbox.kt
@@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_INBOX
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.*
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.utils.Utils
import pl.szczodrzynski.edziennik.utils.models.Date
import kotlin.text.replace
@@ -44,8 +44,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
val body = message.getString("Tresc") ?: ""
val senderLoginId = message.getString("NadawcaId") ?: return@forEach
- val senderId = data.teacherList
- .singleOrNull { it.loginId == senderLoginId }?.id ?: {
+ val senderId = data.teacherList.singleOrNull { it.loginId == senderLoginId }?.id ?: {
val senderName = message.getString("Nadawca") ?: ""
@@ -60,7 +59,7 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
data.teacherList.put(teacherObject.id, teacherObject)
teacherObject.id
}
- }.invoke() ?: -1
+ }.invoke()
val sentDate = message.getLong("DataWyslaniaUnixEpoch")?.let { it * 1000 }
?: -1
@@ -68,13 +67,13 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
?: -1
val messageObject = Message(
- profileId,
- id,
- subject,
- body.replace("\n", "
"),
- TYPE_RECEIVED,
- senderId,
- -1
+ profileId = profileId,
+ id = id,
+ type = TYPE_RECEIVED,
+ subject = subject,
+ body = body.replace("\n", "
"),
+ senderId = senderId,
+ addedDate = sentDate
)
val messageRecipientObject = MessageRecipient(
@@ -85,15 +84,14 @@ class VulcanApiMessagesInbox(override val data: DataVulcan,
id
)
- data.messageIgnoreList.add(messageObject)
+ data.messageList.add(messageObject)
data.messageRecipientList.add(messageRecipientObject)
data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
readDate > 0,
- readDate > 0,
- sentDate
+ readDate > 0
))
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt
index 7437aab4..94cfdcba 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiMessagesSent.kt
@@ -11,7 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_MESSAGES_SENT
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Message
-import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT
+import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
@@ -92,23 +92,22 @@ class VulcanApiMessagesSent(override val data: DataVulcan,
}
val messageObject = Message(
- profileId,
- id,
- subject,
- body.replace("\n", "
"),
- TYPE_SENT,
- -1,
- -1
+ profileId = profileId,
+ id = id,
+ type = TYPE_SENT,
+ subject = subject,
+ body = body.replace("\n", "
"),
+ senderId = null,
+ addedDate = sentDate
)
- data.messageIgnoreList.add(messageObject)
+ data.messageList.add(messageObject)
data.setSeenMetadataList.add(Metadata(
profileId,
Metadata.TYPE_MESSAGE,
id,
true,
- true,
- sentDate
+ true
))
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt
index b2202981..45155a5b 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiNotices.kt
@@ -11,12 +11,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_API_
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.Notice
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonArray
import pl.szczodrzynski.edziennik.getLong
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.toSparseArray
-import pl.szczodrzynski.edziennik.utils.models.Date
class VulcanApiNotices(override val data: DataVulcan,
override val lastSync: Long?,
@@ -31,6 +31,29 @@ class VulcanApiNotices(override val data: DataVulcan,
data.db.noticeTypeDao().getAllNow(profileId).toSparseArray(data.noticeTypes) { it.id }
}
+ val semesterId = data.studentSemesterId
+ val semesterNumber = data.studentSemesterNumber
+ if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
+ getNotices(profile, semesterId - 1, semesterNumber - 1) {
+ getNotices(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+ }
+ else {
+ getNotices(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+
+ } ?: onSuccess(ENDPOINT_VULCAN_API_NOTICES) }
+
+ private fun finish() {
+ data.setSyncNext(ENDPOINT_VULCAN_API_NOTICES, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_VULCAN_API_NOTICES)
+ }
+
+ private fun getNotices(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_NOTICES, parameters = mapOf(
"IdUczen" to data.studentId,
"IdOkresKlasyfikacyjny" to data.studentSemesterId
@@ -41,15 +64,21 @@ class VulcanApiNotices(override val data: DataVulcan,
val id = notice.getLong("Id") ?: return@forEach
val text = notice.getString("TrescUwagi") ?: return@forEach
val teacherId = notice.getLong("IdPracownik") ?: -1
- val addedDate = Date.fromY_m_d(notice.getString("DataWpisuTekst")).inMillis
+ val addedDate = notice.getLong("DataModyfikacji")?.times(1000) ?: System.currentTimeMillis()
+
+ val categoryId = notice.getLong("IdKategoriaUwag") ?: -1
+ val categoryText = data.noticeTypes[categoryId]?.name ?: ""
val noticeObject = Notice(
- profileId,
- id,
- text,
- profile.currentSemester,
- Notice.TYPE_NEUTRAL,
- teacherId
+ profileId = profileId,
+ id = id,
+ type = Notice.TYPE_NEUTRAL,
+ semester = profile.currentSemester,
+ text = text,
+ category = categoryText,
+ points = null,
+ teacherId = teacherId,
+ addedDate = addedDate
)
data.noticeList.add(noticeObject)
@@ -58,13 +87,11 @@ class VulcanApiNotices(override val data: DataVulcan,
Metadata.TYPE_NOTICE,
id,
profile.empty,
- profile.empty,
- addedDate
+ profile.empty
))
}
- data.setSyncNext(ENDPOINT_VULCAN_API_NOTICES, SYNC_ALWAYS)
- onSuccess(ENDPOINT_VULCAN_API_NOTICES)
+ onSuccess()
}
- } ?: onSuccess(ENDPOINT_VULCAN_API_NOTICES) }
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt
index ee1e250f..e897df92 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiProposedGrades.kt
@@ -13,6 +13,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER1_
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_FINAL
import pl.szczodrzynski.edziennik.data.db.entity.Grade.Companion.TYPE_SEMESTER2_PROPOSED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.getJsonArray
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.utils.Utils
@@ -27,32 +28,54 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
init { data.profile?.also { profile ->
+ val semesterId = data.studentSemesterId
+ val semesterNumber = data.studentSemesterNumber
+ if (semesterNumber == 2 && lastSync ?: 0 < profile.dateSemester1Start.inMillis) {
+ getProposedGrades(profile, semesterId - 1, semesterNumber - 1) {
+ getProposedGrades(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+ }
+ else {
+ getProposedGrades(profile, semesterId, semesterNumber) {
+ finish()
+ }
+ }
+
+ } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) }
+
+ private fun finish() {
+ data.setSyncNext(ENDPOINT_VULCAN_API_GRADES_SUMMARY, 6*HOUR)
+ onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY)
+ }
+
+ private fun getProposedGrades(profile: Profile, semesterId: Int, semesterNumber: Int, onSuccess: () -> Unit) {
apiGet(TAG, VULCAN_API_ENDPOINT_GRADES_PROPOSITIONS, parameters = mapOf(
"IdUczen" to data.studentId,
- "IdOkresKlasyfikacyjny" to data.studentSemesterId
+ "IdOkresKlasyfikacyjny" to semesterId
)) { json, _ ->
val grades = json.getJsonObject("Data")
grades.getJsonArray("OcenyPrzewidywane")?.let {
- processGradeList(it, isFinal = false)
+ processGradeList(it, semesterNumber, isFinal = false)
}
grades.getJsonArray("OcenyKlasyfikacyjne")?.let {
- processGradeList(it, isFinal = true)
+ processGradeList(it, semesterNumber, isFinal = true)
}
- data.setSyncNext(ENDPOINT_VULCAN_API_GRADES_SUMMARY, 6*HOUR)
- onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY)
+ onSuccess()
}
- } ?: onSuccess(ENDPOINT_VULCAN_API_GRADES_SUMMARY) }
+ }
- private fun processGradeList(grades: JsonArray, isFinal: Boolean) {
- grades.asJsonObjectList()?.forEach { grade ->
+ private fun processGradeList(grades: JsonArray, semesterNumber: Int, isFinal: Boolean) {
+ grades.asJsonObjectList().forEach { grade ->
val name = grade.get("Wpis").asString
val value = Utils.getGradeValue(name)
val subjectId = grade.get("IdPrzedmiot").asLong
- val id = subjectId * -100 - data.studentSemesterNumber
+ val id = subjectId * -100 - semesterNumber
val color = Utils.getVulcanGradeColor(name)
@@ -60,7 +83,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
profileId = profileId,
id = id,
name = name,
- type = if (data.studentSemesterNumber == 1) {
+ type = if (semesterNumber == 1) {
if (isFinal) TYPE_SEMESTER1_FINAL else TYPE_SEMESTER1_PROPOSED
} else {
if (isFinal) TYPE_SEMESTER2_FINAL else TYPE_SEMESTER2_PROPOSED
@@ -71,7 +94,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
category = "",
description = null,
comment = null,
- semester = data.studentSemesterNumber,
+ semester = semesterNumber,
teacherId = -1,
subjectId = subjectId
)
@@ -82,8 +105,7 @@ class VulcanApiProposedGrades(override val data: DataVulcan,
Metadata.TYPE_GRADE,
gradeObject.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/vulcan/data/api/VulcanApiSendMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt
index c7f7b29e..8c89b620 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiSendMessage.kt
@@ -52,9 +52,9 @@ class VulcanApiSendMessage(override val data: DataVulcan,
}
VulcanApiMessagesSent(data, null) {
- val message = data.messageIgnoreList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
+ val message = data.messageList.firstOrNull { it.type == Message.TYPE_SENT && it.subject == subject }
val metadata = data.metadataList.firstOrNull { it.thingType == Metadata.TYPE_MESSAGE && it.thingId == messageId }
- val event = MessageSentEvent(data.profileId, message, metadata?.addedDate)
+ val event = MessageSentEvent(data.profileId, message, message?.addedDate)
EventBus.getDefault().postSticky(event)
onSuccess()
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt
index d8899dbf..46b52de5 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiTimetable.kt
@@ -80,7 +80,7 @@ class VulcanApiTimetable(override val data: DataVulcan,
id,
name,
Team.TYPE_VIRTUAL,
- "${data.schoolName}:$name",
+ "${data.schoolCode}:$name",
teacherId ?: oldTeacherId ?: -1
)
data.teamList[id] = team
@@ -184,8 +184,7 @@ class VulcanApiTimetable(override val data: DataVulcan,
Metadata.TYPE_LESSON_CHANGE,
lessonObject.id,
seen,
- seen,
- System.currentTimeMillis()
+ seen
))
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt
index 1f03484c..50fb178a 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/api/VulcanApiUpdateSemester.kt
@@ -60,6 +60,7 @@ class VulcanApiUpdateSemester(override val data: DataVulcan,
data.studentClassId = studentClassId
data.studentSemesterId = studentSemesterId
data.studentSemesterNumber = studentSemesterNumber
+ data.profile.studentData["semester${studentSemesterNumber}Id"] = studentSemesterId
data.currentSemesterEndDate = currentSemesterEndDate
profile.studentClassName = studentClassName
dateSemester1Start?.let {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/HomepageTile.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/HomepageTile.kt
new file mode 100644
index 00000000..4d657ac7
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/HomepageTile.kt
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-20.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web
+
+import com.google.gson.annotations.SerializedName
+
+data class HomepageTile(
+ @SerializedName("Nazwa")
+ val name: String?,
+ @SerializedName("Url")
+ val url: String?,
+ @SerializedName("Zawartosc")
+ val children: List
+)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/VulcanWebLuckyNumber.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/VulcanWebLuckyNumber.kt
new file mode 100644
index 00000000..cbf24c2a
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/data/web/VulcanWebLuckyNumber.kt
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-20.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.web
+
+import pl.szczodrzynski.edziennik.DAY
+import pl.szczodrzynski.edziennik.data.api.VULCAN_WEB_ENDPOINT_LUCKY_NUMBER
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain
+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.getJsonArray
+import pl.szczodrzynski.edziennik.utils.models.Date
+import pl.szczodrzynski.edziennik.utils.models.Time
+import pl.szczodrzynski.edziennik.utils.models.Week
+
+class VulcanWebLuckyNumber(override val data: DataVulcan,
+ override val lastSync: Long?,
+ val onSuccess: (endpointId: Int) -> Unit
+) : VulcanWebMain(data, lastSync) {
+ companion object {
+ const val TAG = "VulcanWebLuckyNumber"
+ }
+
+ init {
+ webGetJson(TAG, WEB_MAIN, VULCAN_WEB_ENDPOINT_LUCKY_NUMBER, parameters = mapOf(
+ "permissions" to data.webPermissions
+ )) { json, _ ->
+ val tiles = json
+ .getJsonArray("data")
+ ?.mapNotNull { data.app.gson.fromJson(it.toString(), HomepageTile::class.java) }
+ ?.flatMap { it.children }
+
+ if (tiles == null) {
+ data.setSyncNext(ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS)
+ return@webGetJson
+ }
+
+ var nextSync = System.currentTimeMillis() + 1* DAY *1000
+
+ tiles.firstOrNull { it.name == data.schoolShort }?.children?.firstOrNull()?.let { tile ->
+ // "Szczęśliwy numer w dzienniku: 16"
+ return@let tile.name?.substringAfterLast(' ')?.toIntOrNull()?.let { number ->
+ // lucky number present
+ val luckyNumberObject = LuckyNumber(
+ profileId,
+ Date.getToday(),
+ number
+ )
+
+ data.luckyNumberList.add(luckyNumberObject)
+ data.metadataList.add(
+ Metadata(
+ profileId,
+ Metadata.TYPE_LUCKY_NUMBER,
+ luckyNumberObject.date.value.toLong(),
+ true,
+ profile?.empty ?: false
+ ))
+ }
+ } ?: {
+ // no lucky number
+ if (Date.getToday().weekDay <= Week.FRIDAY && Time.getNow().hour >= 22) {
+ // working days, after 10PM
+ // consider the lucky number is disabled; sync in 4 days
+ nextSync = System.currentTimeMillis() + 4*DAY*1000
+ }
+ else if (Date.getToday().weekDay <= Week.FRIDAY && Time.getNow().hour < 22) {
+ // working days, before 10PM
+
+ }
+ else {
+ // weekends
+ nextSync = Week.getNearestWeekDayDate(Week.MONDAY).combineWith(Time(5, 0, 0))
+ }
+ }()
+
+ data.setSyncNext(ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS, SYNC_ALWAYS)
+ onSuccess(ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS)
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt
index 291cb37b..ed541c69 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/firstlogin/VulcanFirstLogin.kt
@@ -6,12 +6,15 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.firstlogin
import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.*
-import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_VULCAN
-import pl.szczodrzynski.edziennik.data.api.VULCAN_API_ENDPOINT_STUDENT_LIST
+import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanApi
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.CufsCertificate
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginApi
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login.VulcanLoginWebMain
import pl.szczodrzynski.edziennik.data.api.events.FirstLoginFinishedEvent
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.utils.models.Date
@@ -21,19 +24,97 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
}
private val api = VulcanApi(data, null)
+ private val web = VulcanWebMain(data, null)
private val profileList = mutableListOf()
+ private val loginStoreId = data.loginStore.id
+ private var firstProfileId = loginStoreId
+ private val tryingSymbols = mutableListOf()
init {
- val loginStoreId = data.loginStore.id
- val loginStoreType = LOGIN_TYPE_VULCAN
- var firstProfileId = loginStoreId
+ if (data.loginStore.mode == LOGIN_MODE_VULCAN_WEB) {
+ VulcanLoginWebMain(data) {
+ val xml = web.readCertificate() ?: run {
+ data.error(ApiError(TAG, ERROR_VULCAN_WEB_NO_CERTIFICATE))
+ return@VulcanLoginWebMain
+ }
+ val certificate = web.parseCertificate(xml)
+ if (data.symbol != null && data.symbol != "default") {
+ tryingSymbols += data.symbol ?: "default"
+ }
+ else {
+
+ tryingSymbols += certificate.userInstances
+ }
+
+ checkSymbol(certificate)
+ }
+ }
+ else {
+ registerDevice {
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
+ onSuccess()
+ }
+ }
+ }
+
+ private fun checkSymbol(certificate: CufsCertificate) {
+ if (tryingSymbols.isEmpty()) {
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(profileList, data.loginStore))
+ onSuccess()
+ return
+ }
+
+ val result = web.postCertificate(certificate, tryingSymbols.removeAt(0)) { symbol, state ->
+ when (state) {
+ VulcanWebMain.STATE_NO_REGISTER -> {
+ checkSymbol(certificate)
+ }
+ VulcanWebMain.STATE_LOGGED_OUT -> data.error(ApiError(TAG, ERROR_VULCAN_WEB_LOGGED_OUT))
+ VulcanWebMain.STATE_SUCCESS -> {
+ webRegisterDevice(symbol) {
+ checkSymbol(certificate)
+ }
+ }
+ }
+ }
+
+ // postCertificate returns false if the cert is not valid anymore
+ if (!result) {
+ data.error(ApiError(TAG, ERROR_VULCAN_WEB_CERTIFICATE_EXPIRED)
+ .withApiResponse(certificate.xml))
+ }
+ }
+
+ private fun webRegisterDevice(symbol: String, onSuccess: () -> Unit) {
+ web.getStartPage(symbol, postErrors = false) { _, schoolSymbols ->
+ if (schoolSymbols.isEmpty()) {
+ onSuccess()
+ return@getStartPage
+ }
+ data.symbol = symbol
+ val schoolSymbol = data.schoolSymbol ?: schoolSymbols.firstOrNull()
+ web.webGetJson(TAG, VulcanWebMain.WEB_NEW, "$schoolSymbol/$VULCAN_WEB_ENDPOINT_REGISTER_DEVICE") { result, _ ->
+ val json = result.getJsonObject("data")
+ data.symbol = symbol
+ data.apiToken = data.apiToken.toMutableMap().also {
+ it[symbol] = json.getString("TokenKey")
+ }
+ data.apiPin = data.apiPin.toMutableMap().also {
+ it[symbol] = json.getString("PIN")
+ }
+ registerDevice(onSuccess)
+ }
+ }
+ }
+
+ private fun registerDevice(onSuccess: () -> Unit) {
VulcanLoginApi(data) {
- api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, response ->
+ api.apiGet(TAG, VULCAN_API_ENDPOINT_STUDENT_LIST, baseUrl = true) { json, _ ->
val students = json.getJsonArray("Data")
if (students == null || students.isEmpty()) {
- EventBus.getDefault().post(FirstLoginFinishedEvent(listOf(), data.loginStore))
+ EventBus.getDefault().postSticky(FirstLoginFinishedEvent(listOf(), data.loginStore))
onSuccess()
return@apiGet
}
@@ -42,7 +123,8 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
val student = studentEl.asJsonObject
val schoolSymbol = student.getString("JednostkaSprawozdawczaSymbol") ?: return@forEach
- val schoolName = "${data.symbol}_$schoolSymbol"
+ val schoolShort = student.getString("JednostkaSprawozdawczaSkrot") ?: return@forEach
+ val schoolCode = "${data.symbol}_$schoolSymbol"
val studentId = student.getInt("Id") ?: return@forEach
val studentLoginId = student.getInt("UzytkownikLoginId") ?: return@forEach
val studentClassId = student.getInt("IdOddzial") ?: return@forEach
@@ -80,7 +162,7 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
val profile = Profile(
firstProfileId++,
loginStoreId,
- loginStoreType,
+ LOGIN_TYPE_VULCAN,
studentNameLong,
userLogin,
studentNameLong,
@@ -88,13 +170,17 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
accountName
).apply {
this.studentClassName = studentClassName
+ studentData["symbol"] = data.symbol
+
studentData["studentId"] = studentId
studentData["studentLoginId"] = studentLoginId
studentData["studentClassId"] = studentClassId
studentData["studentSemesterId"] = studentSemesterId
studentData["studentSemesterNumber"] = studentSemesterNumber
+ studentData["semester${studentSemesterNumber}Id"] = studentSemesterId
studentData["schoolSymbol"] = schoolSymbol
- studentData["schoolName"] = schoolName
+ studentData["schoolShort"] = schoolShort
+ studentData["schoolName"] = schoolCode
studentData["currentSemesterEndDate"] = currentSemesterEndDate
}
dateSemester1Start?.let {
@@ -107,7 +193,6 @@ class VulcanFirstLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
profileList.add(profile)
}
- EventBus.getDefault().post(FirstLoginFinishedEvent(profileList, data.loginStore))
onSuccess()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/CufsCertificate.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/CufsCertificate.kt
new file mode 100644
index 00000000..45fc96d2
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/CufsCertificate.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-17.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login
+
+import pl.droidsonroids.jspoon.annotation.Selector
+
+class CufsCertificate {
+ @Selector(value = "EndpointReference Address")
+ var targetUrl: String = ""
+
+ @Selector(value = "Lifetime Created")
+ var createdDate: String = ""
+
+ @Selector(value = "Lifetime Expires")
+ var expiryDate: String = ""
+
+ @Selector(value = "Attribute[AttributeName=UserInstance] AttributeValue")
+ var userInstances: List = listOf()
+
+ var xml = ""
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt
index 4c11caf3..45c0153d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLogin.kt
@@ -6,6 +6,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_API
+import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_VULCAN_WEB_MAIN
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.utils.Utils
@@ -45,6 +46,10 @@ class VulcanLogin(val data: DataVulcan, val onSuccess: () -> Unit) {
}
Utils.d(TAG, "Using login method $loginMethodId")
when (loginMethodId) {
+ LOGIN_METHOD_VULCAN_WEB_MAIN -> {
+ data.startProgress(R.string.edziennik_progress_login_vulcan_web_main)
+ VulcanLoginWebMain(data) { onSuccess(loginMethodId) }
+ }
LOGIN_METHOD_VULCAN_API -> {
data.startProgress(R.string.edziennik_progress_login_vulcan_api)
VulcanLoginApi(data) { onSuccess(loginMethodId) }
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt
index 4385b18a..ec84cd05 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginApi.kt
@@ -10,14 +10,12 @@ import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler
import io.github.wulkanowy.signer.android.getPrivateKeyFromCert
-import pl.szczodrzynski.edziennik.currentTimeUnix
+import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.api.VulcanApiUpdateSemester
import pl.szczodrzynski.edziennik.data.api.models.ApiError
-import pl.szczodrzynski.edziennik.getJsonObject
-import pl.szczodrzynski.edziennik.getString
-import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+import pl.szczodrzynski.edziennik.data.api.szkolny.SzkolnyApi
import pl.szczodrzynski.edziennik.utils.Utils.d
import java.net.HttpURLConnection.HTTP_BAD_REQUEST
import java.util.*
@@ -29,28 +27,19 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
}
init { run {
+ if (data.studentSemesterNumber == 1 && data.semester1Id == 0)
+ data.semester1Id = data.studentSemesterNumber
+ if (data.studentSemesterNumber == 2 && data.semester2Id == 0)
+ data.semester2Id = data.studentSemesterNumber
+
+ copyFromLoginStore()
+
if (data.profile != null && data.isApiLoginValid()) {
onSuccess()
}
else {
- // < v4.0 - PFX to Private Key migration
- if (data.apiCertificatePfx.isNotNullNorEmpty()) {
- try {
- data.apiCertificatePrivate = getPrivateKeyFromCert(
- if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
- data.apiCertificatePfx ?: ""
- )
- data.loginStore.removeLoginData("certificatePfx")
- } catch (e: Throwable) {
- e.printStackTrace()
- } finally {
- onSuccess()
- return@run
- }
- }
-
- if (data.apiCertificateKey.isNotNullNorEmpty()
- && data.apiCertificatePrivate.isNotNullNorEmpty()
+ if (data.apiFingerprint[data.symbol].isNotNullNorEmpty()
+ && data.apiPrivateKey[data.symbol].isNotNullNorEmpty()
&& data.symbol.isNotNullNorEmpty()) {
// (see data.isApiLoginValid())
// the semester end date is over
@@ -58,7 +47,7 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
return@run
}
- if (data.symbol.isNotNullNorEmpty() && data.apiToken.isNotNullNorEmpty() && data.apiPin.isNotNullNorEmpty()) {
+ if (data.symbol.isNotNullNorEmpty() && data.apiToken[data.symbol].isNotNullNorEmpty() && data.apiPin[data.symbol].isNotNullNorEmpty()) {
loginWithToken()
}
else {
@@ -67,6 +56,64 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
}
}}
+ private fun copyFromLoginStore() {
+ data.loginStore.data.apply {
+ // < v4.0 - PFX to Private Key migration
+ if (has("certificatePfx")) {
+ try {
+ val privateKey = getPrivateKeyFromCert(
+ if (data.apiToken[data.symbol]?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
+ getString("certificatePfx") ?: ""
+ )
+ data.apiPrivateKey = mapOf(
+ data.symbol to privateKey
+ )
+ remove("certificatePfx")
+ } catch (e: Throwable) {
+ e.printStackTrace()
+ }
+ }
+
+ // 4.0 - new login form - copy user input to profile
+ if (has("symbol")) {
+ data.symbol = getString("symbol")
+ remove("symbol")
+ }
+
+ // 4.0 - before Vulcan Web impl - migrate from strings to Map of Symbol to String
+ if (has("deviceSymbol")) {
+ data.symbol = getString("deviceSymbol")
+ remove("deviceSymbol")
+ }
+ if (has("certificateKey")) {
+ data.apiFingerprint = data.apiFingerprint.toMutableMap().also {
+ it[data.symbol] = getString("certificateKey")
+ }
+ remove("certificateKey")
+ }
+ if (has("certificatePrivate")) {
+ data.apiPrivateKey = data.apiPrivateKey.toMutableMap().also {
+ it[data.symbol] = getString("certificatePrivate")
+ }
+ remove("certificatePrivate")
+ }
+
+ // map form inputs to the symbol
+ if (has("deviceToken")) {
+ data.apiToken = data.apiToken.toMutableMap().also {
+ it[data.symbol] = getString("deviceToken")
+ }
+ remove("deviceToken")
+ }
+ if (has("devicePin")) {
+ data.apiPin = data.apiPin.toMutableMap().also {
+ it[data.symbol] = getString("devicePin")
+ }
+ remove("devicePin")
+ }
+ }
+ }
+
private fun loginWithToken() {
d(TAG, "Request: Vulcan/Login/Api - ${data.apiUrl}/$VULCAN_API_ENDPOINT_CERTIFICATE")
@@ -118,14 +165,22 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
return
}
- data.apiCertificateKey = cert.getString("CertyfikatKlucz")
- data.apiToken = data.apiToken?.substring(0, 3)
- data.apiCertificatePrivate = getPrivateKeyFromCert(
- if (data.apiToken?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
+ val privateKey = getPrivateKeyFromCert(
+ if (data.apiToken[data.symbol]?.get(0) == 'F') VULCAN_API_PASSWORD_FAKELOG else VULCAN_API_PASSWORD,
cert.getString("CertyfikatPfx") ?: ""
)
+
+ data.apiFingerprint = data.apiFingerprint.toMutableMap().also {
+ it[data.symbol] = cert.getString("CertyfikatKlucz")
+ }
+ data.apiToken = data.apiToken.toMutableMap().also {
+ it[data.symbol] = it[data.symbol]?.substring(0, 3)
+ }
+ data.apiPrivateKey = data.apiPrivateKey.toMutableMap().also {
+ it[data.symbol] = privateKey
+ }
data.loginStore.removeLoginData("certificatePfx")
- data.loginStore.removeLoginData("devicePin")
+ data.loginStore.removeLoginData("apiPin")
onSuccess()
}
@@ -136,14 +191,33 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
}
}
+ val deviceId = data.app.deviceId.padStart(16, '0')
+ val loginStoreId = data.loginStore.id.toString(16).padStart(4, '0')
+ val symbol = data.symbol?.crc16()?.toString(16)?.take(2) ?: "00"
+ val uuid =
+ deviceId.substring(0..7) +
+ "-" + deviceId.substring(8..11) +
+ "-" + deviceId.substring(12..15) +
+ "-" + loginStoreId +
+ "-" + symbol + "6f72616e7a"
+
+ val deviceNameSuffix = " - nie usuwać"
+
+ val szkolnyApi = SzkolnyApi(data.app)
+ val firebaseToken = szkolnyApi.runCatching({
+ getFirebaseToken("vulcan")
+ }, onError = {
+ // screw errors
+ }) ?: data.app.config.sync.tokenVulcan
+
Request.builder()
.url("${data.apiUrl}$VULCAN_API_ENDPOINT_CERTIFICATE")
.userAgent(VULCAN_API_USER_AGENT)
.addHeader("RequestMobileType", "RegisterDevice")
- .addParameter("PIN", data.apiPin)
- .addParameter("TokenKey", data.apiToken)
- .addParameter("DeviceId", UUID.randomUUID().toString())
- .addParameter("DeviceName", VULCAN_API_DEVICE_NAME)
+ .addParameter("PIN", data.apiPin[data.symbol])
+ .addParameter("TokenKey", data.apiToken[data.symbol])
+ .addParameter("DeviceId", uuid)
+ .addParameter("DeviceName", VULCAN_API_DEVICE_NAME.take(50 - deviceNameSuffix.length) + deviceNameSuffix)
.addParameter("DeviceNameUser", "")
.addParameter("DeviceDescription", "")
.addParameter("DeviceSystemType", "Android")
@@ -154,6 +228,7 @@ class VulcanLoginApi(val data: DataVulcan, val onSuccess: () -> Unit) {
.addParameter("AppVersion", VULCAN_API_APP_VERSION)
.addParameter("RemoteMobileAppVersion", VULCAN_API_APP_VERSION)
.addParameter("RemoteMobileAppName", VULCAN_API_APP_NAME)
+ .addParameter("FirebaseTokenKey", firebaseToken ?: "")
.postJson()
.allowErrorCode(HTTP_BAD_REQUEST)
.callback(callback)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt
new file mode 100644
index 00000000..467beea3
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/vulcan/login/VulcanLoginWebMain.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-16.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.login
+
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.data.api.*
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
+import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanWebMain
+import pl.szczodrzynski.edziennik.data.api.models.ApiError
+import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.isNotNullNorEmpty
+import pl.szczodrzynski.edziennik.utils.models.Date
+import pl.szczodrzynski.fslogin.FSLogin
+import pl.szczodrzynski.fslogin.realm.CufsRealm
+
+class VulcanLoginWebMain(val data: DataVulcan, val onSuccess: () -> Unit) {
+ companion object {
+ private const val TAG = "VulcanLoginWebMain"
+ }
+
+ private val web by lazy { VulcanWebMain(data, null) }
+
+ init { run {
+ copyFromLoginStore()
+
+ if (data.profile != null && data.isWebMainLoginValid()) {
+ onSuccess()
+ }
+ else {
+ if (data.symbol.isNotNullNorEmpty()
+ && data.webType.isNotNullNorEmpty()
+ && data.webHost.isNotNullNorEmpty()
+ && (data.webEmail.isNotNullNorEmpty() || data.webUsername.isNotNullNorEmpty())
+ && data.webPassword.isNotNullNorEmpty()) {
+ try {
+ val success = loginWithCredentials()
+ if (!success)
+ data.error(ApiError(TAG, ERROR_VULCAN_WEB_DATA_MISSING))
+ } catch (e: Exception) {
+ data.error(ApiError(TAG, EXCEPTION_VULCAN_WEB_LOGIN)
+ .withThrowable(e))
+ }
+ }
+ else {
+ data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
+ }
+ }
+ }}
+
+ private fun copyFromLoginStore() {
+ data.loginStore.data.apply {
+ // 4.0 - new login form - copy user input to profile
+ if (has("symbol")) {
+ data.symbol = getString("symbol")
+ remove("symbol")
+ }
+ }
+ }
+
+ private fun loginWithCredentials(): Boolean {
+ val realm = when (data.webType) {
+ "cufs" -> CufsRealm(
+ host = data.webHost ?: return false,
+ symbol = data.symbol ?: "default",
+ httpCufs = data.webIsHttpCufs
+ )
+ "adfs" -> CufsRealm(
+ host = data.webHost ?: return false,
+ symbol = data.symbol ?: "default",
+ httpCufs = data.webIsHttpCufs
+ ).toAdfsRealm(id = data.webAdfsId ?: return false)
+ "adfslight" -> CufsRealm(
+ host = data.webHost ?: return false,
+ symbol = data.symbol ?: "default",
+ httpCufs = data.webIsHttpCufs
+ ).toAdfsLightRealm(
+ id = data.webAdfsId ?: return false,
+ domain = data.webAdfsDomain ?: "adfslight",
+ isScoped = data.webIsScopedAdfs
+ )
+ else -> return false
+ }
+
+ val certificate = web.readCertificate()?.let { web.parseCertificate(it) }
+ if (certificate != null && Date.fromIso(certificate.expiryDate) > System.currentTimeMillis()) {
+ useCertificate(certificate)
+ return true
+ }
+
+ val fsLogin = FSLogin(data.app.http, debug = App.debugMode)
+ fsLogin.performLogin(
+ realm = realm,
+ username = data.webUsername ?: data.webEmail ?: return false,
+ password = data.webPassword ?: return false,
+ onSuccess = { fsCertificate ->
+ web.saveCertificate(fsCertificate.wresult)
+ useCertificate(web.parseCertificate(fsCertificate.wresult))
+ },
+ onFailure = { errorText ->
+ // TODO
+ data.error(ApiError(TAG, 0).withThrowable(RuntimeException(errorText)))
+ }
+ )
+
+ return true
+ }
+
+ private fun useCertificate(certificate: CufsCertificate) {
+ // auto-post certificate when not first login
+ if (data.profile != null && data.symbol != null && data.symbol != "default") {
+ val result = web.postCertificate(certificate, data.symbol ?: "default") { _, state ->
+ when (state) {
+ VulcanWebMain.STATE_SUCCESS -> {
+ web.getStartPage { _, _ -> onSuccess() }
+ }
+ VulcanWebMain.STATE_NO_REGISTER -> data.error(ApiError(TAG, ERROR_VULCAN_WEB_NO_REGISTER))
+ VulcanWebMain.STATE_LOGGED_OUT -> data.error(ApiError(TAG, ERROR_VULCAN_WEB_LOGGED_OUT))
+ }
+ }
+ // postCertificate returns false if the cert is not valid anymore
+ if (!result) {
+ data.error(ApiError(TAG, ERROR_VULCAN_WEB_CERTIFICATE_EXPIRED)
+ .withApiResponse(certificate.xml))
+ }
+ }
+ else {
+ // first login - succeed immediately
+ onSuccess()
+ }
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/AttachmentGetEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/AttachmentGetEvent.kt
index cbc85b7d..52415c56 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/AttachmentGetEvent.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/AttachmentGetEvent.kt
@@ -4,11 +4,21 @@
package pl.szczodrzynski.edziennik.data.api.events
-data class AttachmentGetEvent(val profileId: Int, val messageId: Long, val attachmentId: Long,
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+
+data class AttachmentGetEvent(val profileId: Int, val owner: Any, val attachmentId: Long,
var eventType: Int = TYPE_PROGRESS, val fileName: String? = null,
val bytesWritten: Long = 0) {
companion object {
const val TYPE_PROGRESS = 0
const val TYPE_FINISHED = 1
}
+
+ val ownerId
+ get() = when (owner) {
+ is Message -> owner.id
+ is Event -> owner.id
+ else -> -1
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/EventGetEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/EventGetEvent.kt
new file mode 100644
index 00000000..00cf1727
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/EventGetEvent.kt
@@ -0,0 +1,9 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-3-31.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.events
+
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+
+data class EventGetEvent(val event: EventFull)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt
new file mode 100644
index 00000000..fe66c4b3
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/events/RegisterAvailabilityEvent.kt
@@ -0,0 +1,11 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-9-3.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.events
+
+import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
+
+data class RegisterAvailabilityEvent(
+ val data: Map< String, RegisterAvailabilityStatus>
+)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/interfaces/EdziennikInterface.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/interfaces/EdziennikInterface.kt
index e19a19ee..153bbe18 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/interfaces/EdziennikInterface.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/interfaces/EdziennikInterface.kt
@@ -5,9 +5,9 @@
package pl.szczodrzynski.edziennik.data.api.interfaces
import com.google.gson.JsonObject
-import pl.szczodrzynski.edziennik.data.db.entity.Message
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
interface EdziennikInterface {
@@ -16,8 +16,9 @@ interface EdziennikInterface {
fun sendMessage(recipients: List, subject: String, text: String)
fun markAllAnnouncementsAsRead()
fun getAnnouncement(announcement: AnnouncementFull)
- fun getAttachment(message: Message, attachmentId: Long, attachmentName: String)
+ fun getAttachment(owner: Any, attachmentId: Long, attachmentName: String)
fun getRecipientList()
+ fun getEvent(eventFull: EventFull)
fun firstLogin()
fun cancel()
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
index b5086539..6bd9aa83 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/Data.kt
@@ -86,6 +86,9 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
val gradeCategories = LongSparseArray()
var teacherOnConflictStrategy = OnConflictStrategy.IGNORE
+ var eventListReplace = false
+ var messageListReplace = false
+ var announcementListReplace = false
val classrooms = LongSparseArray()
val attendanceTypes = LongSparseArray()
@@ -118,14 +121,12 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
val attendanceList = mutableListOf()
val announcementList = mutableListOf()
- val announcementIgnoreList = mutableListOf()
val luckyNumberList = mutableListOf()
val teacherAbsenceList = mutableListOf()
val messageList = mutableListOf()
- val messageIgnoreList = mutableListOf()
val messageRecipientList = mutableListOf()
val messageRecipientIgnoreList = mutableListOf()
@@ -177,11 +178,9 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
noticeList.clear()
attendanceList.clear()
announcementList.clear()
- announcementIgnoreList.clear()
luckyNumberList.clear()
teacherAbsenceList.clear()
messageList.clear()
- messageIgnoreList.clear()
messageRecipientList.clear()
messageRecipientIgnoreList.clear()
metadataList.clear()
@@ -197,6 +196,13 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
profile.userCode = generateUserCode()
+ // update profile subname with class name, school year and account type
+ profile.subname = joinNotNullStrings(
+ " - ",
+ profile.studentClassName,
+ "${profile.studentSchoolYearStart}/${profile.studentSchoolYearStart + 1}"
+ ) + " " + app.getString(if (profile.isParent) R.string.account_type_parent else R.string.account_type_child)
+
db.profileDao().add(profile)
db.loginStoreDao().add(loginStore)
@@ -277,34 +283,19 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
d("Metadata saved in ${System.currentTimeMillis()-startTime} ms")
startTime = System.currentTimeMillis()
- if (lessonList.isNotEmpty()) {
- db.timetableDao() += lessonList
- }
- if (gradeList.isNotEmpty()) {
- db.gradeDao().addAll(gradeList)
- }
- if (eventList.isNotEmpty()) {
- db.eventDao().addAll(eventList)
- }
+ db.timetableDao().putAll(lessonList, removeNotKept = true)
+ db.gradeDao().putAll(gradeList, removeNotKept = true)
+ db.eventDao().putAll(eventList, forceReplace = eventListReplace, removeNotKept = true)
if (noticeList.isNotEmpty()) {
db.noticeDao().clear(profile.id)
- db.noticeDao().addAll(noticeList)
+ db.noticeDao().putAll(noticeList)
}
- if (attendanceList.isNotEmpty())
- db.attendanceDao().addAll(attendanceList)
- if (announcementList.isNotEmpty())
- db.announcementDao().addAll(announcementList)
- if (announcementIgnoreList.isNotEmpty())
- db.announcementDao().addAllIgnore(announcementIgnoreList)
- if (luckyNumberList.isNotEmpty())
- db.luckyNumberDao().addAll(luckyNumberList)
- if (teacherAbsenceList.isNotEmpty())
- db.teacherAbsenceDao().addAll(teacherAbsenceList)
+ db.attendanceDao().putAll(attendanceList, removeNotKept = true)
+ db.announcementDao().putAll(announcementList, forceReplace = announcementListReplace, removeNotKept = false)
+ db.luckyNumberDao().putAll(luckyNumberList)
+ db.teacherAbsenceDao().putAll(teacherAbsenceList)
- if (messageList.isNotEmpty())
- db.messageDao().addAll(messageList)
- if (messageIgnoreList.isNotEmpty())
- db.messageDao().addAllIgnore(messageIgnoreList)
+ db.messageDao().putAll(messageList, forceReplace = messageListReplace, removeNotKept = false)
if (messageRecipientList.isNotEmpty())
db.messageRecipientDao().addAll(messageRecipientList)
if (messageRecipientIgnoreList.isNotEmpty())
@@ -345,7 +336,7 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
}
fun shouldSyncLuckyNumber(): Boolean {
- return (db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday().value) ?: -1) == -1
+ return db.luckyNumberDao().getNearestFutureNow(profileId, Date.getToday()) == null
}
/*fun error(tag: String, errorCode: Int, response: Response? = null, throwable: Throwable? = null, apiResponse: JsonObject? = null) {
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/DataRemoveModel.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/DataRemoveModel.kt
index ccccc00e..49b57999 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/DataRemoveModel.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/models/DataRemoveModel.kt
@@ -20,10 +20,10 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: TimetableDao) {
if (dateFrom != null && dateTo != null) {
- dao.clearBetweenDates(profileId, dateFrom, dateTo)
+ dao.dontKeepBetweenDates(profileId, dateFrom, dateTo)
} else {
- dateFrom?.let { dateFrom -> dao.clearFromDate(profileId, dateFrom) }
- dateTo?.let { dateTo -> dao.clearToDate(profileId, dateTo) }
+ dateFrom?.let { dateFrom -> dao.dontKeepFromDate(profileId, dateFrom) }
+ dateTo?.let { dateTo -> dao.dontKeepToDate(profileId, dateTo) }
}
}
}
@@ -38,12 +38,12 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: GradeDao) {
if (all) {
- if (type != null) dao.clearWithType(profileId, type)
+ if (type != null) dao.dontKeepWithType(profileId, type)
else dao.clear(profileId)
}
semester?.let {
- if (type != null) dao.clearForSemesterWithType(profileId, it, type)
- else dao.clearForSemester(profileId, it)
+ if (type != null) dao.dontKeepForSemesterWithType(profileId, it, type)
+ else dao.dontKeepForSemester(profileId, it)
}
}
}
@@ -53,12 +53,15 @@ open class DataRemoveModel {
fun futureExceptType(exceptType: Long) = Events(null, exceptType, null)
fun futureExceptTypes(exceptTypes: List) = Events(null, null, exceptTypes)
fun futureWithType(type: Long) = Events(type, null, null)
+ fun future() = Events(null, null, null)
}
fun commit(profileId: Int, dao: EventDao) {
- type?.let { dao.removeFutureWithType(profileId, Date.getToday(), it) }
- exceptType?.let { dao.removeFutureExceptType(profileId, Date.getToday(), it) }
- exceptTypes?.let { dao.removeFutureExceptTypes(profileId, Date.getToday(), it) }
+ type?.let { dao.dontKeepFutureWithType(profileId, Date.getToday(), it) }
+ exceptType?.let { dao.dontKeepFutureExceptType(profileId, Date.getToday(), it) }
+ exceptTypes?.let { dao.dontKeepFutureExceptTypes(profileId, Date.getToday(), it) }
+ if (type == null && exceptType == null && exceptTypes == null)
+ dao.dontKeepFuture(profileId, Date.getToday())
}
}
@@ -69,7 +72,7 @@ open class DataRemoveModel {
fun commit(profileId: Int, dao: AttendanceDao) {
if (dateFrom != null) {
- dao.clearAfterDate(profileId, dateFrom)
+ dao.dontKeepAfterDate(profileId, dateFrom)
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
index eb70ab9a..042e63fe 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyApi.kt
@@ -12,12 +12,14 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.withContext
import okhttp3.OkHttpClient
+import org.greenrobot.eventbus.EventBus
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.DateAdapter
import pl.szczodrzynski.edziennik.data.api.szkolny.adapter.TimeAdapter
import pl.szczodrzynski.edziennik.data.api.szkolny.interceptor.SignatureInterceptor
import pl.szczodrzynski.edziennik.data.api.szkolny.request.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.ApiResponse
+import pl.szczodrzynski.edziennik.data.api.szkolny.response.RegisterAvailabilityStatus
import pl.szczodrzynski.edziennik.data.api.szkolny.response.Update
import pl.szczodrzynski.edziennik.data.api.szkolny.response.WebPushResponse
import pl.szczodrzynski.edziennik.data.db.entity.Event
@@ -27,6 +29,7 @@ import pl.szczodrzynski.edziennik.data.db.entity.Profile
import pl.szczodrzynski.edziennik.data.db.full.EventFull
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorDetailsDialog
import pl.szczodrzynski.edziennik.ui.modules.error.ErrorSnackbar
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
import retrofit2.Response
@@ -73,7 +76,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
suspend inline fun runCatching(errorSnackbar: ErrorSnackbar, crossinline block: SzkolnyApi.() -> T?): T? {
return try {
- withContext(Dispatchers.Default) { block() }
+ withContext(Dispatchers.Default) { block.invoke(this@SzkolnyApi) }
}
catch (e: Exception) {
errorSnackbar.addError(e.toApiError(TAG)).show()
@@ -82,7 +85,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
}
suspend inline fun runCatching(activity: AppCompatActivity, crossinline block: SzkolnyApi.() -> T?): T? {
return try {
- withContext(Dispatchers.Default) { block() }
+ withContext(Dispatchers.Default) { block.invoke(this@SzkolnyApi) }
}
catch (e: Exception) {
ErrorDetailsDialog(
@@ -95,7 +98,7 @@ class SzkolnyApi(val app: App) : CoroutineScope {
}
inline fun runCatching(block: SzkolnyApi.() -> T, onError: (e: Throwable) -> Unit): T? {
return try {
- block()
+ block.invoke(this@SzkolnyApi)
}
catch (e: Exception) {
onError(e)
@@ -111,6 +114,22 @@ class SzkolnyApi(val app: App) : CoroutineScope {
*/
@Throws(Exception::class)
private inline fun parseResponse(response: Response>): T {
+ app.config.update = response.body()?.update?.let { update ->
+ if (update.versionCode > BuildConfig.VERSION_CODE) {
+ if (update.updateMandatory
+ && EventBus.getDefault().hasSubscriberForEvent(update::class.java)) {
+ EventBus.getDefault().postSticky(update)
+ }
+ update
+ }
+ else
+ null
+ }
+
+ response.body()?.registerAvailability?.let { registerAvailability ->
+ app.config.sync.registerAvailability = registerAvailability
+ }
+
if (response.isSuccessful && response.body()?.success == true) {
if (Unit is T) {
return Unit
@@ -196,6 +215,11 @@ class SzkolnyApi(val app: App) : CoroutineScope {
// skip blacklisted events
if (event.id in blacklistedIds)
return@forEach
+
+ // force nullable non-negative colors
+ if (event.color == -1)
+ event.color = null
+
// create the event for every matching team and profile
teams.filter { it.code == event.teamCode }.onEach { team ->
val profile = profiles.firstOrNull { it.id == team.profileId } ?: return@onEach
@@ -322,4 +346,23 @@ class SzkolnyApi(val app: App) : CoroutineScope {
return parseResponse(response).message
}
+
+ @Throws(Exception::class)
+ fun getPlatforms(registerName: String): List {
+ val response = api.appLoginPlatforms(registerName).execute()
+
+ return parseResponse(response)
+ }
+
+ @Throws(Exception::class)
+ fun getFirebaseToken(registerName: String): String {
+ val response = api.firebaseToken(registerName).execute()
+ return parseResponse(response)
+ }
+
+ @Throws(Exception::class)
+ fun getRegisterAvailability(): Map {
+ val response = api.registerAvailability().execute()
+ return parseResponse(response)
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
index 0e3dd574..6046e4da 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/SzkolnyService.kt
@@ -6,11 +6,9 @@ package pl.szczodrzynski.edziennik.data.api.szkolny
import pl.szczodrzynski.edziennik.data.api.szkolny.request.*
import pl.szczodrzynski.edziennik.data.api.szkolny.response.*
+import pl.szczodrzynski.edziennik.ui.modules.login.LoginInfo
import retrofit2.Call
-import retrofit2.http.Body
-import retrofit2.http.GET
-import retrofit2.http.POST
-import retrofit2.http.Query
+import retrofit2.http.*
interface SzkolnyService {
@@ -34,4 +32,13 @@ interface SzkolnyService {
@POST("feedbackMessage")
fun feedbackMessage(@Body request: FeedbackMessageRequest): Call>
+
+ @GET("appLogin/platforms/{registerName}")
+ fun appLoginPlatforms(@Path("registerName") registerName: String): Call>>
+
+ @GET("firebase/token/{registerName}")
+ fun firebaseToken(@Path("registerName") registerName: String): Call>
+
+ @GET("registerAvailability")
+ fun registerAvailability(): Call>>
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
index 446ae7ab..4d9f425c 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/interceptor/Signing.kt
@@ -39,13 +39,13 @@ object Signing {
val appPassword by lazy {
iLoveApple(
"ThisIsOurHardWorkPleaseDoNotCopyOrSteal(c)2019.KubaSz".sha256(),
- BuildConfig.VERSION_NAME,
+ BuildConfig.VERSION_NAME.substringBeforeLast('+'),
BuildConfig.VERSION_CODE.toLong()
)
}
/*fun provideKey(param1: String, param2: Long): ByteArray {*/
fun pleaseStopRightNow(param1: String, param2: Long): ByteArray {
- return "$param1.MTIzNDU2Nzg5MD86J6EdtN===.$param2".sha256()
+ return "$param1.MTIzNDU2Nzg5MDx45DzIF8===.$param2".sha256()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/request/EventShareRequest.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/request/EventShareRequest.kt
index 624b8b0f..1977d1b2 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/request/EventShareRequest.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/request/EventShareRequest.kt
@@ -12,7 +12,8 @@ data class EventShareRequest (
val action: String = "event",
- val sharedByName: String,
+ /* If null, the server shows an error */
+ val sharedByName: String?,
val shareTeamCode: String? = null,
val unshareTeamCode: String? = null,
val requesterName: String? = null,
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/ApiResponse.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/ApiResponse.kt
index ac56f53f..0987dcef 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/ApiResponse.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/ApiResponse.kt
@@ -10,7 +10,10 @@ data class ApiResponse (
val errors: List? = null,
- val data: T? = null
+ val data: T? = null,
+
+ val update: Update? = null,
+ val registerAvailability: Map? = null
) {
data class Error (val code: String, val reason: String)
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/RegisterAvailabilityStatus.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/RegisterAvailabilityStatus.kt
new file mode 100644
index 00000000..82f2e050
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/RegisterAvailabilityStatus.kt
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-9-2.
+ */
+
+package pl.szczodrzynski.edziennik.data.api.szkolny.response
+
+import pl.szczodrzynski.edziennik.BuildConfig
+import pl.szczodrzynski.edziennik.DAY
+import pl.szczodrzynski.edziennik.currentTimeUnix
+
+data class RegisterAvailabilityStatus(
+ val available: Boolean,
+ val name: String?,
+ val userMessage: Message?,
+ val nextCheckAt: Long = currentTimeUnix() + 7 * DAY,
+ val minVersionCode: Int = BuildConfig.VERSION_CODE
+) {
+ data class Message(
+ val title: String,
+ val contentShort: String,
+ val contentLong: String,
+ val icon: String?,
+ val image: String?,
+ val url: String?
+ )
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/UpdateResponse.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/UpdateResponse.kt
index a2028926..63a8ce9d 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/UpdateResponse.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/szkolny/response/UpdateResponse.kt
@@ -11,5 +11,6 @@ data class Update(
val releaseNotes: String?,
val releaseType: String,
val isOnGooglePlay: Boolean,
- val downloadUrl: String?
-)
\ No newline at end of file
+ val downloadUrl: String?,
+ val updateMandatory: Boolean
+)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/AppSync.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/AppSync.kt
index 56d5132a..c10bab3e 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/AppSync.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/AppSync.kt
@@ -34,17 +34,16 @@ class AppSync(val app: App, val notifications: MutableList, val pr
if (events.isNotEmpty()) {
val today = Date.getToday()
app.db.metadataDao().addAllIgnore(events.map { event ->
- val isPast = event.eventDate < today
+ val isPast = event.date < today
Metadata(
event.profileId,
Metadata.TYPE_EVENT,
event.id,
isPast || markAsSeen || event.seen,
- isPast || markAsSeen || event.notified,
- event.addedDate
+ isPast || markAsSeen || event.notified
)
})
- return app.db.eventDao().addAll(events).size
+ return app.db.eventDao().upsertAll(events).size
}
return 0;
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt
index 7c049f5a..21a5c112 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/task/Notifications.kt
@@ -34,6 +34,7 @@ class Notifications(val app: App, val notifications: MutableList,
announcementNotifications()
messageNotifications()
luckyNumberNotifications()
+ teacherAbsenceNotifications()
}
private fun timetableNotifications() {
@@ -52,13 +53,13 @@ class Notifications(val app: App, val notifications: MutableList,
profileId = lesson.profileId,
profileName = profiles.singleOrNull { it.id == lesson.profileId }?.name,
viewId = MainActivity.DRAWER_ITEM_TIMETABLE,
- addedDate = lesson.addedDate
+ addedDate = System.currentTimeMillis()
).addExtra("timetableDate", lesson.displayDate?.stringY_m_d ?: "")
}
}
private fun eventNotifications() {
- for (event in app.db.eventDao().notNotifiedNow.filter { it.eventDate >= today }) {
+ for (event in app.db.eventDao().getNotNotifiedNow().filter { it.date >= today }) {
val text = if (event.type == Event.TYPE_HOMEWORK)
app.getString(
if (event.subjectLongName.isNullOrEmpty())
@@ -66,7 +67,7 @@ class Notifications(val app: App, val notifications: MutableList,
else
R.string.notification_homework_format,
event.subjectLongName,
- event.eventDate.formattedString
+ event.date.formattedString
)
else
app.getString(
@@ -74,8 +75,8 @@ class Notifications(val app: App, val notifications: MutableList,
R.string.notification_event_no_subject_format
else
R.string.notification_event_format,
- event.typeName,
- event.eventDate.formattedString,
+ event.typeName ?: "wydarzenie",
+ event.date.formattedString,
event.subjectLongName
)
val type = if (event.type == Event.TYPE_HOMEWORK) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
@@ -88,17 +89,17 @@ class Notifications(val app: App, val notifications: MutableList,
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
viewId = if (event.type == Event.TYPE_HOMEWORK) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
addedDate = event.addedDate
- ).addExtra("eventId", event.id).addExtra("eventDate", event.eventDate.value.toLong())
+ ).addExtra("eventId", event.id).addExtra("eventDate", event.date.value.toLong())
}
}
fun sharedEventNotifications() {
- for (event in app.db.eventDao().notNotifiedNow.filter { it.eventDate >= today && it.sharedBy != null }) {
+ for (event in app.db.eventDao().getNotNotifiedNow().filter { it.date >= today && it.sharedBy != null }) {
val text = app.getString(
R.string.notification_shared_event_format,
event.sharedByName,
event.typeName ?: "wydarzenie",
- event.eventDate.formattedString,
+ event.date.formattedString,
event.topic
)
val type = if (event.type == Event.TYPE_HOMEWORK) Notification.TYPE_NEW_HOMEWORK else Notification.TYPE_NEW_EVENT
@@ -111,12 +112,12 @@ class Notifications(val app: App, val notifications: MutableList,
profileName = profiles.singleOrNull { it.id == event.profileId }?.name,
viewId = if (event.type == Event.TYPE_HOMEWORK) MainActivity.DRAWER_ITEM_HOMEWORK else MainActivity.DRAWER_ITEM_AGENDA,
addedDate = event.addedDate
- ).addExtra("eventId", event.id).addExtra("eventDate", event.eventDate.value.toLong())
+ ).addExtra("eventId", event.id).addExtra("eventDate", event.date.value.toLong())
}
}
private fun gradeNotifications() {
- for (grade in app.db.gradeDao().notNotifiedNow) {
+ for (grade in app.db.gradeDao().getNotNotifiedNow()) {
val gradeName = when (grade.type) {
Grade.TYPE_SEMESTER1_PROPOSED, Grade.TYPE_SEMESTER2_PROPOSED -> app.getString(R.string.grade_semester_proposed_format_2, grade.name)
Grade.TYPE_SEMESTER1_FINAL, Grade.TYPE_SEMESTER2_FINAL -> app.getString(R.string.grade_semester_final_format_2, grade.name)
@@ -143,7 +144,7 @@ class Notifications(val app: App, val notifications: MutableList,
}
private fun behaviourNotifications() {
- for (notice in app.db.noticeDao().notNotifiedNow) {
+ for (notice in app.db.noticeDao().getNotNotifiedNow()) {
val noticeTypeStr = when (notice.type) {
Notice.TYPE_POSITIVE -> app.getString(R.string.notification_notice_praise)
@@ -154,7 +155,7 @@ class Notifications(val app: App, val notifications: MutableList,
val text = app.getString(
R.string.notification_notice_format,
noticeTypeStr,
- notice.teacherFullName,
+ notice.teacherName,
Date.fromMillis(notice.addedDate).formattedString
)
notifications += Notification(
@@ -171,9 +172,9 @@ class Notifications(val app: App, val notifications: MutableList,
}
private fun attendanceNotifications() {
- for (attendance in app.db.attendanceDao().notNotifiedNow) {
+ for (attendance in app.db.attendanceDao().getNotNotifiedNow()) {
- val attendanceTypeStr = when (attendance.type) {
+ val attendanceTypeStr = when (attendance.baseType) {
Attendance.TYPE_ABSENT -> app.getString(R.string.notification_absence)
Attendance.TYPE_ABSENT_EXCUSED -> app.getString(R.string.notification_absence_excused)
Attendance.TYPE_BELATED -> app.getString(R.string.notification_belated)
@@ -190,7 +191,7 @@ class Notifications(val app: App, val notifications: MutableList,
R.string.notification_attendance_format,
attendanceTypeStr,
attendance.subjectLongName,
- attendance.lessonDate.formattedString
+ attendance.date.formattedString
)
notifications += Notification(
id = Notification.buildId(attendance.profileId, Notification.TYPE_NEW_ATTENDANCE, attendance.id),
@@ -206,10 +207,10 @@ class Notifications(val app: App, val notifications: MutableList,
}
private fun announcementNotifications() {
- for (announcement in app.db.announcementDao().notNotifiedNow) {
+ for (announcement in app.db.announcementDao().getNotNotifiedNow()) {
val text = app.getString(
R.string.notification_announcement_format,
- announcement.teacherFullName,
+ announcement.teacherName,
announcement.subject
)
notifications += Notification(
@@ -226,10 +227,10 @@ class Notifications(val app: App, val notifications: MutableList,
}
private fun messageNotifications() {
- for (message in app.db.messageDao().receivedNotNotifiedNow) {
+ for (message in app.db.messageDao().getNotNotifiedNow()) {
val text = app.getString(
R.string.notification_message_format,
- message.senderFullName,
+ message.senderName,
message.subject
)
notifications += Notification(
@@ -246,9 +247,9 @@ class Notifications(val app: App, val notifications: MutableList,
}
private fun luckyNumberNotifications() {
- val luckyNumbers = app.db.luckyNumberDao().notNotifiedNow
- luckyNumbers?.removeAll { it.date < today }
- luckyNumbers?.forEach { luckyNumber ->
+ val luckyNumbers = app.db.luckyNumberDao().getNotNotifiedNow().toMutableList()
+ luckyNumbers.removeAll { it.date < today }
+ luckyNumbers.forEach { luckyNumber ->
val profile = profiles.singleOrNull { it.id == luckyNumber.profileId } ?: return@forEach
val text = when (profile.studentNumber != -1 && profile.studentNumber == luckyNumber.number) {
true -> when (luckyNumber.date.value) {
@@ -270,8 +271,27 @@ class Notifications(val app: App, val notifications: MutableList,
profileId = luckyNumber.profileId,
profileName = profile.name,
viewId = MainActivity.DRAWER_ITEM_HOME,
- addedDate = luckyNumber.addedDate
+ addedDate = System.currentTimeMillis()
)
}
}
+
+ private fun teacherAbsenceNotifications() {
+ for (teacherAbsence in app.db.teacherAbsenceDao().getNotNotifiedNow()) {
+ val message = app.getString(
+ R.string.notification_teacher_absence_new_format,
+ teacherAbsence.teacherName
+ )
+ notifications += Notification(
+ id = Notification.buildId(teacherAbsence.profileId, Notification.TYPE_TEACHER_ABSENCE, teacherAbsence.id),
+ title = app.getNotificationTitle(Notification.TYPE_TEACHER_ABSENCE),
+ text = message,
+ type = Notification.TYPE_TEACHER_ABSENCE,
+ profileId = teacherAbsence.profileId,
+ profileName = profiles.singleOrNull { it.id == teacherAbsence.profileId }?.name,
+ viewId = MainActivity.DRAWER_ITEM_AGENDA,
+ addedDate = teacherAbsence.addedDate
+ ).addExtra("eventDate", teacherAbsence.dateFrom.value.toLong())
+ }
+ }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt
index 5b01d476..aee8e3af 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/AppDb.kt
@@ -43,7 +43,7 @@ import pl.szczodrzynski.edziennik.data.db.migration.*
LibrusLesson::class,
TimetableManual::class,
Metadata::class
-], version = 79)
+], version = 89)
@TypeConverters(
ConverterTime::class,
ConverterDate::class,
@@ -164,7 +164,17 @@ abstract class AppDb : RoomDatabase() {
Migration76(),
Migration77(),
Migration78(),
- Migration79()
+ Migration79(),
+ Migration80(),
+ Migration81(),
+ Migration82(),
+ Migration83(),
+ Migration84(),
+ Migration85(),
+ Migration86(),
+ Migration87(),
+ Migration88(),
+ Migration89()
).allowMainThreadQueries().build()
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.java
deleted file mode 100644
index ab32fb7c..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.Announcement;
-import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
-import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ANNOUNCEMENT;
-
-@Dao
-public abstract class AnnouncementDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long add(Announcement announcement);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void addAll(List announcementList);
-
- @Insert(onConflict = OnConflictStrategy.IGNORE)
- public abstract void addAllIgnore(List announcementList);
-
- @Query("DELETE FROM announcements WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @RawQuery(observedEntities = {Announcement.class, Metadata.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- public LiveData> getAll(int profileId, String filter) {
- return getAll(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM announcements \n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE announcements.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
- public LiveData> getAll(int profileId) {
- return getAll(profileId, "1");
- }
- public LiveData> getAllWhere(int profileId, String filter) {
- return getAll(profileId, filter);
- }
-
- @RawQuery(observedEntities = {Announcement.class, Metadata.class})
- abstract List getAllNow(SupportSQLiteQuery query);
- public List getAllNow(int profileId, String filter) {
- return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM announcements \n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE announcements.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
- public List getNotNotifiedNow(int profileId) {
- return getAllNow(profileId, "notified = 0");
- }
-
- @Query("SELECT " +
- "*, " +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName " +
- "FROM announcements " +
- "LEFT JOIN teachers USING(profileId, teacherId) " +
- "LEFT JOIN metadata ON announcementId = thingId AND thingType = "+TYPE_ANNOUNCEMENT+" AND metadata.profileId = announcements.profileId " +
- "WHERE notified = 0 " +
- "ORDER BY addedDate DESC")
- public abstract List getNotNotifiedNow();
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt
new file mode 100644
index 00000000..67e034c5
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AnnouncementDao.kt
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-25.
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
+import pl.szczodrzynski.edziennik.data.db.entity.Announcement
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.AnnouncementFull
+
+@Dao
+@SelectiveDao(db = AppDb::class)
+abstract class AnnouncementDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *,
+ teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
+ FROM announcements
+ LEFT JOIN teachers USING(profileId, teacherId)
+ LEFT JOIN metadata ON announcementId = thingId AND thingType = ${Metadata.TYPE_ANNOUNCEMENT} AND metadata.profileId = announcements.profileId
+ """
+
+ private const val ORDER_BY = """ORDER BY addedDate DESC"""
+ }
+
+ private val selective by lazy { AnnouncementDaoSelective(App.db) }
+
+ @RawQuery(observedEntities = [Announcement::class])
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [Announcement::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
+
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "announcementId"], skippedColumns = ["addedDate", "announcementText"])
+ override fun update(item: Announcement) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
+
+ // CLEAR
+ @Query("DELETE FROM announcements WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM announcements WHERE keep = 0")
+ abstract override fun removeNotKept()
+
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE announcements.profileId = $profileId $ORDER_BY")
+
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE announcements.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
+ fun getNotNotifiedNow(profileId: Int) =
+ getRawNow("$QUERY WHERE announcements.profileId = $profileId AND notified = 0 $ORDER_BY")
+
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE announcements.profileId = $profileId AND announcementId = $id")
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.java
deleted file mode 100644
index 95c3147f..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.Attendance;
-import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull;
-import pl.szczodrzynski.edziennik.utils.models.Date;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_ATTENDANCE;
-
-@Dao
-public abstract class AttendanceDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long add(Attendance attendance);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void addAll(List attendanceList);
-
- @Query("DELETE FROM attendances WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @Query("DELETE FROM attendances WHERE profileId = :profileId AND attendanceLessonDate > :date")
- public abstract void clearAfterDate(int profileId, Date date);
-
- @RawQuery(observedEntities = {Attendance.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- public LiveData> getAll(int profileId, String filter) {
- return getAll(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM attendances \n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = "+profileId+"\n" +
- "WHERE attendances.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC"));
- }
- public LiveData> getAll(int profileId) {
- return getAll(profileId, "1");
- }
- public LiveData> getAllWhere(int profileId, String filter) {
- return getAll(profileId, filter);
- }
-
- @RawQuery
- abstract List getAllNow(SupportSQLiteQuery query);
- public List getAllNow(int profileId, String filter) {
- return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM attendances \n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = "+profileId+"\n" +
- "WHERE attendances.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC"));
- }
- public List getNotNotifiedNow(int profileId) {
- return getAllNow(profileId, "notified = 0");
- }
-
- @Query("SELECT * FROM attendances " +
- "LEFT JOIN subjects USING(profileId, subjectId) " +
- "LEFT JOIN metadata ON attendanceId = thingId AND thingType = " + TYPE_ATTENDANCE + " AND metadata.profileId = attendances.profileId " +
- "WHERE notified = 0 " +
- "ORDER BY attendanceLessonDate DESC, attendanceStartTime DESC")
- public abstract List getNotNotifiedNow();
-
- // only absent and absent_excused count as absences
- // all the other types are counted as being present
- @Query("SELECT \n" +
- "CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+ Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
- " / \n" +
- "CAST(count() AS float)*100 \n" +
- "FROM attendances \n" +
- "WHERE profileId = :profileId")
- public abstract LiveData getAttendancePercentage(int profileId);
-
- @Query("SELECT \n" +
- "CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
- " / \n" +
- "CAST(count() AS float)*100 \n" +
- "FROM attendances \n" +
- "WHERE profileId = :profileId AND attendanceSemester = :semester")
- public abstract float getAttendancePercentageNow(int profileId, int semester);
-
- @Query("SELECT \n" +
- "CAST(SUM(CASE WHEN attendanceType != "+Attendance.TYPE_ABSENT+" AND attendanceType != "+Attendance.TYPE_ABSENT_EXCUSED+" THEN 1 ELSE 0 END) AS float)\n" +
- " / \n" +
- "CAST(count() AS float)*100 \n" +
- "FROM attendances \n" +
- "WHERE profileId = :profileId")
- public abstract float getAttendancePercentageNow(int profileId);
-}
-
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt
new file mode 100644
index 00000000..97513689
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/AttendanceDao.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-24.
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
+import pl.szczodrzynski.edziennik.data.db.entity.Attendance
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.AttendanceFull
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+@Dao
+@SelectiveDao(db = AppDb::class)
+abstract class AttendanceDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *,
+ teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
+ FROM attendances
+ LEFT JOIN teachers USING(profileId, teacherId)
+ LEFT JOIN subjects USING(profileId, subjectId)
+ LEFT JOIN metadata ON attendanceId = thingId AND thingType = ${Metadata.TYPE_ATTENDANCE} AND metadata.profileId = attendances.profileId
+ """
+
+ private const val ORDER_BY = """ORDER BY attendanceDate DESC, attendanceTime DESC"""
+ }
+
+ private val selective by lazy { AttendanceDaoSelective(App.db) }
+
+ @RawQuery(observedEntities = [Attendance::class])
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [Attendance::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
+
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "attendanceId"], skippedColumns = ["addedDate", "announcementText"])
+ override fun update(item: Attendance) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
+
+ // CLEAR
+ @Query("DELETE FROM attendances WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM attendances WHERE keep = 0")
+ abstract override fun removeNotKept()
+
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE attendances.profileId = $profileId $ORDER_BY")
+
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE attendances.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
+ fun getNotNotifiedNow(profileId: Int) =
+ getRawNow("$QUERY WHERE attendances.profileId = $profileId AND notified = 0 $ORDER_BY")
+
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE attendances.profileId = $profileId AND attendanceId = $id")
+
+ @Query("UPDATE attendances SET keep = 0 WHERE profileId = :profileId AND attendanceDate >= :date")
+ abstract fun dontKeepAfterDate(profileId: Int, date: Date?)
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/BaseDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/BaseDao.kt
new file mode 100644
index 00000000..0ae961db
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/BaseDao.kt
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-3-28.
+ */
+
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.*
+import androidx.sqlite.db.SimpleSQLiteQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.data.db.entity.Keepable
+
+@Dao
+interface BaseDao {
+ @RawQuery
+ fun getRaw(query: SupportSQLiteQuery): LiveData>
+ fun getRaw(query: String) = getRaw(SimpleSQLiteQuery(query))
+ @RawQuery
+ fun getOne(query: SupportSQLiteQuery): LiveData
+ fun getOne(query: String) = getOne(SimpleSQLiteQuery(query))
+ @RawQuery
+ fun getRawNow(query: SupportSQLiteQuery): List
+ fun getRawNow(query: String) = getRawNow(SimpleSQLiteQuery(query))
+ @RawQuery
+ fun getOneNow(query: SupportSQLiteQuery): F?
+ fun getOneNow(query: String) = getOneNow(SimpleSQLiteQuery(query))
+
+ fun removeNotKept()
+
+ /**
+ * INSERT an [item] into the database,
+ * ignoring any conflicts.
+ */
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ fun add(item: T): Long
+ /**
+ * INSERT [items] into the database,
+ * ignoring any conflicts.
+ */
+ @Insert(onConflict = OnConflictStrategy.IGNORE)
+ fun addAll(items: List): LongArray
+
+ /**
+ * REPLACE an [item] in the database,
+ * removing any conflicting rows.
+ * Creates the item if it does not exist yet.
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun replace(item: T)
+ /**
+ * REPLACE [items] in the database,
+ * removing any conflicting rows.
+ * Creates items if it does not exist yet.
+ */
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ fun replaceAll(items: List)
+
+ /**
+ * Selective UPDATE an [item] in the database.
+ * Do nothing if a matching item does not exist.
+ */
+ fun update(item: T): Long
+ /**
+ * Selective UPDATE [items] in the database.
+ * Do nothing for those items which do not exist.
+ */
+ fun updateAll(items: List): LongArray
+
+ /**
+ * Remove all items from the database,
+ * that match the given [profileId].
+ */
+ fun clear(profileId: Int)
+
+ /**
+ * INSERT an [item] into the database,
+ * doing a selective [update] on conflicts.
+ * @return the newly inserted item's ID or -1L if the item was updated instead
+ */
+ @Transaction
+ fun upsert(item: T): Long {
+ val id = add(item)
+ if (id == -1L) update(item)
+ return id
+ }
+ /**
+ * INSERT [items] into the database,
+ * doing a selective [update] on conflicts.
+ * @return a [LongArray] of IDs of newly inserted items or -1L if the item existed before
+ */
+ @Transaction
+ fun upsertAll(items: List, removeNotKept: Boolean = false): LongArray {
+ val insertResult = addAll(items)
+ val updateList = mutableListOf()
+
+ insertResult.forEachIndexed { index, result ->
+ if (result == -1L) updateList.add(items[index])
+ }
+
+ if (updateList.isNotEmpty()) updateAll(items)
+ if (removeNotKept) removeNotKept()
+ return insertResult
+ }
+
+ /**
+ * Make sure that [items] are in the database.
+ * When [forceReplace] == false, do a selective update (UPSERT).
+ * When [forceReplace] == true, add all items replacing any conflicting ones (REPLACE).
+ *
+ * @param forceReplace whether to replace all items instead of selectively updating
+ * @param removeNotKept whether to remove all items whose [keep] parameter is false
+ */
+ fun putAll(items: List, forceReplace: Boolean = false, removeNotKept: Boolean = false) {
+ if (items.isEmpty())
+ return
+ if (forceReplace)
+ replaceAll(items)
+ else
+ upsertAll(items, removeNotKept = false)
+
+ if (removeNotKept) removeNotKept()
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java
deleted file mode 100644
index 083b499a..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.java
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.room.Transaction;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.Event;
-import pl.szczodrzynski.edziennik.data.db.full.EventFull;
-import pl.szczodrzynski.edziennik.utils.models.Date;
-import pl.szczodrzynski.edziennik.utils.models.Time;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_EVENT;
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_HOMEWORK;
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_LESSON_CHANGE;
-
-@Dao
-public abstract class EventDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long add(Event event);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long[] addAll(List eventList);
-
- @Query("DELETE FROM events WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @Query("DELETE FROM events WHERE profileId = :profileId AND eventId = :id")
- public abstract void remove(int profileId, long id);
- @Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
- public abstract void removeMetadata(int profileId, int thingType, long thingId);
- @Transaction
- public void remove(int profileId, long type, long id) {
- remove(profileId, id);
- removeMetadata(profileId, type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, id);
- }
- @Transaction
- public void remove(Event event) {
- remove(event.profileId, event.type, event.id);
- }
- @Transaction
- public void remove(int profileId, Event event) {
- remove(profileId, event.type, event.id);
- }
- @Query("DELETE FROM events WHERE teamId = :teamId AND eventId = :id")
- public abstract void removeByTeamId(long teamId, long id);
-
- @RawQuery(observedEntities = {Event.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- public LiveData> getAll(int profileId, String filter, String limit) {
- String query = "SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName,\n" +
- "eventTypes.eventTypeName AS typeName,\n" +
- "eventTypes.eventTypeColor AS typeColor\n" +
- "FROM events\n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN teams USING(profileId, teamId)\n" +
- "LEFT JOIN eventTypes USING(profileId, eventType)\n" +
- "LEFT JOIN metadata ON eventId = thingId AND (thingType = " + TYPE_EVENT + " OR thingType = " + TYPE_HOMEWORK + ") AND metadata.profileId = "+profileId+"\n" +
- "WHERE events.profileId = "+profileId+" AND events.eventBlacklisted = 0 AND "+filter+"\n" +
- "GROUP BY eventId\n" +
- "ORDER BY eventDate, eventStartTime ASC "+limit;
- Log.d("DB", query);
- return getAll(new SimpleSQLiteQuery(query));
- }
- public LiveData> getAll(int profileId) {
- return getAll(profileId, "1", "");
- }
- public List getAllNow(int profileId) {
- return getAllNow(profileId, "1");
- }
- public LiveData> getAllWhere(int profileId, String filter) {
- return getAll(profileId, filter, "");
- }
- public LiveData> getAllByType(int profileId, long type, String filter) {
- return getAll(profileId, "eventType = "+type+" AND "+filter, "");
- }
- public LiveData> getAllByDate(int profileId, @NonNull Date date) {
- return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"'", "");
- }
- public List getAllByDateNow(int profileId, @NonNull Date date) {
- return getAllNow(profileId, "eventDate = '"+date.getStringY_m_d()+"'");
- }
- public LiveData> getAllByDateTime(int profileId, @NonNull Date date, Time time) {
- if (time == null)
- return getAllByDate(profileId, date);
- return getAll(profileId, "eventDate = '"+date.getStringY_m_d()+"' AND eventStartTime = '"+time.getStringValue()+"'", "");
- }
- public LiveData> getAllNearest(int profileId, @NonNull Date today, int limit) {
- return getAll(profileId, "eventDate >= '"+today.getStringY_m_d()+"'", "LIMIT "+limit);
- }
-
- @RawQuery
- abstract List getAllNow(SupportSQLiteQuery query);
- public List getAllNow(int profileId, String filter) {
- return getAllNow(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName,\n" +
- "eventTypes.eventTypeName AS typeName,\n" +
- "eventTypes.eventTypeColor AS typeColor\n" +
- "FROM events \n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN teams USING(profileId, teamId)\n" +
- "LEFT JOIN eventTypes USING(profileId, eventType)\n" +
- "LEFT JOIN metadata ON eventId = thingId AND (thingType = " + TYPE_EVENT + " OR thingType = " + TYPE_HOMEWORK + ") AND metadata.profileId = "+profileId+"\n" +
- "WHERE events.profileId = "+profileId+" AND events.eventBlacklisted = 0 AND "+filter+"\n" +
- "GROUP BY eventId\n" +
- "ORDER BY eventStartTime, addedDate ASC"));
- }
- public List getNotNotifiedNow(int profileId) {
- return getAllNow(profileId, "notified = 0");
- }
-
- @Query("SELECT eventId FROM events WHERE profileId = :profileId AND eventBlacklisted = 1")
- public abstract List getBlacklistedIds(int profileId);
- @Query("SELECT eventId FROM events WHERE eventBlacklisted = 1")
- public abstract List getBlacklistedIds();
-
- @Query("SELECT " +
- "*, " +
- "eventTypes.eventTypeName AS typeName, " +
- "eventTypes.eventTypeColor AS typeColor " +
- "FROM events " +
- "LEFT JOIN subjects USING(profileId, subjectId) " +
- "LEFT JOIN eventTypes USING(profileId, eventType) " +
- "LEFT JOIN metadata ON eventId = thingId AND (thingType = " + TYPE_EVENT + " OR thingType = " + TYPE_HOMEWORK + ") AND metadata.profileId = events.profileId " +
- "WHERE events.eventBlacklisted = 0 AND notified = 0 " +
- "GROUP BY eventId " +
- "ORDER BY addedDate ASC")
- public abstract List getNotNotifiedNow();
-
- public EventFull getByIdNow(int profileId, long eventId) {
- List eventList = getAllNow(profileId, "eventId = "+eventId);
- return eventList.size() == 0 ? null : eventList.get(0);
- }
-
- @Query("UPDATE events SET eventAddedManually = 1 WHERE profileId = :profileId AND eventDate < :date")
- public abstract void convertOlderToManual(int profileId, Date date);
-
- @Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0")
- public abstract void removeNotManual(int profileId);
-
- @RawQuery
- abstract long removeFuture(SupportSQLiteQuery query);
- @Transaction
- public void removeFuture(int profileId, Date todayDate, String filter) {
- removeFuture(new SimpleSQLiteQuery("DELETE FROM events WHERE profileId = " + profileId
- + " AND eventAddedManually = 0 AND eventDate >= '" + todayDate.getStringY_m_d() + "'" +
- " AND " + filter));
- }
-
- @Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType = :type")
- public abstract void removeFutureWithType(int profileId, Date todayDate, long type);
-
- @Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType != :exceptType")
- public abstract void removeFutureExceptType(int profileId, Date todayDate, long exceptType);
-
- @Transaction
- public void removeFutureExceptTypes(int profileId, Date todayDate, List exceptTypes) {
- removeFuture(profileId, todayDate, "eventType NOT IN " + exceptTypes.toString().replace('[', '(').replace(']', ')'));
- }
-
- @Query("UPDATE metadata SET seen = :seen WHERE profileId = :profileId AND (thingType = "+TYPE_EVENT+" OR thingType = "+TYPE_LESSON_CHANGE+" OR thingType = "+TYPE_HOMEWORK+") AND thingId IN (SELECT eventId FROM events WHERE profileId = :profileId AND eventDate = :date)")
- public abstract void setSeenByDate(int profileId, Date date, boolean seen);
-
- @Query("UPDATE events SET eventBlacklisted = :blacklisted WHERE profileId = :profileId AND eventId = :eventId")
- public abstract void setBlacklisted(int profileId, long eventId, boolean blacklisted);
-}
-
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt
new file mode 100644
index 00000000..a532602b
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventDao.kt
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-1-6
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.room.Transaction
+import androidx.sqlite.db.SimpleSQLiteQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
+import pl.szczodrzynski.edziennik.data.db.entity.Event
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.EventFull
+import pl.szczodrzynski.edziennik.utils.models.Date
+import pl.szczodrzynski.edziennik.utils.models.Time
+
+@Dao
+@SelectiveDao(db = AppDb::class)
+abstract class EventDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *,
+ teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName,
+ eventTypes.eventTypeName AS typeName,
+ eventTypes.eventTypeColor AS typeColor
+ FROM events
+ LEFT JOIN teachers USING(profileId, teacherId)
+ LEFT JOIN subjects USING(profileId, subjectId)
+ LEFT JOIN teams USING(profileId, teamId)
+ LEFT JOIN eventTypes USING(profileId, eventType)
+ LEFT JOIN metadata ON eventId = thingId AND (thingType = ${Metadata.TYPE_EVENT} OR thingType = ${Metadata.TYPE_HOMEWORK}) AND metadata.profileId = events.profileId
+ """
+
+ private const val ORDER_BY = """GROUP BY eventId ORDER BY eventDate, eventTime, addedDate ASC"""
+ private const val NOT_BLACKLISTED = """events.eventBlacklisted = 0"""
+ private const val NOT_DONE = """events.eventIsDone = 0"""
+ }
+
+ private val selective by lazy { EventDaoSelective(App.db) }
+
+ @RawQuery(observedEntities = [Event::class])
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [Event::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
+
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "eventId"], skippedColumns = ["eventIsDone", "eventBlacklisted", "homeworkBody", "attachmentIds", "attachmentNames"])
+ override fun update(item: Event) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
+
+ // CLEAR
+ @Query("DELETE FROM events WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM events WHERE keep = 0")
+ abstract override fun removeNotKept()
+
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId $ORDER_BY")
+ fun getAllByType(profileId: Int, type: Long, filter: String = "1") =
+ getRaw("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND eventType = $type AND $filter $ORDER_BY")
+ fun getAllByDate(profileId: Int, date: Date) =
+ getRaw("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND eventDate = '${date.stringY_m_d}' $ORDER_BY")
+ fun getAllByDateTime(profileId: Int, date: Date, time: Time) =
+ getRaw("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND eventDate = '${date.stringY_m_d}' AND eventTime = '${time.stringValue}' $ORDER_BY")
+ fun getNearestNotDone(profileId: Int, today: Date, limit: Int) =
+ getRaw("$QUERY WHERE $NOT_BLACKLISTED AND $NOT_DONE AND events.profileId = $profileId AND eventDate >= '${today.stringY_m_d}' $ORDER_BY LIMIT $limit")
+
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE $NOT_BLACKLISTED AND notified = 0 $ORDER_BY")
+ fun getNotNotifiedNow(profileId: Int) =
+ getRawNow("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND notified = 0 $ORDER_BY")
+ fun getAllByDateNow(profileId: Int, date: Date) =
+ getRawNow("$QUERY WHERE $NOT_BLACKLISTED AND events.profileId = $profileId AND eventDate = '${date.stringY_m_d}' $ORDER_BY")
+
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE events.profileId = $profileId AND eventId = $id")
+
+
+ @Query("SELECT eventId FROM events WHERE profileId = :profileId AND eventBlacklisted = 1")
+ abstract fun getBlacklistedIds(profileId: Int): List
+
+ @get:Query("SELECT eventId FROM events WHERE eventBlacklisted = 1")
+ abstract val blacklistedIds: List
+
+ /*@Query("UPDATE events SET eventAddedManually = 1 WHERE profileId = :profileId AND eventDate < :date")
+ abstract fun convertOlderToManual(profileId: Int, date: Date?)
+
+ @Query("DELETE FROM events WHERE teamId = :teamId AND eventId = :id")
+ abstract fun removeByTeamId(teamId: Long, id: Long)
+
+ @Query("DELETE FROM events WHERE profileId = :profileId AND eventAddedManually = 0")
+ abstract fun removeNotManual(profileId: Int)*/
+
+ @RawQuery
+ abstract fun dontKeepFuture(query: SupportSQLiteQuery?): Long
+
+ @Transaction
+ open fun dontKeepFuture(profileId: Int, todayDate: Date, filter: String) {
+ dontKeepFuture(SimpleSQLiteQuery("UPDATE events SET keep = 0 WHERE profileId = " + profileId
+ + " AND eventAddedManually = 0 AND eventDate >= '" + todayDate.stringY_m_d + "'" +
+ " AND " + filter))
+ }
+
+ @Query("UPDATE events SET keep = 0 WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate")
+ abstract fun dontKeepFuture(profileId: Int, todayDate: Date)
+
+ @Query("UPDATE events SET keep = 0 WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType = :type")
+ abstract fun dontKeepFutureWithType(profileId: Int, todayDate: Date, type: Long)
+
+ @Query("UPDATE events SET keep = 0 WHERE profileId = :profileId AND eventAddedManually = 0 AND eventDate >= :todayDate AND eventType != :exceptType")
+ abstract fun dontKeepFutureExceptType(profileId: Int, todayDate: Date, exceptType: Long)
+
+ @Transaction
+ open fun dontKeepFutureExceptTypes(profileId: Int, todayDate: Date, exceptTypes: List) {
+ dontKeepFuture(profileId, todayDate, "eventType NOT IN " + exceptTypes.toString().replace('[', '(').replace(']', ')'))
+ }
+
+ @Query("UPDATE metadata SET seen = :seen WHERE profileId = :profileId AND (thingType = " + Metadata.TYPE_EVENT + " OR thingType = " + Metadata.TYPE_LESSON_CHANGE + " OR thingType = " + Metadata.TYPE_HOMEWORK + ") AND thingId IN (SELECT eventId FROM events WHERE profileId = :profileId AND eventDate = :date)")
+ abstract fun setSeenByDate(profileId: Int, date: Date, seen: Boolean)
+
+ @Query("UPDATE events SET eventBlacklisted = :blacklisted WHERE profileId = :profileId AND eventId = :eventId")
+ abstract fun setBlacklisted(profileId: Int, eventId: Long, blacklisted: Boolean)
+
+ @Query("DELETE FROM events WHERE profileId = :profileId AND eventId = :id")
+ abstract fun remove(profileId: Int, id: Long)
+
+ @Query("DELETE FROM metadata WHERE profileId = :profileId AND thingType = :thingType AND thingId = :thingId")
+ abstract fun removeMetadata(profileId: Int, thingType: Int, thingId: Long)
+
+ @Transaction
+ open fun remove(profileId: Int, type: Long, id: Long) {
+ remove(profileId, id)
+ removeMetadata(profileId, if (type == Event.TYPE_HOMEWORK) Metadata.TYPE_HOMEWORK else Metadata.TYPE_EVENT, id)
+ }
+
+ @Transaction
+ open fun remove(event: Event) {
+ remove(event.profileId, event.type, event.id)
+ }
+
+ @Transaction
+ open fun remove(profileId: Int, event: Event) {
+ remove(profileId, event.type, event.id)
+ }
+
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.java
deleted file mode 100644
index 25366699..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.EventType;
-
-@Dao
-public interface EventTypeDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void add(EventType gradeCategory);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- void addAll(List gradeCategoryList);
-
- @Query("DELETE FROM eventTypes WHERE profileId = :profileId")
- void clear(int profileId);
-
- @Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId")
- EventType getByIdNow(int profileId, long typeId);
-
- @Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
- LiveData> getAll(int profileId);
-
- @Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
- List getAllNow(int profileId);
-
- @Query("SELECT * FROM eventTypes")
- List getAllNow();
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.kt
new file mode 100644
index 00000000..28be6d65
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/EventTypeDao.kt
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2020-1-6
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import android.content.Context
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.OnConflictStrategy
+import androidx.room.Query
+import pl.szczodrzynski.edziennik.R
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_CLASS_EVENT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_DEFAULT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_ESSAY
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_EXAM
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_EXCURSION
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_HOMEWORK
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_INFORMATION
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_PROJECT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_PT_MEETING
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_READING
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.COLOR_SHORT_QUIZ
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_CLASS_EVENT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_DEFAULT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_ESSAY
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_EXAM
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_EXCURSION
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_HOMEWORK
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_INFORMATION
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_PROJECT
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_PT_MEETING
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_READING
+import pl.szczodrzynski.edziennik.data.db.entity.Event.Companion.TYPE_SHORT_QUIZ
+import pl.szczodrzynski.edziennik.data.db.entity.EventType
+
+@Dao
+abstract class EventTypeDao {
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ abstract fun add(eventType: EventType)
+
+ @Insert(onConflict = OnConflictStrategy.REPLACE)
+ abstract fun addAll(eventTypeList: List)
+
+ @Query("DELETE FROM eventTypes WHERE profileId = :profileId")
+ abstract fun clear(profileId: Int)
+
+ @Query("SELECT * FROM eventTypes WHERE profileId = :profileId AND eventType = :typeId")
+ abstract fun getByIdNow(profileId: Int, typeId: Long): EventType?
+
+ @Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
+ abstract fun getAll(profileId: Int): LiveData>
+
+ @Query("SELECT * FROM eventTypes WHERE profileId = :profileId")
+ abstract fun getAllNow(profileId: Int): List
+
+ @get:Query("SELECT * FROM eventTypes")
+ abstract val allNow: List
+
+ fun addDefaultTypes(context: Context, profileId: Int): List {
+ val typeList = listOf(
+ EventType(profileId, TYPE_HOMEWORK, context.getString(R.string.event_type_homework), COLOR_HOMEWORK),
+ EventType(profileId, TYPE_DEFAULT, context.getString(R.string.event_other), COLOR_DEFAULT),
+ EventType(profileId, TYPE_EXAM, context.getString(R.string.event_exam), COLOR_EXAM),
+ EventType(profileId, TYPE_SHORT_QUIZ, context.getString(R.string.event_short_quiz), COLOR_SHORT_QUIZ),
+ EventType(profileId, TYPE_ESSAY, context.getString(R.string.event_essay), COLOR_ESSAY),
+ EventType(profileId, TYPE_PROJECT, context.getString(R.string.event_project), COLOR_PROJECT),
+ EventType(profileId, TYPE_PT_MEETING, context.getString(R.string.event_pt_meeting), COLOR_PT_MEETING),
+ EventType(profileId, TYPE_EXCURSION, context.getString(R.string.event_excursion), COLOR_EXCURSION),
+ EventType(profileId, TYPE_READING, context.getString(R.string.event_reading), COLOR_READING),
+ EventType(profileId, TYPE_CLASS_EVENT, context.getString(R.string.event_class_event), COLOR_CLASS_EVENT),
+ EventType(profileId, TYPE_INFORMATION, context.getString(R.string.event_information), COLOR_INFORMATION)
+ )
+ addAll(typeList)
+ return typeList
+ }
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt
index 9c3e93c5..4fcfc721 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/GradeDao.kt
@@ -1,102 +1,103 @@
/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
+ * Copyright (c) Kuba Szczodrzyński 2020-4-24.
*/
package pl.szczodrzynski.edziennik.data.db.dao
import androidx.lifecycle.LiveData
-import androidx.room.*
-import androidx.sqlite.db.SimpleSQLiteQuery
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.room.Transaction
import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.GradeFull
+import pl.szczodrzynski.edziennik.utils.models.Date
import java.util.*
-import kotlin.collections.List
import kotlin.collections.component1
import kotlin.collections.component2
-import kotlin.collections.iterator
import kotlin.collections.set
@Dao
-abstract class GradeDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- abstract fun add(grade: Grade): Long
+@SelectiveDao(db = AppDb::class)
+abstract class GradeDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *,
+ teachers.teacherName ||" "|| teachers.teacherSurname AS teacherName
+ FROM grades
+ LEFT JOIN teachers USING(profileId, teacherId)
+ LEFT JOIN subjects USING(profileId, subjectId)
+ LEFT JOIN metadata ON gradeId = thingId AND thingType = ${Metadata.TYPE_GRADE} AND metadata.profileId = grades.profileId
+ """
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- abstract fun addAll(gradeList: List)
+ private const val ORDER_BY = """ORDER BY addedDate DESC"""
+ }
- @Query("DELETE FROM grades WHERE profileId = :profileId")
- abstract fun clear(profileId: Int)
-
- @Query("DELETE FROM grades WHERE profileId = :profileId AND gradeType = :type")
- abstract fun clearWithType(profileId: Int, type: Int)
-
- @Query("DELETE FROM grades WHERE profileId = :profileId AND gradeSemester = :semester")
- abstract fun clearForSemester(profileId: Int, semester: Int)
-
- @Query("DELETE FROM grades WHERE profileId = :profileId AND gradeSemester = :semester AND gradeType = :type")
- abstract fun clearForSemesterWithType(profileId: Int, semester: Int, type: Int)
+ private val selective by lazy { GradeDaoSelective(App.db) }
@RawQuery(observedEntities = [Grade::class])
- abstract fun getAll(query: SupportSQLiteQuery?): LiveData>
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [Grade::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
- fun getAll(profileId: Int, filter: String, orderBy: String): LiveData> {
- return getAll(SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM grades \n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = " + profileId + "\n" +
- "WHERE grades.profileId = " + profileId + " AND " + filter + "\n" +
- "ORDER BY " + orderBy)) // TODO: 2019-04-30 why did I add sorting by gradeType???
- }
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "gradeId"], skippedColumns = ["addedDate", "gradeClassAverage"])
+ override fun update(item: Grade) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
- fun getAllOrderBy(profileId: Int, orderBy: String): LiveData> {
- return getAll(profileId, "1", orderBy)
- }
+ // CLEAR
+ @Query("DELETE FROM grades WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM grades WHERE keep = 0")
+ abstract override fun removeNotKept()
- fun getAllWhere(profileId: Int, filter: String): LiveData> {
- return getAll(profileId, filter, "addedDate DESC")
- }
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE grades.profileId = $profileId $ORDER_BY")
+ fun getAllFromDate(profileId: Int, date: Date) =
+ getRaw("$QUERY WHERE grades.profileId = $profileId AND addedDate > ${date.inMillis} $ORDER_BY")
+ fun getAllBySubject(profileId: Int, subjectId: Long) =
+ getRaw("$QUERY WHERE grades.profileId = $profileId AND subjectId = $subjectId $ORDER_BY")
+ fun getAllOrderBy(profileId: Int, orderBy: String) =
+ getRaw("$QUERY WHERE grades.profileId = $profileId ORDER BY $orderBy")
- @RawQuery
- abstract fun getAllNow(query: SupportSQLiteQuery?): List
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE grades.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
+ fun getNotNotifiedNow(profileId: Int) =
+ getRawNow("$QUERY WHERE grades.profileId = $profileId AND notified = 0 $ORDER_BY")
+ fun getByParentIdNow(profileId: Int, parentId: Long) =
+ getRawNow("$QUERY WHERE grades.profileId = $profileId AND gradeParentId = $parentId $ORDER_BY")
- fun getAllNow(profileId: Int, filter: String): List {
- return getAllNow(SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS teacherFullName\n" +
- "FROM grades \n" +
- "LEFT JOIN subjects USING(profileId, subjectId)\n" +
- "LEFT JOIN teachers USING(profileId, teacherId)\n" +
- "LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = " + profileId + "\n" +
- "WHERE grades.profileId = " + profileId + " AND " + filter + "\n" +
- "ORDER BY addedDate DESC"))
- }
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE grades.profileId = $profileId AND gradeId = $id")
- fun getNotNotifiedNow(profileId: Int): List {
- return getAllNow(profileId, "notified = 0")
- }
+ @Query("UPDATE grades SET keep = 0 WHERE profileId = :profileId AND gradeType = :type")
+ abstract fun dontKeepWithType(profileId: Int, type: Int)
- fun getAllWithParentIdNow(profileId: Int, parentId: Long): List {
- return getAllNow(profileId, "gradeParentId = $parentId")
- }
+ @Query("UPDATE grades SET keep = 0 WHERE profileId = :profileId AND gradeSemester = :semester")
+ abstract fun dontKeepForSemester(profileId: Int, semester: Int)
- @get:Query("SELECT * FROM grades " +
- "LEFT JOIN subjects USING(profileId, subjectId) " +
- "LEFT JOIN metadata ON gradeId = thingId AND thingType = " + Metadata.TYPE_GRADE + " AND metadata.profileId = grades.profileId " +
- "WHERE notified = 0 " +
- "ORDER BY addedDate DESC")
- abstract val notNotifiedNow: List
+ @Query("UPDATE grades SET keep = 0 WHERE profileId = :profileId AND gradeSemester = :semester AND gradeType = :type")
+ abstract fun dontKeepForSemesterWithType(profileId: Int, semester: Int, type: Int)
- @RawQuery
- abstract fun getNow(query: SupportSQLiteQuery): GradeFull?
+
+ // GRADE DETAILS - MOBIDZIENNIK
@Query("UPDATE grades SET gradeClassAverage = :classAverage, gradeColor = :color WHERE profileId = :profileId AND gradeId = :gradeId")
abstract fun updateDetailsById(profileId: Int, gradeId: Long, classAverage: Float, color: Int)
- @Query("UPDATE metadata SET addedDate = :addedDate WHERE profileId = :profileId AND thingType = " + Metadata.TYPE_GRADE + " AND thingId = :gradeId")
+ @Query("UPDATE grades SET addedDate = :addedDate WHERE profileId = :profileId AND gradeId = :gradeId")
abstract fun updateAddedDateById(profileId: Int, gradeId: Long, addedDate: Long)
@Transaction
@@ -118,7 +119,7 @@ abstract class GradeDao {
@Query("SELECT gradeColor FROM grades WHERE profileId = :profileId ORDER BY gradeId")
abstract fun getColors(profileId: Int): List
- @Query("SELECT addedDate FROM metadata WHERE profileId = :profileId AND thingType = " + Metadata.TYPE_GRADE + " ORDER BY thingId")
+ @Query("SELECT addedDate FROM grades WHERE profileId = :profileId ORDER BY gradeId")
abstract fun getAddedDates(profileId: Int): List
@Transaction
@@ -134,8 +135,4 @@ abstract class GradeDao {
gradeAddedDates[gradeId] = addedDates.next()
}
}
-
- fun getAllFromDate(profileId: Int, date: Long): LiveData> {
- return getAllWhere(profileId, "addedDate > $date")
- }
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.java
deleted file mode 100644
index c1c33c23..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.annotation.Nullable;
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber;
-import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
-import pl.szczodrzynski.edziennik.data.db.entity.Notice;
-import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull;
-import pl.szczodrzynski.edziennik.utils.models.Date;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_LUCKY_NUMBER;
-
-@Dao
-public abstract class LuckyNumberDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void add(LuckyNumber luckyNumber);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void addAll(List luckyNumberList);
-
- @Query("DELETE FROM luckyNumbers WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate = :date")
- public abstract LiveData getByDate(int profileId, Date date);
-
- @Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate = :date")
- public abstract LuckyNumber getByDateNow(int profileId, Date date);
-
- @Nullable
- @Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate >= :date ORDER BY luckyNumberDate DESC LIMIT 1")
- public abstract LuckyNumber getNearestFutureNow(int profileId, int date);
-
- @Query("SELECT * FROM luckyNumbers WHERE profileId = :profileId AND luckyNumberDate >= :date ORDER BY luckyNumberDate DESC LIMIT 1")
- public abstract LiveData getNearestFuture(int profileId, int date);
-
- @RawQuery(observedEntities = {LuckyNumber.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- public LiveData> getAll(int profileId, String filter) {
- return getAll(new SimpleSQLiteQuery("SELECT\n" +
- "*\n" +
- "FROM luckyNumbers\n" +
- "LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE luckyNumbers.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
- public LiveData> getAll(int profileId) {
- return getAll(profileId, "1");
- }
- public LiveData> getAllWhere(int profileId, String filter) {
- return getAll(profileId, filter);
- }
-
- @RawQuery(observedEntities = {Notice.class, Metadata.class})
- abstract List getAllNow(SupportSQLiteQuery query);
- public List getAllNow(int profileId, String filter) {
- return getAllNow(new SimpleSQLiteQuery("SELECT\n" +
- "*\n" +
- "FROM luckyNumbers\n" +
- "LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE luckyNumbers.profileId = "+profileId+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
- public List getNotNotifiedNow(int profileId) {
- return getAllNow(profileId, "notified = 0");
- }
-
- @Query("SELECT * FROM luckyNumbers\n" +
- "LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = "+TYPE_LUCKY_NUMBER+" AND metadata.profileId = luckyNumbers.profileId " +
- "WHERE notified = 0 " +
- "ORDER BY addedDate DESC")
- public abstract List getNotNotifiedNow();
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt
new file mode 100644
index 00000000..ad44c0d3
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/LuckyNumberDao.kt
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-25.
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
+import pl.szczodrzynski.edziennik.data.db.entity.LuckyNumber
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.LuckyNumberFull
+import pl.szczodrzynski.edziennik.utils.models.Date
+
+@Dao
+@SelectiveDao(db = AppDb::class)
+abstract class LuckyNumberDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *
+ FROM luckyNumbers
+ LEFT JOIN metadata ON luckyNumberDate = thingId AND thingType = ${Metadata.TYPE_LUCKY_NUMBER} AND metadata.profileId = luckyNumbers.profileId
+ """
+
+ private const val ORDER_BY = """ORDER BY luckyNumberDate DESC"""
+ }
+
+ private val selective by lazy { LuckyNumberDaoSelective(App.db) }
+
+ @RawQuery(observedEntities = [LuckyNumber::class])
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [LuckyNumber::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
+
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "luckyNumberDate"], skippedColumns = ["addedDate"])
+ override fun update(item: LuckyNumber) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
+
+ // CLEAR
+ @Query("DELETE FROM luckyNumbers WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM luckyNumbers WHERE keep = 0")
+ abstract override fun removeNotKept()
+
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE luckyNumbers.profileId = $profileId $ORDER_BY")
+
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE luckyNumbers.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE notified = 0 $ORDER_BY")
+ fun getNotNotifiedNow(profileId: Int) =
+ getRawNow("$QUERY WHERE luckyNumbers.profileId = $profileId AND notified = 0 $ORDER_BY")
+
+ // GET ONE - LIVE DATA
+ fun getNearestFuture(profileId: Int, today: Date) =
+ getOne("$QUERY WHERE luckyNumbers.profileId = $profileId AND luckyNumberDate >= ${today.value} $ORDER_BY LIMIT 1")
+
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE attendances.profileId = $profileId AND attendanceId = $id")
+ fun getNearestFutureNow(profileId: Int, today: Date) =
+ getOneNow("$QUERY WHERE luckyNumbers.profileId = $profileId AND luckyNumberDate >= ${today.value} $ORDER_BY LIMIT 1")
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java
deleted file mode 100644
index bc3a46a5..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.annotation.Nullable;
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.Message;
-import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
-import pl.szczodrzynski.edziennik.data.db.full.MessageFull;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_DELETED;
-import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED;
-import static pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_SENT;
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_MESSAGE;
-
-@Dao
-public abstract class MessageDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long add(Message message);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void addAll(List messageList);
-
- @Insert(onConflict = OnConflictStrategy.IGNORE)
- public abstract void addAllIgnore(List messageList);
-
- @Query("DELETE FROM messages WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @RawQuery(observedEntities = {Message.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- @RawQuery(observedEntities = {Message.class, Metadata.class})
- abstract List getNow(SupportSQLiteQuery query);
- @RawQuery(observedEntities = {Message.class, Metadata.class})
- abstract MessageFull getOneNow(SupportSQLiteQuery query);
-
- public LiveData> getWithMetadataAndSenderName(int profileId, int messageType, String filter) {
- return getAll(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" +
- "FROM messages \n" +
- "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" +
- "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE messages.profileId = "+profileId+" AND messageType = "+messageType+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
-
- public LiveData> getWithMetadata(int profileId, int messageType, String filter) {
- return getAll(new SimpleSQLiteQuery("SELECT \n" +
- "* \n" +
- "FROM messages \n" +
- "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE messages.profileId = "+profileId+" AND messageType = "+messageType+" AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
-
- @Nullable
- public MessageFull getById(int profileId, long messageId) {
- return getOneNow(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" +
- "FROM messages \n" +
- "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" +
- "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE messages.profileId = "+profileId+" AND messageId = "+messageId+"\n" +
- "ORDER BY addedDate DESC"));
- }
-
- public LiveData> getReceived(int profileId) {
- return getWithMetadataAndSenderName(profileId, TYPE_RECEIVED, "1");
- }
- public LiveData> getDeleted(int profileId) {
- return getWithMetadataAndSenderName(profileId, TYPE_DELETED, "1");
- }
- public LiveData> getSent(int profileId) {
- return getWithMetadata(profileId, TYPE_SENT, "1");
- }
-
- public List getReceivedNow(int profileId, String filter) {
- return getNow(new SimpleSQLiteQuery("SELECT \n" +
- "*, \n" +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName\n" +
- "FROM messages \n" +
- "LEFT JOIN teachers ON teachers.profileId = "+profileId+" AND teacherId = senderId\n" +
- "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = "+profileId+"\n" +
- "WHERE messages.profileId = "+profileId+" AND messageType = 0 AND "+filter+"\n" +
- "ORDER BY addedDate DESC"));
- }
- public List getReceivedNotNotifiedNow(int profileId) {
- return getReceivedNow(profileId, "notified = 0");
- }
-
- @Query("SELECT " +
- "*, " +
- "teachers.teacherName || ' ' || teachers.teacherSurname AS senderFullName " +
- "FROM messages " +
- "LEFT JOIN teachers ON teachers.profileId = messages.profileId AND teacherId = senderId " +
- "LEFT JOIN metadata ON messageId = thingId AND thingType = "+TYPE_MESSAGE+" AND metadata.profileId = messages.profileId " +
- "WHERE messageType = 0 AND notified = 0 " +
- "ORDER BY addedDate DESC")
- public abstract List getReceivedNotNotifiedNow();
-}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt
new file mode 100644
index 00000000..a0be36ab
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MessageDao.kt
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) Kuba Szczodrzyński 2020-4-25.
+ */
+package pl.szczodrzynski.edziennik.data.db.dao
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Query
+import androidx.room.RawQuery
+import androidx.sqlite.db.SupportSQLiteQuery
+import pl.szczodrzynski.edziennik.App
+import pl.szczodrzynski.edziennik.annotation.SelectiveDao
+import pl.szczodrzynski.edziennik.annotation.UpdateSelective
+import pl.szczodrzynski.edziennik.data.db.AppDb
+import pl.szczodrzynski.edziennik.data.db.entity.Message
+import pl.szczodrzynski.edziennik.data.db.entity.Metadata
+import pl.szczodrzynski.edziennik.data.db.full.MessageFull
+
+@Dao
+@SelectiveDao(db = AppDb::class)
+abstract class MessageDao : BaseDao {
+ companion object {
+ private const val QUERY = """
+ SELECT
+ *,
+ teachers.teacherName ||" "|| teachers.teacherSurname AS senderName
+ FROM messages
+ LEFT JOIN teachers ON teachers.profileId = messages.profileId AND teacherId = senderId
+ LEFT JOIN metadata ON messageId = thingId AND thingType = ${Metadata.TYPE_MESSAGE} AND metadata.profileId = messages.profileId
+ """
+
+ private const val ORDER_BY = """ORDER BY messageIsPinned, addedDate DESC"""
+ }
+
+ private val selective by lazy { MessageDaoSelective(App.db) }
+
+ @RawQuery(observedEntities = [Message::class])
+ abstract override fun getRaw(query: SupportSQLiteQuery): LiveData>
+ @RawQuery(observedEntities = [Message::class])
+ abstract override fun getOne(query: SupportSQLiteQuery): LiveData
+
+ // SELECTIVE UPDATE
+ @UpdateSelective(primaryKeys = ["profileId", "messageId"], skippedColumns = ["messageType", "messageBody", "messageIsPinned", "attachmentIds", "attachmentNames", "attachmentSizes"])
+ override fun update(item: Message) = selective.update(item)
+ override fun updateAll(items: List) = selective.updateAll(items)
+
+ // CLEAR
+ @Query("DELETE FROM messages WHERE profileId = :profileId")
+ abstract override fun clear(profileId: Int)
+ // REMOVE NOT KEPT
+ @Query("DELETE FROM messages WHERE keep = 0")
+ abstract override fun removeNotKept()
+
+ // GET ALL - LIVE DATA
+ fun getAll(profileId: Int) =
+ getRaw("$QUERY WHERE messages.profileId = $profileId $ORDER_BY")
+ fun getAllByType(profileId: Int, type: Int) =
+ getRaw("$QUERY WHERE messages.profileId = $profileId AND messageType = $type $ORDER_BY")
+ fun getReceived(profileId: Int) = getAllByType(profileId, Message.TYPE_RECEIVED)
+ fun getSent(profileId: Int) = getAllByType(profileId, Message.TYPE_SENT)
+ fun getDeleted(profileId: Int) = getAllByType(profileId, Message.TYPE_DELETED)
+ fun getDraft(profileId: Int) = getAllByType(profileId, Message.TYPE_DRAFT)
+
+ // GET ALL - NOW
+ fun getAllNow(profileId: Int) =
+ getRawNow("$QUERY WHERE messages.profileId = $profileId $ORDER_BY")
+ fun getNotNotifiedNow() =
+ getRawNow("$QUERY WHERE notified = 0 AND messageType = ${Message.TYPE_RECEIVED} $ORDER_BY")
+
+ // GET ONE - NOW
+ fun getByIdNow(profileId: Int, id: Long) =
+ getOneNow("$QUERY WHERE messages.profileId = $profileId AND messageId = $id")
+
+
+}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java
index 845941de..eac92f21 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/MetadataDao.java
@@ -63,38 +63,38 @@ public abstract class MetadataDao {
@Transaction
public void setSeen(int profileId, Object o, boolean seen) {
if (o instanceof Grade) {
- if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), seen, false, 0)) == -1) {
+ if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_GRADE, ((Grade) o).getId(), seen);
}
}
if (o instanceof Attendance) {
- if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, seen, false, 0)) == -1) {
- updateSeen(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, seen);
+ if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), seen, false)) == -1) {
+ updateSeen(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), seen);
}
}
if (o instanceof Notice) {
- if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).id, seen, false, 0)) == -1) {
- updateSeen(profileId, TYPE_NOTICE, ((Notice) o).id, seen);
+ if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).getId(), seen, false)) == -1) {
+ updateSeen(profileId, TYPE_NOTICE, ((Notice) o).getId(), seen);
}
}
if (o instanceof Event) {
- if (add(new Metadata(profileId, ((Event) o).type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).id, seen, false, 0)) == -1) {
- updateSeen(profileId, ((Event) o).type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).id, seen);
+ if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), seen, false)) == -1) {
+ updateSeen(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), seen);
}
}
if (o instanceof LessonFull) {
- if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen, false, 0)) == -1) {
+ if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen, false)) == -1) {
updateSeen(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), seen);
}
}
if (o instanceof Announcement) {
- if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, seen, false, 0)) == -1) {
- updateSeen(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, seen);
+ if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), seen, false)) == -1) {
+ updateSeen(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), seen);
}
}
if (o instanceof Message) {
- if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).id, seen, false, 0)) == -1) {
- updateSeen(profileId, TYPE_MESSAGE, ((Message) o).id, seen);
+ if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen, false)) == -1) {
+ updateSeen(profileId, TYPE_MESSAGE, ((Message) o).getId(), seen);
}
}
}
@@ -102,38 +102,38 @@ public abstract class MetadataDao {
@Transaction
public void setNotified(int profileId, Object o, boolean notified) {
if (o instanceof Grade) {
- if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), false, notified, 0)) == -1) {
+ if (add(new Metadata(profileId, TYPE_GRADE, ((Grade) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_GRADE, ((Grade) o).getId(), notified);
}
}
if (o instanceof Attendance) {
- if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, false, notified, 0)) == -1) {
- updateNotified(profileId, TYPE_ATTENDANCE, ((Attendance) o).id, notified);
+ if (add(new Metadata(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), false, notified)) == -1) {
+ updateNotified(profileId, TYPE_ATTENDANCE, ((Attendance) o).getId(), notified);
}
}
if (o instanceof Notice) {
- if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).id, false, notified, 0)) == -1) {
- updateNotified(profileId, TYPE_NOTICE, ((Notice) o).id, notified);
+ if (add(new Metadata(profileId, TYPE_NOTICE, ((Notice) o).getId(), false, notified)) == -1) {
+ updateNotified(profileId, TYPE_NOTICE, ((Notice) o).getId(), notified);
}
}
if (o instanceof Event) {
- if (add(new Metadata(profileId, ((Event) o).type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).id, false, notified, 0)) == -1) {
- updateNotified(profileId, ((Event) o).type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).id, notified);
+ if (add(new Metadata(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), false, notified)) == -1) {
+ updateNotified(profileId, ((Event) o).getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, ((Event) o).getId(), notified);
}
}
if (o instanceof LessonFull) {
- if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), false, notified, 0)) == -1) {
+ if (add(new Metadata(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), false, notified)) == -1) {
updateNotified(profileId, TYPE_LESSON_CHANGE, ((LessonFull) o).getId(), notified);
}
}
if (o instanceof Announcement) {
- if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, false, notified, 0)) == -1) {
- updateNotified(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).id, notified);
+ if (add(new Metadata(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), false, notified)) == -1) {
+ updateNotified(profileId, TYPE_ANNOUNCEMENT, ((Announcement) o).getId(), notified);
}
}
if (o instanceof Message) {
- if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).id, false, notified, 0)) == -1) {
- updateNotified(profileId, TYPE_MESSAGE, ((Message) o).id, notified);
+ if (add(new Metadata(profileId, TYPE_MESSAGE, ((Message) o).getId(), false, notified)) == -1) {
+ updateNotified(profileId, TYPE_MESSAGE, ((Message) o).getId(), notified);
}
}
}
@@ -141,9 +141,9 @@ public abstract class MetadataDao {
@Transaction
public void setBoth(int profileId, Event o, boolean seen, boolean notified, long addedDate) {
if (o != null) {
- if (add(new Metadata(profileId, o.type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.id, seen, notified, addedDate)) == -1) {
- updateSeen(profileId, o.type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.id, seen);
- updateNotified(profileId, o.type == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.id, notified);
+ if (add(new Metadata(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), seen, notified)) == -1) {
+ updateSeen(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), seen);
+ updateNotified(profileId, o.getType() == Event.TYPE_HOMEWORK ? TYPE_HOMEWORK : TYPE_EVENT, o.getId(), notified);
}
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.java b/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.java
deleted file mode 100644
index 110544e4..00000000
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/db/dao/NoticeDao.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) Kacper Ziubryniewicz 2020-1-6
- */
-
-package pl.szczodrzynski.edziennik.data.db.dao;
-
-import androidx.lifecycle.LiveData;
-import androidx.room.Dao;
-import androidx.room.Insert;
-import androidx.room.OnConflictStrategy;
-import androidx.room.Query;
-import androidx.room.RawQuery;
-import androidx.sqlite.db.SimpleSQLiteQuery;
-import androidx.sqlite.db.SupportSQLiteQuery;
-
-import java.util.List;
-
-import pl.szczodrzynski.edziennik.data.db.entity.Metadata;
-import pl.szczodrzynski.edziennik.data.db.entity.Notice;
-import pl.szczodrzynski.edziennik.data.db.full.NoticeFull;
-
-import static pl.szczodrzynski.edziennik.data.db.entity.Metadata.TYPE_NOTICE;
-
-@Dao
-public abstract class NoticeDao {
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract long add(Notice notice);
-
- @Insert(onConflict = OnConflictStrategy.REPLACE)
- public abstract void addAll(List noticeList);
-
- @Query("DELETE FROM notices WHERE profileId = :profileId")
- public abstract void clear(int profileId);
-
- @Query("DELETE FROM notices WHERE profileId = :profileId AND noticeSemester = :semester")
- public abstract void clearForSemester(int profileId, int semester);
-
- @RawQuery(observedEntities = {Notice.class})
- abstract LiveData> getAll(SupportSQLiteQuery query);
- public LiveData