mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2025-01-18 21:06:44 -06:00
[API/Edudziennik] Add getting timetable.
This commit is contained in:
parent
21a6e4d8c6
commit
e3741f1c75
@ -86,6 +86,19 @@ object Regexes {
|
|||||||
|
|
||||||
|
|
||||||
val EDUDZIENNIK_STUDENT_ID by lazy {
|
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 {
|
||||||
|
"""<a id="School_detail".*?/School/([\w-_]+?)/""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
|
}
|
||||||
|
val EDUDZIENNIK_CLASS_DETAIL_ID by lazy {
|
||||||
|
"""<a id="Klass_detail".*?/Klass/([\w-_]+?)/""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -83,4 +83,7 @@ class DataEdudziennik(app: App, profile: Profile?, loginStore: LoginStore) : Dat
|
|||||||
|
|
||||||
val courseEndpoint: String
|
val courseEndpoint: String
|
||||||
get() = "Course/$studentId/"
|
get() = "Course/$studentId/"
|
||||||
|
|
||||||
|
val timetableEndpoint: String
|
||||||
|
get() = "Plan/$studentId/"
|
||||||
}
|
}
|
||||||
|
@ -4,13 +4,11 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik
|
||||||
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.FEATURE_LUCKY_NUMBER
|
import pl.szczodrzynski.edziennik.data.api.*
|
||||||
import pl.szczodrzynski.edziennik.data.api.FEATURE_STUDENT_INFO
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_METHOD_EDUDZIENNIK_WEB
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.LOGIN_TYPE_EDUDZIENNIK
|
|
||||||
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
import pl.szczodrzynski.edziennik.data.api.models.Feature
|
||||||
|
|
||||||
const val ENDPOINT_EDUDZIENNIK_WEB_START = 1000
|
const val ENDPOINT_EDUDZIENNIK_WEB_START = 1000
|
||||||
|
const val ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE = 1001
|
||||||
const val ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER = 1010
|
const val ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER = 1010
|
||||||
|
|
||||||
val EdudziennikFeatures = listOf(
|
val EdudziennikFeatures = listOf(
|
||||||
@ -18,6 +16,10 @@ val EdudziennikFeatures = listOf(
|
|||||||
ENDPOINT_EDUDZIENNIK_WEB_START to LOGIN_METHOD_EDUDZIENNIK_WEB
|
ENDPOINT_EDUDZIENNIK_WEB_START to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||||
|
|
||||||
|
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_TIMETABLE, listOf(
|
||||||
|
ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||||
|
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB)),
|
||||||
|
|
||||||
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
|
Feature(LOGIN_TYPE_EDUDZIENNIK, FEATURE_LUCKY_NUMBER, listOf(
|
||||||
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER to LOGIN_METHOD_EDUDZIENNIK_WEB
|
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER to LOGIN_METHOD_EDUDZIENNIK_WEB
|
||||||
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB))
|
), listOf(LOGIN_METHOD_EDUDZIENNIK_WEB))
|
||||||
|
@ -8,8 +8,10 @@ import pl.szczodrzynski.edziennik.R
|
|||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebLuckyNumber
|
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.EdudziennikWebStart
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web.EdudziennikWebTimetable
|
||||||
import pl.szczodrzynski.edziennik.utils.Utils
|
import pl.szczodrzynski.edziennik.utils.Utils
|
||||||
|
|
||||||
class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
||||||
@ -43,6 +45,10 @@ class EdudziennikData(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
|||||||
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
data.startProgress(R.string.edziennik_progress_endpoint_data)
|
||||||
EdudziennikWebStart(data, onSuccess)
|
EdudziennikWebStart(data, onSuccess)
|
||||||
}
|
}
|
||||||
|
ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE -> {
|
||||||
|
data.startProgress(R.string.edziennik_progress_endpoint_timetable)
|
||||||
|
EdudziennikWebTimetable(data, onSuccess)
|
||||||
|
}
|
||||||
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
|
ENDPOINT_EDUDZIENNIK_WEB_LUCKY_NUMBER -> {
|
||||||
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
data.startProgress(R.string.edziennik_progress_endpoint_lucky_number)
|
||||||
EdudziennikWebLuckyNumber(data, onSuccess)
|
EdudziennikWebLuckyNumber(data, onSuccess)
|
||||||
|
@ -27,7 +27,7 @@ open class EdudziennikWeb(open val data: DataEdudziennik) {
|
|||||||
get() = data.profile
|
get() = data.profile
|
||||||
|
|
||||||
fun webGet(tag: String, endpoint: String, xhr: Boolean = false, onSuccess: (text: String) -> Unit) {
|
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
|
true -> endpoint
|
||||||
else -> "$endpoint/"
|
else -> "$endpoint/"
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
|
|
||||||
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
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.DataEdudziennik
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_START
|
||||||
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
@ -18,14 +20,10 @@ class EdudziennikWebStart(override val data: DataEdudziennik,
|
|||||||
|
|
||||||
init { data.profile?.also { profile ->
|
init { data.profile?.also { profile ->
|
||||||
webGet(TAG, data.studentEndpoint + "start") { text ->
|
webGet(TAG, data.studentEndpoint + "start") { text ->
|
||||||
val schoolId = """<a id="School_detail".*?href="/Students/${data.studentId}/School/(\w+?)/""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
val schoolId = EDUDZIENNIK_SCHOOL_DETAIL_ID.find(text)?.get(1)
|
||||||
.find(text)?.get(1)
|
|
||||||
|
|
||||||
data.schoolId = schoolId
|
data.schoolId = schoolId
|
||||||
|
|
||||||
val classId = """<a id="Klass_detail".*?href="/Students/${data.studentId}/Klass/(\w+?)/""".toRegex(RegexOption.DOT_MATCHES_ALL)
|
val classId = EDUDZIENNIK_CLASS_DETAIL_ID.find(text)?.get(1)
|
||||||
.find(text)?.get(1)
|
|
||||||
|
|
||||||
data.classId = classId
|
data.classId = classId
|
||||||
|
|
||||||
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_START, SYNC_ALWAYS)
|
data.setSyncNext(ENDPOINT_EDUDZIENNIK_WEB_START, SYNC_ALWAYS)
|
||||||
|
@ -0,0 +1,149 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Kacper Ziubryniewicz 2019-12-23
|
||||||
|
*/
|
||||||
|
|
||||||
|
package pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.web
|
||||||
|
|
||||||
|
import org.jsoup.Jsoup
|
||||||
|
import pl.szczodrzynski.edziennik.*
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_SUBJECT_ID
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.Regexes.EDUDZIENNIK_TEACHER_ID
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.DataEdudziennik
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.ENDPOINT_EDUDZIENNIK_WEB_TIMETABLE
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.edziennik.edudziennik.data.EdudziennikWeb
|
||||||
|
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.api.SYNC_ALWAYS
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
|
||||||
|
import pl.szczodrzynski.edziennik.data.db.modules.timetable.Lesson
|
||||||
|
import pl.szczodrzynski.edziennik.utils.Utils.d
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Date
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Time
|
||||||
|
import pl.szczodrzynski.edziennik.utils.models.Week
|
||||||
|
|
||||||
|
class EdudziennikWebTimetable(override val data: DataEdudziennik,
|
||||||
|
val onSuccess: () -> 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<Int>()
|
||||||
|
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() }
|
||||||
|
}
|
@ -46,7 +46,7 @@ class EdudziennikLogin(val data: DataEdudziennik, val onSuccess: () -> Unit) {
|
|||||||
Utils.d(TAG, "Using login method $loginMethodId")
|
Utils.d(TAG, "Using login method $loginMethodId")
|
||||||
when (loginMethodId) {
|
when (loginMethodId) {
|
||||||
LOGIN_METHOD_EDUDZIENNIK_WEB -> {
|
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) }
|
EdudziennikLoginWeb(data) { onSuccess(loginMethodId) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1128,4 +1128,5 @@
|
|||||||
<string name="lessons_finished">Nie ma dzisiaj więcej lekcji!</string>
|
<string name="lessons_finished">Nie ma dzisiaj więcej lekcji!</string>
|
||||||
<string name="login_edudziennik_title">Zaloguj się - Edudziennik</string>
|
<string name="login_edudziennik_title">Zaloguj się - Edudziennik</string>
|
||||||
<string name="login_edudziennik_subtitle">Użyj danych, którymi logujesz się do wersji komputerowej Edudziennika.</string>
|
<string name="login_edudziennik_subtitle">Użyj danych, którymi logujesz się do wersji komputerowej Edudziennika.</string>
|
||||||
|
<string name="edziennik_progress_login_edudziennik_web">Logowanie do Edudziennika</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user