From e3741f1c75cee70cd6d51801d326674a7c1a38a8 Mon Sep 17 00:00:00 2001 From: Kacper Ziubryniewicz Date: Mon, 23 Dec 2019 18:34:39 +0100 Subject: [PATCH] [API/Edudziennik] Add getting timetable. --- .../edziennik/data/api/Regexes.kt | 15 +- .../edziennik/edudziennik/DataEdudziennik.kt | 3 + .../edudziennik/EdudziennikFeatures.kt | 10 +- .../edudziennik/data/EdudziennikData.kt | 6 + .../edudziennik/data/EdudziennikWeb.kt | 2 +- .../data/web/EdudziennikWebStart.kt | 10 +- .../data/web/EdudziennikWebTimetable.kt | 149 ++++++++++++++++++ .../edudziennik/login/EdudziennikLogin.kt | 2 +- app/src/main/res/values/strings.xml | 1 + 9 files changed, 185 insertions(+), 13 deletions(-) create mode 100644 app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebTimetable.kt 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 62a09881..e928f40b 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 @@ -86,6 +86,19 @@ object Regexes { val EDUDZIENNIK_STUDENT_ID by lazy { - """/Students/(\w+?)/""".toRegex() + """/Students/([\w-_]+?)/""".toRegex() + } + val EDUDZIENNIK_SUBJECT_ID by lazy { + """/Courses/([\w-_]+?)/""".toRegex() + } + val EDUDZIENNIK_TEACHER_ID by lazy { + """/Teachers/([\w-_]+?)/""".toRegex() + } + + val EDUDZIENNIK_SCHOOL_DETAIL_ID by lazy { + """ Unit) { @@ -43,6 +45,10 @@ class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) { data.startProgress(R.string.edziennik_progress_endpoint_data) EdudziennikWebStart(data, onSuccess) } + ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE -> { + data.startProgress(R.string.edziennik_progress_endpoint_timetable) + EdudziennikWebTimetable(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/EdudziennikWeb.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt index 2538106c..c7ce1250 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/EdudziennikWeb.kt @@ -27,7 +27,7 @@ open class EdudziennikWeb(open val data: DataEdudziennik) { get() = data.profile fun webGet(tag: String, endpoint: String, xhr: Boolean = false, onSuccess: (text: String) -> Unit) { - val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.isEmpty()) { + val url = "https://dziennikel.appspot.com/" + when (endpoint.endsWith('/') || endpoint.contains('?') || endpoint.isEmpty()) { true -> endpoint else -> "$endpoint/" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt index fb018b6a..72f80fa2 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/data/web/EdudziennikWebStart.kt @@ -4,6 +4,8 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web +import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_CLASS_DETAIL_ID +import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SCHOOL_DETAIL_ID import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb @@ -18,14 +20,10 @@ class EdudziennikWebStart(override val data: DataEdudziennik, init { data.profile?.also { profile -> webGet(TAG, data.studentEndpoint + "start") { text -> - val schoolId = """ Unit) : EdudziennikWeb(data) { + companion object { + private const val TAG = "EdudziennikWebTimetable" + } + + init { data.profile?.also { profile -> + + val currentWeekStart = Week.getWeekStart() + + if (Date.getToday().weekDay > 4) { + currentWeekStart.stepForward(0, 0, 7) + } + + val getDate = data.arguments?.getString("weekStart") ?: currentWeekStart.stringY_m_d + + val weekStart = Date.fromY_m_d(getDate) + val weekEnd = weekStart.clone().stepForward(0, 0, 6) + + webGet(TAG, data.timetableEndpoint + "print?date=$getDate") { text -> + val doc = Jsoup.parse(text) + + val dataDays = mutableListOf() + val dataStart = weekStart.clone() + while (dataStart <= weekEnd) { + dataDays += dataStart.value + dataStart.stepForward(0, 0, 1) + } + + doc.select("#Schedule tbody").first().children().forEach { row -> + val rowElements = row.children() + + val lessonNumber = rowElements[0].text().toInt() + + val times = rowElements[1].text().split('-') + val startTime = Time.fromH_m(times[0].trim()) + val endTime = Time.fromH_m(times[1].trim()) + + rowElements.subList(2, rowElements.size).forEachIndexed { index, lesson -> + val course = lesson.select(".course").firstOrNull() ?: return@forEachIndexed + val info = course.select("span > span") + + if (info.size < 2) return@forEachIndexed + + val type = when (course.hasClass("substitute")) { + true -> Lesson.TYPE_CHANGE + else -> Lesson.TYPE_NORMAL + } + + /* Getting subject */ + + val subjectElement = info[0].child(0) + val subjectId = EDUDZIENNIK_SUBJECT_ID.find(subjectElement.attr("href"))?.get(1) + ?.crc32() ?: return@forEachIndexed + + val subject = data.subjectList.singleOrNull { it.id == subjectId } ?: run { + val subjectName = subjectElement.text().trim() + val subjectObject = Subject(profileId, subjectId, subjectName, subjectName) + + data.subjectList.put(subjectId, subjectObject) + subjectObject + } + + /* Getting teacher */ + + val teacherElement = info[1].child(0) + val teacherId = EDUDZIENNIK_TEACHER_ID.find(teacherElement.attr("href"))?.get(1) + ?.crc32() ?: return@forEachIndexed + + val teacher = data.teacherList.singleOrNull { it.id == teacherId } ?: run { + val teacherName = teacherElement.text().trim() + val teacherObject = teacherName.getLastFirstName()?.let { (teacherLastName, teacherFirstName) -> + Teacher(profileId, teacherId, teacherFirstName, teacherLastName) + } + + data.teacherList.put(teacherId, teacherObject) + teacherObject + } ?: return@forEachIndexed + + val lessonObject = Lesson(profileId, -1).also { + it.type = type + it.date = weekStart.clone().stepForward(0, 0, index) + it.lessonNumber = lessonNumber + it.startTime = startTime + it.endTime = endTime + it.subjectId = subject.id + it.teacherId = teacher.id + + it.id = it.buildId() + } + + data.lessonNewList.add(lessonObject) + dataDays.remove(lessonObject.date!!.value) + + if (type != Lesson.TYPE_NORMAL) { + val seen = profile.empty || lessonObject.date!! < Date.getToday() + + data.metadataList.add(Metadata( + profileId, + Metadata.TYPE_LESSON_CHANGE, + lessonObject.id, + seen, + seen, + System.currentTimeMillis() + )) + } + } + } + + for (day in dataDays) { + val lessonDate = Date.fromValue(day) + data.lessonNewList += Lesson(profileId, lessonDate.value.toLong()).apply { + type = Lesson.TYPE_NO_LESSONS + date = lessonDate + } + } + + d(TAG, "Clearing lessons between ${weekStart.stringY_m_d} and ${weekEnd.stringY_m_d} - timetable downloaded for $getDate") + + data.toRemove.add(DataRemoveModel.Timetable.between(weekStart, weekEnd)) + data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE, SYNC_ALWAYS) + onSuccess() + } + } ?: onSuccess() } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLogin.kt index 0199ebbb..1cb2fd07 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/edudziennik/login/EdudziennikLogin.kt @@ -46,7 +46,7 @@ class EdudziennikLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) { Utils.d(TAG, "Using login method $loginMethodId") when (loginMethodId) { LOGIN_METHOD_EDUDZIENNIK_WEB -> { - data.startProgress(R.string.edziennik_progress_login_template_web) + data.startProgress(R.string.edziennik_progress_login_edudziennik_web) EdudziennikLoginWeb(data) { onSuccess(loginMethodId) } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 6e810800..8d8cfceb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1128,4 +1128,5 @@ Nie ma dzisiaj więcej lekcji! Zaloguj się - Edudziennik Użyj danych, którymi logujesz się do wersji komputerowej Edudziennika. + Logowanie do Edudziennika