[APIv2] Update Mobidziennik API. Update Data structure.

This commit is contained in:
Kuba Szczodrzyński 2019-10-06 22:58:13 +02:00
parent f0bf6b8b81
commit f7412fea7f
13 changed files with 301 additions and 20 deletions

View File

@ -16,6 +16,7 @@ import com.google.gson.JsonObject
import im.wangchao.mhttp.Response
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
import pl.szczodrzynski.navlib.R
import pl.szczodrzynski.navlib.crc16
import pl.szczodrzynski.navlib.getColorFromRes
@ -177,3 +178,44 @@ fun <T> List<T>.toSparseArray(key: (T) -> Long): LongSparseArray<T> {
toSparseArray(result, key)
return result
}
fun <T> SparseArray<T>.singleOrNull(predicate: (T) -> Boolean): T? {
forEach { _, value ->
if (predicate(value))
return value
}
return null
}
fun <T> LongSparseArray<T>.singleOrNull(predicate: (T) -> Boolean): T? {
forEach { _, value ->
if (predicate(value))
return value
}
return null
}
fun String.fixWhiteSpaces() = buildString(length) {
var wasWhiteSpace = true
for (c in this@fixWhiteSpaces) {
if (c.isWhitespace()) {
if (!wasWhiteSpace) {
append(c)
wasWhiteSpace = true
}
} else {
append(c)
wasWhiteSpace = false
}
}
}.trimEnd()
fun List<Team>.getById(id: Long): Team? {
return singleOrNull { it.id == id }
}
fun LongSparseArray<Team>.getById(id: Long): Team? {
forEach { _, value ->
if (value.id == id)
return value
}
return null
}

View File

@ -106,6 +106,7 @@ const val ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED = 211
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_KEY = 212
const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 212
const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302

View File

@ -1,9 +1,11 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-5.
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik
import android.util.LongSparseArray
import android.util.SparseArray
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.LOGIN_METHOD_MOBIDZIENNIK_WEB
import pl.szczodrzynski.edziennik.api.v2.models.Data
@ -26,6 +28,9 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
}
}
val teachersMap = LongSparseArray<String>()
val subjectsMap = LongSparseArray<String>()
private var mLoginServerName: String? = null
var loginServerName: String?
get() { mLoginServerName = mLoginServerName ?: loginStore.getLoginData("serverName", null); return mLoginServerName }
@ -41,6 +46,11 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
get() { mLoginPassword = mLoginPassword ?: loginStore.getLoginData("password", null); return mLoginPassword }
set(value) { loginStore.putLoginData("password", value); mLoginPassword = value }
private var mStudentId: Int? = null
var studentId: Int
get() { mStudentId = mStudentId ?: profile?.getStudentData("studentId", 0); return mStudentId ?: 0 }
set(value) { profile?.putStudentData("studentId", value) ?: return; mStudentId = value }
/* __ __ _
\ \ / / | |
\ \ /\ / /__| |__

View File

@ -7,7 +7,7 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik
import pl.szczodrzynski.edziennik.api.v2.*
import pl.szczodrzynski.edziennik.api.v2.models.Feature
const val ENDPOINT_MOBIDZIENNIK_API = 1000
const val ENDPOINT_MOBIDZIENNIK_API_MAIN = 1000
const val ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX = 2011
const val ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_SENT = 2012
const val ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL = 2019
@ -21,25 +21,25 @@ const val ENDPOINT_MOBIDZIENNIK_API2 = 3000
val MobidziennikFeatures = listOf(
// timetable
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_TIMETABLE, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
// agenda
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_AGENDA, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)),
// grades
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_GRADES, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_GRADES to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)),
// homework
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_HOMEWORK, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
// behaviour
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_BEHAVIOUR, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_NOTICES to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_WEB)),
// attendance
@ -55,31 +55,31 @@ val MobidziennikFeatures = listOf(
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ALWAYS_NEEDED, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
/*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_STUDENT_INFO, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_STUDENT_NUMBER, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_SCHOOL_INFO, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_CLASS_INFO, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_TEAM_INFO, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_TEACHERS, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_SUBJECTS, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_CLASSROOMS, listOf(
ENDPOINT_MOBIDZIENNIK_API to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)),*/
// lucky number possibilities

View File

@ -4,7 +4,9 @@
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.*
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikApi
import pl.szczodrzynski.edziennik.utils.Utils
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
@ -35,10 +37,10 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
private fun useEndpoint(endpointId: Int, onSuccess: () -> Unit) {
Utils.d(TAG, "Using endpoint $endpointId")
when (endpointId) {
/*ENDPOINT_MOBIDZIENNIK_API -> {
ENDPOINT_MOBIDZIENNIK_API_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_data)
MobidziennikApi(data) { onSuccess() }
}
}/*
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
MobidziennikWebMessagesInbox(data) { onSuccess() }

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
import android.util.SparseArray
import androidx.collection.SparseArrayCompat
import androidx.core.util.forEach
import pl.szczodrzynski.edziennik.api.v2.ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata.*
import pl.szczodrzynski.edziennik.api.v2.models.ApiError
class MobidziennikApi(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikApi"
}
init {
webGet(TAG, "/api/zrzutbazy") { text ->
if (!text.contains("T@B#LA")) {
data.error(ApiError(TAG, ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE)
.withApiResponse(text))
return@webGet
}
val tables = text.split("T@B#LA")
tables.forEachIndexed { index, table ->
val rows = table.split("\n")
when (index) {
0 -> MobidziennikApiUsers(data, rows)
3 -> MobidziennikApiDates(data, rows)
4 -> MobidziennikApiSubjects(data, rows)
7 -> MobidziennikApiTeams(data, rows, null)
8 -> MobidziennikApiStudent(data, rows)
9 -> MobidziennikApiTeams(data, null, rows)
/*14 -> MobidziennikApiGradeCategories(data, rows)
15 -> MobidziennikApiLessons(data, rows)
16 -> MobidziennikApiAttendance(data, rows)
17 -> MobidziennikApiNotices(data, rows)
18 -> MobidziennikApiGrades(data, rows)
21 -> MobidziennikApiEvents(data, rows)
23 -> MobidziennikApiHomework(data, rows)
24 -> MobidziennikApiTimetable(data, rows)*/
}
}
}
}
}

View File

@ -0,0 +1,26 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.App
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikApiDates(val data: DataMobidziennik, rows: List<String>) {
init {
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
when (cols[1]) {
"semestr1_poczatek" -> data.profile?.dateSemester1Start = Date.fromYmd(cols[3])
"semestr2_poczatek" -> data.profile?.dateSemester2Start = Date.fromYmd(cols[3])
"koniec_roku_szkolnego" -> data.profile?.dateYearEnd = Date.fromYmd(cols[3])
}
}
}
}

View File

@ -0,0 +1,18 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
class MobidziennikApiStudent(val data: DataMobidziennik, rows: List<String>) {
init {
for (row in rows) {
if (row.isEmpty())
continue
// TODO
}
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.subjects.Subject
class MobidziennikApiSubjects(val data: DataMobidziennik, rows: List<String>) {
init {
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
val id = cols[0].toLong()
val longName = cols[1].trim()
val shortName = cols[2].trim()
data.subjectsMap.put(id, longName)
data.subjectList.put(id, Subject(data.profileId, id, longName, shortName))
}
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.App.profileId
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
import pl.szczodrzynski.edziennik.data.db.modules.teams.Team
import pl.szczodrzynski.edziennik.getById
import pl.szczodrzynski.edziennik.utils.Utils.strToInt
import pl.szczodrzynski.edziennik.values
class MobidziennikApiTeams(val data: DataMobidziennik, tableTeams: List<String>?, tableRelations: List<String>?) {
init {
if (tableTeams != null) {
for (row in tableTeams) {
if (row.isEmpty())
continue
val cols = row.split("|")
val id = cols[0].toLong()
val name = cols[1]+cols[2]
val type = cols[3].toInt()
val code = data.loginServerName+":"+name
val teacherId = cols[4].toLongOrNull() ?: -1
val teamObject = Team(
profileId,
id,
name,
type,
code,
teacherId)
data.teamList.put(id, teamObject)
}
}
if (tableRelations != null) {
val allTeams = data.teamList.values()
data.teamList.clear()
for (row in tableRelations) {
if (row.isEmpty())
continue
val cols = row.split("|")
val studentId = cols[1].toInt()
val teamId = cols[2].toLong()
val studentNumber = cols[4].toInt()
if (studentId != data.studentId)
continue
val team = allTeams.getById(teamId)
if (team != null) {
if (team.type == 1) {
data.profile?.studentNumber = studentNumber
data.teamClass = team
}
data.teamList.put(teamId, team)
}
}
}
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-6.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.apidata
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.teachers.Teacher
class MobidziennikApiUsers(val data: DataMobidziennik, rows: List<String>) {
init {
for (row in rows) {
if (row.isEmpty())
continue
val cols = row.split("|")
val id = cols[0].toLong()
val name = cols[4].trim()
val surname = cols[5].trim()
data.teachersMap.put(id, "$surname $name")
data.teacherList.put(id, Teacher(data.profileId, id, name, surname))
}
}
}

View File

@ -28,6 +28,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.profiles.Profile
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.teams.Team
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.toSparseArray
import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.values
@ -96,8 +97,19 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
val teacherList = LongSparseArray<Teacher>()
val subjectList = LongSparseArray<Subject>()
var teamList = LongSparseArray<Team>()
var lessonRanges = SparseArray<LessonRange>()
val teamList = LongSparseArray<Team>()
val lessonRanges = SparseArray<LessonRange>()
private var mTeamClass: Team? = null
var teamClass: Team?
get() {
if (mTeamClass == null)
mTeamClass = teamList.singleOrNull { it.type == Team.TYPE_CLASS }
return mTeamClass
}
set(value) {
mTeamClass = value
}
var lessonsToRemove: DataRemoveModel? = null
val lessonList = mutableListOf<Lesson>()

View File

@ -8,6 +8,9 @@ import java.util.List;
@Entity(tableName = "teams",
primaryKeys = {"profileId", "teamId"})
public class Team {
public static final int TYPE_CLASS = 1;
public static final int TYPE_VIRTUAL = 2;
public int profileId;
@ColumnInfo(name = "teamId")