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) + """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")