diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt
index 4bd50da0..ccfd2301 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Regexes.kt
@@ -4,6 +4,8 @@
package pl.szczodrzynski.edziennik.data.api
+import kotlin.text.RegexOption.DOT_MATCHES_ALL
+
object Regexes {
val STYLE_CSS_COLOR by lazy {
"""color: \w+?;?"?""".toRegex()
@@ -12,69 +14,69 @@ object Regexes {
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
- """
\n*\s*(.+?)\s*\n*(?:<.*?)??""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """\n*\s*(.+?)\s*\n*(?:<.*?)??""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_COLOR by lazy {
- """background-color:([#A-Fa-f0-9]+);""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """background-color:([#A-Fa-f0-9]+);""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_CATEGORY by lazy {
- """> (.+?):""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """> (.+?):""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_CLASS_AVERAGE by lazy {
- """Średnia ocen:.*([0-9]*\.?[0-9]*)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Średnia ocen:.*([0-9]*\.?[0-9]*)""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_ADDED_DATE by lazy {
- """Wpisano:.*.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Wpisano:.*.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_COUNT_TO_AVG by lazy {
- """Liczona do średniej:.*?nie
""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Liczona do średniej:.*?nie
""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_GRADES_DETAILS by lazy {
- """(.+?).*?.+?.*?(?:\((.+?)\).*?)?.*?Wartość oceny:.*?([0-9.]+).*?Wpisał\(a\):.*?(.+?).*?(?:Komentarz:.*?(.+?))?""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """(.+?).*?.+?.*?(?:\((.+?)\).*?)?.*?Wartość oceny:.*?([0-9.]+).*?Wpisał\(a\):.*?(.+?).*?(?:Komentarz:.*?(.+?))?""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_EVENT_TYPE by lazy {
- """\(([0-9A-ząęóżźńśłć]*?)\)$""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """\(([0-9A-ząęóżźńśłć]*?)\)$""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_LUCKY_NUMBER by lazy {
- """class="szczesliwy_numerek".*>0*([0-9]+)(?:/0*[0-9]+)*""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """class="szczesliwy_numerek".*>0*([0-9]+)(?:/0*[0-9]+)*""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_CLASS_CALENDAR by lazy {
"""events: (.+),$""".toRegex(RegexOption.MULTILINE)
}
val MOBIDZIENNIK_MESSAGE_READ_DATE by lazy {
- """czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """czas przeczytania:.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_MESSAGE_SENT_READ_DATE by lazy {
- """.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """.+?,\s([0-9]+)\s(.+?)\s([0-9]{4}),\sgodzina\s([0-9:]+)""".toRegex(DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_MESSAGE_ATTACHMENT by lazy {
- """href="https://.+?\.mobidziennik.pl/.+?&(?:amp;)?zalacznik=([0-9]+)"(?:.+?""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_ERROR by lazy {
- """id="spanErrorMessage">(.*?)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """id="spanErrorMessage">(.*?)""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_ACCOUNT_NAME by lazy {
- """Imię i nazwisko:.+?">(.+?)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Imię i nazwisko:.+?">(.+?)""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_IS_PARENT by lazy {
"""id="ctl00_CzyRodzic" value="([01])" />""".toRegex()
}
val IDZIENNIK_LOGIN_FIRST_SCHOOL_YEAR by lazy {
- """name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """name="ctl00\${"$"}dxComboRokSzkolny".+?selected="selected".*?value="([0-9]+)">([0-9/]+)<""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_STUDENT_SELECT by lazy {
- """""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """""".toRegex(DOT_MATCHES_ALL)
}
val IDZIENNIK_LOGIN_FIRST_STUDENT by lazy {
- """(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """(.+?)\s(.+?)\s*\((.+?),\s*(.+?)\)""".toRegex(DOT_MATCHES_ALL)
}
@@ -98,6 +100,16 @@ object Regexes {
"""(.*?)""".toRegex()
}
+ val EDUDZIENNIK_ATTENDANCE_ENTRIES by lazy {
+ """(.+?) | """.toRegex()
+ }
+ val EDUDZIENNIK_ATTENDANCE_TYPES by lazy {
+ """.*?
(.*?)
""".toRegex(DOT_MATCHES_ALL)
+ }
+ val EDUDZIENNIK_ATTENDANCE_TYPE by lazy {
+ """\((.+?)\) (.+)""".toRegex()
+ }
+
val EDUDZIENNIK_SUBJECT_ID by lazy {
"""/Courses/([\w-_]+?)/""".toRegex()
}
@@ -112,15 +124,15 @@ object Regexes {
}
val EDUDZIENNIK_SCHOOL_DETAIL_ID by lazy {
- """
.*?(.*?)
.*?""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """.*?(.*?)
.*?""".toRegex(DOT_MATCHES_ALL)
}
val EDUDZIENNIK_CLASS_DETAIL_ID by lazy {
- """Klasa (.*?)""".toRegex(RegexOption.DOT_MATCHES_ALL)
+ """Klasa (.*?)""".toRegex(DOT_MATCHES_ALL)
}
}
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt
index 25835d12..33c524fc 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/EdudziennikFeatures.kt
@@ -10,6 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.models.Feature
const val ENDPOINT_EDUDZIENNIK_WEB_START = 1000
const val ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE = 1001
const val ENDPOINT_EDUDZIENNIK_WEB_EXAMS = 1002
+const val ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE = 1003
const val ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER = 1010
val EdudziennikFeatures = listOf(
@@ -29,6 +30,10 @@ val EdudziennikFeatures = listOf(
ENDPOINT_EDUDZIENNIK_WEB_EXAMS to LOGIN_METHOD_EDUDZIENNIK_WEB
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+ Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_ATTENDANCE, listOf(
+ ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE to LOGIN_METHOD_EDUDZIENNIK_WEB
+ ), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
+
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER to LOGIN_METHOD_EDUDZIENNIK_WEB
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB))
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt
index 9567d27b..c48d622c 100644
--- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikData.kt
@@ -6,10 +6,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.*
-import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebExams
-import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebLuckyNumber
-import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebStart
-import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebTimetable
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.*
import pl.szczodrzynski.edziennik.utils.Utils
class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
@@ -51,6 +48,10 @@ class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
data.startProgress(R.string.edziennik_progress_endpoint_exams)
EdudziennikWebExams(data, onSuccess)
}
+ ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE -> {
+ data.startProgress(R.string.edziennik_progress_endpoint_attendance)
+ EdudziennikWebAttendance(data, onSuccess)
+ }
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
EdudziennikWebLuckyNumber(data, onSuccess)
diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt
new file mode 100644
index 00000000..18df0181
--- /dev/null
+++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebAttendance.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) Kacper Ziubryniewicz 2019-12-24
+ */
+
+package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
+
+import pl.szczodrzynski.edziennik.crc32
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_ENTRIES
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPE
+import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_ATTENDANCE_TYPES
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE
+import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
+import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.data.db.modules.attendance.Attendance
+import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
+import pl.szczodrzynski.edziennik.get
+import pl.szczodrzynski.edziennik.singleOrNull
+import pl.szczodrzynski.edziennik.utils.models.Date
+import java.util.*
+
+class EdudziennikWebAttendance(override val data: DataEdudziennik,
+ val onSuccess: () -> Unit) : EdudziennikWeb(data) {
+ companion object {
+ private const val TAG = "EdudziennikWebAttendance"
+ }
+
+ init { data.profile?.also { profile ->
+ webGet(TAG, data.studentEndpoint + "Presence") { text ->
+
+ val attendanceTypes = EDUDZIENNIK_ATTENDANCE_TYPES.find(text)?.get(1)?.split(',')?.map {
+ val type = EDUDZIENNIK_ATTENDANCE_TYPE.find(it.trim())
+ val symbol = type?.get(1)?.trim()
+ val name = type?.get(2)?.trim()
+ return@map Triple(
+ symbol,
+ name,
+ when (name?.toLowerCase(Locale.ROOT)) {
+ "obecność" -> Attendance.TYPE_PRESENT
+ "nieobecność" -> Attendance.TYPE_ABSENT
+ "spóźnienie" -> Attendance.TYPE_BELATED
+ "nieobecność usprawiedliwiona" -> Attendance.TYPE_ABSENT_EXCUSED
+ "dzień wolny" -> Attendance.TYPE_RELEASED
+ "brak zajęć" -> Attendance.TYPE_RELEASED
+ "oddelegowany" -> Attendance.TYPE_RELEASED
+ else -> Attendance.TYPE_CUSTOM
+ }
+ )
+ } ?: emptyList()
+
+ EDUDZIENNIK_ATTENDANCE_ENTRIES.findAll(text).forEach { attendanceElement ->
+ val date = Date.fromY_m_d(attendanceElement[1])
+ val lessonNumber = attendanceElement[2].toInt()
+ val attendanceSymbol = attendanceElement[3]
+
+ val lessons = data.app.db.timetableDao().getForDateNow(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 }
+ ?: 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
+ )
+
+ data.attendanceList.add(attendanceObject)
+ data.metadataList.add(Metadata(
+ profileId,
+ Metadata.TYPE_ATTENDANCE,
+ id,
+ profile.empty,
+ profile.empty,
+ System.currentTimeMillis()
+ ))
+ }
+
+ data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_ATTENDANCE, SYNC_ALWAYS)
+ onSuccess()
+ }
+ } ?: onSuccess() }
+}
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 ef06c58e..8ac973f4 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
@@ -13,10 +13,12 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.Edudzienni
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
+import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.getString
+import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.splitName
import pl.szczodrzynski.edziennik.utils.Utils.d
import pl.szczodrzynski.edziennik.utils.models.Date
@@ -70,6 +72,12 @@ class EdudziennikWebTimetable(override val data: DataEdudziennik,
val startTime = Time.fromH_m(times[0].trim())
val endTime = Time.fromH_m(times[1].trim())
+ data.lessonRanges.singleOrNull {
+ it.lessonNumber == lessonNumber && it.startTime == startTime && it.endTime == endTime
+ } ?: run {
+ data.lessonRanges.put(lessonNumber, LessonRange(profileId, lessonNumber, startTime, endTime))
+ }
+
rowElements.subList(2, rowElements.size).forEachIndexed { index, lesson ->
val course = lesson.select(".course").firstOrNull() ?: return@forEachIndexed
val info = course.select("span > span")