mirror of
https://github.com/szkolny-eu/szkolny-android.git
synced 2024-11-24 10:54:36 -06:00
[API/Vulcan] Migrate to new MessageBox API. (#134)
* Implement fetching vulcan messages from new api * Bump kotlin version and fix timetable card lessons size display * Revert formatting changes * Revert disabling message composing * Revert MultiDex changes and dependency upgrades * Add missing MultiDex dependency, update Google Services * Separate MessageBoxes sync, revert API data behavior changes * Revert migrating MessageRecipient to Kotlin * Use loginId from MessageBox address book * Revert using compatible HTML mode in Vulcan * Implement message meta and read status changing * Always set attachment lists * Fix setting tutor role description * Implement sending messages * Replace millis constant with WEEK * Revert timetable changes * Remove unused DataVulcan properties * Ensure UUID-format recipient IDs Co-authored-by: Kuba Szczodrzyński <kuba@szczodrzynski.pl>
This commit is contained in:
parent
54a61c6254
commit
bb44fa066c
@ -142,6 +142,7 @@ dependencies {
|
||||
|
||||
// Language cores
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||
implementation "androidx.multidex:multidex:2.0.1"
|
||||
coreLibraryDesugaring "com.android.tools:desugar_jdk_libs:1.1.5"
|
||||
|
||||
// Android Jetpack
|
||||
|
@ -92,7 +92,7 @@ val MOBIDZIENNIK_USER_AGENT = SYSTEM_USER_AGENT
|
||||
|
||||
const val VULCAN_HEBE_USER_AGENT = "Dart/2.10 (dart:io)"
|
||||
const val VULCAN_HEBE_APP_NAME = "DzienniczekPlus 2.0"
|
||||
const val VULCAN_HEBE_APP_VERSION = "21.02.09 (G)"
|
||||
const val VULCAN_HEBE_APP_VERSION = "22.09.02 (G)"
|
||||
private const val VULCAN_API_DEVICE_NAME_PREFIX = "Szkolny.eu "
|
||||
private const val VULCAN_API_DEVICE_NAME_SUFFIX = " - nie usuwać"
|
||||
val VULCAN_API_DEVICE_NAME by lazy {
|
||||
@ -116,9 +116,11 @@ const val VULCAN_HEBE_ENDPOINT_GRADE_SUMMARY = "api/mobile/grade/summary"
|
||||
const val VULCAN_HEBE_ENDPOINT_HOMEWORK = "api/mobile/homework"
|
||||
const val VULCAN_HEBE_ENDPOINT_NOTICES = "api/mobile/note"
|
||||
const val VULCAN_HEBE_ENDPOINT_ATTENDANCE = "api/mobile/lesson"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGES = "api/mobile/message"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS = "api/mobile/message/status"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGES_SEND = "api/mobile/message"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGEBOX = "api/mobile/messagebox"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGEBOX_ADDRESSBOOK = "api/mobile/messagebox/addressbook"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGEBOX_MESSAGES = "api/mobile/messagebox/message"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGEBOX_STATUS = "api/mobile/messagebox/message/status"
|
||||
const val VULCAN_HEBE_ENDPOINT_MESSAGEBOX_SEND = "api/mobile/messagebox/message"
|
||||
const val VULCAN_HEBE_ENDPOINT_LUCKY_NUMBER = "api/mobile/school/lucky"
|
||||
|
||||
const val EDUDZIENNIK_USER_AGENT = "Szkolny.eu/${BuildConfig.VERSION_NAME}"
|
||||
|
@ -20,6 +20,10 @@ object Regexes {
|
||||
"""<br\s?/?>""".toRegex()
|
||||
}
|
||||
|
||||
val MESSAGE_META by lazy {
|
||||
"""^\[META:([A-z0-9-&=]+)]""".toRegex()
|
||||
}
|
||||
|
||||
|
||||
|
||||
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
|
||||
|
@ -222,15 +222,15 @@ class DataVulcan(app: App, profile: Profile?, loginStore: LoginStore) : Data(app
|
||||
get() { mHebeContext = mHebeContext ?: profile?.getStudentData("hebeContext", null); return mHebeContext }
|
||||
set(value) { profile?.putStudentData("hebeContext", value) ?: return; mHebeContext = value }
|
||||
|
||||
private var mSenderAddressHash: String? = null
|
||||
var senderAddressHash: String?
|
||||
get() { mSenderAddressHash = mSenderAddressHash ?: profile?.getStudentData("senderAddressHash", null); return mSenderAddressHash }
|
||||
set(value) { profile?.putStudentData("senderAddressHash", value) ?: return; mSenderAddressHash = value }
|
||||
private var mMessageBoxKey: String? = null
|
||||
var messageBoxKey: String?
|
||||
get() { mMessageBoxKey = mMessageBoxKey ?: profile?.getStudentData("messageBoxKey", null); return mMessageBoxKey }
|
||||
set(value) { profile?.putStudentData("messageBoxKey", value) ?: return; mMessageBoxKey = value }
|
||||
|
||||
private var mSenderAddressName: String? = null
|
||||
var senderAddressName: String?
|
||||
get() { mSenderAddressName = mSenderAddressName ?: profile?.getStudentData("senderAddressName", null); return mSenderAddressName }
|
||||
set(value) { profile?.putStudentData("senderAddressName", value) ?: return; mSenderAddressName = value }
|
||||
private var mMessageBoxName: String? = null
|
||||
var messageBoxName: String?
|
||||
get() { mMessageBoxName = mMessageBoxName ?: profile?.getStudentData("messageBoxName", null); return mMessageBoxName }
|
||||
set(value) { profile?.putStudentData("messageBoxName", value) ?: return; mMessageBoxName = value }
|
||||
|
||||
val apiUrl: String?
|
||||
get() {
|
||||
|
@ -12,6 +12,7 @@ const val ENDPOINT_VULCAN_WEB_LUCKY_NUMBERS = 2010
|
||||
const val ENDPOINT_VULCAN_HEBE_MAIN = 3000
|
||||
const val ENDPOINT_VULCAN_HEBE_PUSH_CONFIG = 3005
|
||||
const val ENDPOINT_VULCAN_HEBE_ADDRESSBOOK = 3010
|
||||
const val ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2 = 3011
|
||||
const val ENDPOINT_VULCAN_HEBE_TIMETABLE = 3020
|
||||
const val ENDPOINT_VULCAN_HEBE_EXAMS = 3030
|
||||
const val ENDPOINT_VULCAN_HEBE_GRADES = 3040
|
||||
@ -19,10 +20,11 @@ const val ENDPOINT_VULCAN_HEBE_GRADE_SUMMARY = 3050
|
||||
const val ENDPOINT_VULCAN_HEBE_HOMEWORK = 3060
|
||||
const val ENDPOINT_VULCAN_HEBE_NOTICES = 3070
|
||||
const val ENDPOINT_VULCAN_HEBE_ATTENDANCE = 3080
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3090
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3100
|
||||
const val ENDPOINT_VULCAN_HEBE_TEACHERS = 3110
|
||||
const val ENDPOINT_VULCAN_HEBE_LUCKY_NUMBER = 3200
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES = 3500
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX = 3510
|
||||
const val ENDPOINT_VULCAN_HEBE_MESSAGES_SENT = 3520
|
||||
|
||||
val VulcanFeatures = listOf(
|
||||
// timetable
|
||||
@ -85,6 +87,8 @@ val VulcanFeatures = listOf(
|
||||
Feature(LOGIN_TYPE_VULCAN, FEATURE_ALWAYS_NEEDED, listOf(
|
||||
ENDPOINT_VULCAN_HEBE_MAIN to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS to LOGIN_METHOD_VULCAN_HEBE
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2 to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS to LOGIN_METHOD_VULCAN_HEBE,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES to LOGIN_METHOD_VULCAN_HEBE,
|
||||
), listOf(LOGIN_METHOD_VULCAN_HEBE))
|
||||
)
|
||||
|
@ -21,10 +21,12 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||
ENDPOINT_VULCAN_HEBE_MAIN,
|
||||
ENDPOINT_VULCAN_HEBE_PUSH_CONFIG,
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK,
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2,
|
||||
ENDPOINT_VULCAN_HEBE_TIMETABLE,
|
||||
ENDPOINT_VULCAN_HEBE_EXAMS,
|
||||
ENDPOINT_VULCAN_HEBE_HOMEWORK,
|
||||
ENDPOINT_VULCAN_HEBE_NOTICES,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX,
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGES_SENT,
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS,
|
||||
@ -107,6 +109,10 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_addressbook)
|
||||
VulcanHebeAddressbook(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2 -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_addressbook)
|
||||
VulcanHebeAddressbook2(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_TEACHERS -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_teachers)
|
||||
VulcanHebeTeachers(data, lastSync, onSuccess)
|
||||
@ -139,6 +145,10 @@ class VulcanData(val data: DataVulcan, val onSuccess: () -> Unit) {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_attendance)
|
||||
VulcanHebeAttendance(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages)
|
||||
VulcanHebeMessageBoxes(data, lastSync, onSuccess)
|
||||
}
|
||||
ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX -> {
|
||||
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
|
||||
VulcanHebeMessages(data, lastSync, onSuccess).getMessages(Message.TYPE_RECEIVED)
|
||||
|
@ -14,7 +14,6 @@ import im.wangchao.mhttp.Response
|
||||
import im.wangchao.mhttp.body.MediaTypeUtils
|
||||
import im.wangchao.mhttp.callback.JsonCallbackHandler
|
||||
import io.github.wulkanowy.signer.hebe.getSignatureHeaders
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.*
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe.HebeFilterType
|
||||
@ -55,6 +54,15 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
return date.getLong("Timestamp") ?: return default
|
||||
}
|
||||
|
||||
fun buildDateTime(): JsonObject {
|
||||
return JsonObject(
|
||||
"Timestamp" to System.currentTimeMillis(),
|
||||
"Date" to Date.getToday().stringY_m_d,
|
||||
"DateDisplay" to Date.getToday().stringDmy,
|
||||
"Time" to Time.getNow().stringHMS,
|
||||
)
|
||||
}
|
||||
|
||||
fun getDate(json: JsonObject?, key: String): Date? {
|
||||
val date = json.getJsonObject(key)
|
||||
return date.getString("Date")?.let { Date.fromY_m_d(it) }
|
||||
@ -74,6 +82,22 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
return teacherId
|
||||
}
|
||||
|
||||
fun getTeacherRecipient(json: JsonObject): Teacher? {
|
||||
val globalKey = json.getString("GlobalKey") ?: return null
|
||||
if (globalKey == data.messageBoxKey)
|
||||
return null
|
||||
var name = json.getString("Name") ?: return null
|
||||
val group = json.getString("Group", "P")
|
||||
val loginId = "${globalKey};${group};${name}"
|
||||
val pattern = " - $group - (${data.schoolShort})"
|
||||
if (name.endsWith(pattern))
|
||||
name = name.substringBefore(pattern)
|
||||
val teacher = data.getTeacherByFirstLast(name, loginId)
|
||||
if (teacher.type == 0)
|
||||
teacher.type = Teacher.TYPE_OTHER
|
||||
return teacher
|
||||
}
|
||||
|
||||
fun getSubjectId(json: JsonObject?, key: String): Long? {
|
||||
val subject = json.getJsonObject(key)
|
||||
val subjectId = subject.getLong("Id") ?: return null
|
||||
@ -89,7 +113,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
}
|
||||
|
||||
fun getTeamId(json: JsonObject?, key: String): Long? {
|
||||
val team = json.getJsonObject(key)
|
||||
val team = json.getJsonObject(key) ?: return null
|
||||
val teamId = team.getLong("Id")
|
||||
var teamName = team.getString("Shortcut")
|
||||
?: team.getString("Name")
|
||||
@ -104,7 +128,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
}
|
||||
|
||||
fun getClassId(json: JsonObject?, key: String): Long? {
|
||||
val team = json.getJsonObject(key)
|
||||
val team = json.getJsonObject(key) ?: return null
|
||||
val teamId = team.getLong("Id")
|
||||
val teamName = data.profile?.studentClassName
|
||||
?: team.getString("Name")
|
||||
@ -148,7 +172,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
|
||||
fun isCurrentYear(dateTime: Long): Boolean {
|
||||
return profile?.let { profile ->
|
||||
return@let dateTime >= profile.dateSemester1Start.inMillis
|
||||
return@let dateTime >= profile.dateSemester1Start.inMillis - WEEK * MS
|
||||
} ?: false
|
||||
}
|
||||
|
||||
@ -355,6 +379,7 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
dateTo: Date? = null,
|
||||
lastSync: Long? = null,
|
||||
folder: Int? = null,
|
||||
messageBox: String? = null,
|
||||
params: Map<String, String> = mapOf(),
|
||||
includeFilterType: Boolean = true,
|
||||
onSuccess: (data: List<JsonObject>, response: Response?) -> Unit
|
||||
@ -378,6 +403,9 @@ open class VulcanHebe(open val data: DataVulcan, open val lastSync: Long?) {
|
||||
query["periodId"] = data.studentSemesterId.toString()
|
||||
query["pupilId"] = data.studentId.toString()
|
||||
}
|
||||
HebeFilterType.BY_MESSAGEBOX -> {
|
||||
query["box"] = messageBox ?: data.messageBoxKey ?: ""
|
||||
}
|
||||
}
|
||||
|
||||
if (dateFrom != null)
|
||||
|
@ -5,6 +5,7 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
enum class HebeFilterType(val endpoint: String) {
|
||||
BY_MESSAGEBOX("byBox"),
|
||||
BY_PUPIL("byPupil"),
|
||||
BY_PERSON("byPerson"),
|
||||
BY_PERIOD("byPeriod")
|
||||
|
@ -5,6 +5,7 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import androidx.core.util.set
|
||||
import androidx.room.OnConflictStrategy
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_ADDRESSBOOK
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
@ -44,7 +45,6 @@ class VulcanHebeAddressbook(
|
||||
) { list, _ ->
|
||||
list.forEach { person ->
|
||||
val id = person.getString("Id") ?: return@forEach
|
||||
val loginId = person.getString("LoginId") ?: return@forEach
|
||||
|
||||
val idType = id.split("-")
|
||||
.getOrNull(0)
|
||||
@ -69,7 +69,7 @@ class VulcanHebeAddressbook(
|
||||
idLong,
|
||||
name,
|
||||
surname,
|
||||
loginId
|
||||
null
|
||||
).also {
|
||||
data.teacherList[idLong] = it
|
||||
}
|
||||
@ -108,13 +108,14 @@ class VulcanHebeAddressbook(
|
||||
}
|
||||
|
||||
teacher.setTeacherType(personType)
|
||||
teacher.typeDescription = roleText
|
||||
if (roleText != null)
|
||||
teacher.typeDescription = roleText
|
||||
}
|
||||
|
||||
if (teacher.type == 0)
|
||||
teacher.setTeacherType(typeBase)
|
||||
}
|
||||
|
||||
data.teacherOnConflictStrategy = OnConflictStrategy.REPLACE
|
||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK, 2 * DAY)
|
||||
onSuccess(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK)
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2021-2-21.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import androidx.room.OnConflictStrategy
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGEBOX_ADDRESSBOOK
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_OTHER
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_PARENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_STUDENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher.Companion.TYPE_TEACHER
|
||||
import pl.szczodrzynski.edziennik.ext.DAY
|
||||
import pl.szczodrzynski.edziennik.ext.getString
|
||||
|
||||
class VulcanHebeAddressbook2(
|
||||
override val data: DataVulcan,
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : VulcanHebe(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "VulcanHebeAddressbook2"
|
||||
}
|
||||
|
||||
init {
|
||||
apiGetList(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGEBOX_ADDRESSBOOK,
|
||||
HebeFilterType.BY_MESSAGEBOX,
|
||||
messageBox = data.messageBoxKey,
|
||||
lastSync = lastSync,
|
||||
includeFilterType = false
|
||||
) { list, _ ->
|
||||
list.forEach { person ->
|
||||
val teacher = getTeacherRecipient(person) ?: return@forEach
|
||||
val group = person.getString("Group", "P")
|
||||
if (teacher.type == TYPE_OTHER) {
|
||||
teacher.type = when (group) {
|
||||
"P" -> TYPE_TEACHER // Pracownik
|
||||
"O" -> TYPE_PARENT // Opiekun
|
||||
"U" -> TYPE_STUDENT // Uczeń
|
||||
else -> TYPE_OTHER
|
||||
}
|
||||
}
|
||||
}
|
||||
data.teacherOnConflictStrategy = OnConflictStrategy.REPLACE
|
||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2, 2 * DAY)
|
||||
onSuccess(ENDPOINT_VULCAN_HEBE_ADDRESSBOOK_2)
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) Kuba Szczodrzyński 2022-9-16.
|
||||
*/
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGEBOX
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.ext.DAY
|
||||
import pl.szczodrzynski.edziennik.ext.getString
|
||||
|
||||
class VulcanHebeMessageBoxes(
|
||||
override val data: DataVulcan,
|
||||
override val lastSync: Long?,
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : VulcanHebe(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "VulcanHebeMessageBoxes"
|
||||
}
|
||||
|
||||
init {
|
||||
apiGetList(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGEBOX,
|
||||
lastSync = lastSync
|
||||
) { list, _ ->
|
||||
for (messageBox in list) {
|
||||
val name = messageBox.getString("Name") ?: continue
|
||||
val studentName = profile?.studentNameLong ?: continue
|
||||
if (!name.startsWith(studentName))
|
||||
continue
|
||||
|
||||
data.messageBoxKey = messageBox.getString("GlobalKey")
|
||||
data.messageBoxName = name
|
||||
break
|
||||
}
|
||||
data.setSyncNext(ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES, 7 * DAY)
|
||||
onSuccess(ENDPOINT_VULCAN_HEBE_MESSAGE_BOXES)
|
||||
}
|
||||
}
|
||||
}
|
@ -4,22 +4,21 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import androidx.core.util.set
|
||||
import com.google.gson.JsonObject
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.MainActivity.Companion.DRAWER_ITEM_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGEBOX_MESSAGES
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.ENDPOINT_VULCAN_HEBE_MESSAGES_SENT
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_DELETED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_RECEIVED
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message.Companion.TYPE_SENT
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.MessageRecipient
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
|
||||
import pl.szczodrzynski.edziennik.ext.*
|
||||
import pl.szczodrzynski.edziennik.utils.Utils
|
||||
import pl.szczodrzynski.navlib.crc16
|
||||
|
||||
class VulcanHebeMessages(
|
||||
override val data: DataVulcan,
|
||||
@ -27,29 +26,7 @@ class VulcanHebeMessages(
|
||||
val onSuccess: (endpointId: Int) -> Unit
|
||||
) : VulcanHebe(data, lastSync) {
|
||||
companion object {
|
||||
const val TAG = "VulcanHebeMessagesInbox"
|
||||
}
|
||||
|
||||
private fun getPersonId(json: JsonObject): Long {
|
||||
val senderLoginId = json.getInt("LoginId") ?: return -1
|
||||
/*if (senderLoginId == data.studentLoginId)
|
||||
return -1*/
|
||||
|
||||
val senderName = json.getString("Address") ?: return -1
|
||||
val senderNameSplit = senderName.splitName()
|
||||
val senderLoginIdStr = senderLoginId.toString()
|
||||
val teacher = data.teacherList.singleOrNull { it.loginId == senderLoginIdStr }
|
||||
?: Teacher(
|
||||
profileId,
|
||||
-1 * crc16(senderName).toLong(),
|
||||
senderNameSplit?.second ?: "",
|
||||
senderNameSplit?.first ?: "",
|
||||
senderLoginIdStr
|
||||
).also {
|
||||
it.setTeacherType(Teacher.TYPE_OTHER)
|
||||
data.teacherList[it.id] = it
|
||||
}
|
||||
return teacher.id
|
||||
const val TAG = "VulcanHebeMessages"
|
||||
}
|
||||
|
||||
fun getMessages(messageType: Int) {
|
||||
@ -64,17 +41,28 @@ class VulcanHebeMessages(
|
||||
TYPE_SENT -> ENDPOINT_VULCAN_HEBE_MESSAGES_SENT
|
||||
else -> ENDPOINT_VULCAN_HEBE_MESSAGES_INBOX
|
||||
}
|
||||
|
||||
val messageBox = data.messageBoxKey
|
||||
if (messageBox == null) {
|
||||
onSuccess(endpointId)
|
||||
return
|
||||
}
|
||||
|
||||
apiGetList(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGES,
|
||||
HebeFilterType.BY_PERSON,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGEBOX_MESSAGES,
|
||||
HebeFilterType.BY_MESSAGEBOX,
|
||||
messageBox = data.messageBoxKey,
|
||||
folder = folder,
|
||||
lastSync = lastSync
|
||||
) { list, _ ->
|
||||
list.forEach { message ->
|
||||
val id = message.getLong("Id") ?: return@forEach
|
||||
val uuid = message.getString("Id") ?: return@forEach
|
||||
val id = Utils.crc32(uuid.toByteArray())
|
||||
val globalKey = message.getString("GlobalKey", "")
|
||||
val threadKey = message.getString("ThreadKey", "")
|
||||
val subject = message.getString("Subject") ?: return@forEach
|
||||
val body = message.getString("Content") ?: return@forEach
|
||||
var body = message.getString("Content") ?: return@forEach
|
||||
|
||||
val sender = message.getJsonObject("Sender") ?: return@forEach
|
||||
|
||||
@ -83,13 +71,27 @@ class VulcanHebeMessages(
|
||||
|
||||
if (!isCurrentYear(sentDate)) return@forEach
|
||||
|
||||
val senderId = if (messageType == TYPE_RECEIVED)
|
||||
getTeacherRecipient(sender)?.id
|
||||
else
|
||||
null
|
||||
|
||||
val meta = mutableMapOf(
|
||||
"uuid" to uuid,
|
||||
"globalKey" to globalKey,
|
||||
"threadKey" to threadKey,
|
||||
)
|
||||
val metaString = meta.map { "${it.key}=${it.value}" }.join("&")
|
||||
body = "[META:${metaString}]" + body
|
||||
body = body.replace("\n", "<br>")
|
||||
|
||||
val messageObject = Message(
|
||||
profileId = profileId,
|
||||
id = id,
|
||||
type = messageType,
|
||||
subject = subject,
|
||||
body = body.replace("\n", "<br>"),
|
||||
senderId = if (messageType == TYPE_RECEIVED) getPersonId(sender) else null,
|
||||
body = body,
|
||||
senderId = senderId,
|
||||
addedDate = sentDate
|
||||
)
|
||||
|
||||
@ -101,9 +103,14 @@ class VulcanHebeMessages(
|
||||
else -1
|
||||
|
||||
for (receiver in receivers) {
|
||||
val recipientId = if (messageType == TYPE_SENT)
|
||||
getTeacherRecipient(receiver)?.id ?: -1
|
||||
else
|
||||
-1
|
||||
|
||||
val messageRecipientObject = MessageRecipient(
|
||||
profileId,
|
||||
if (messageType == TYPE_SENT) getPersonId(receiver) else -1,
|
||||
recipientId,
|
||||
-1,
|
||||
receiverReadDate,
|
||||
id
|
||||
@ -115,6 +122,9 @@ class VulcanHebeMessages(
|
||||
?.asJsonObjectList()
|
||||
?: return@forEach
|
||||
|
||||
messageObject.attachmentIds = mutableListOf()
|
||||
messageObject.attachmentNames = mutableListOf()
|
||||
messageObject.attachmentSizes = mutableListOf()
|
||||
for (attachment in attachments) {
|
||||
val fileName = attachment.getString("Name") ?: continue
|
||||
val url = attachment.getString("Link") ?: continue
|
||||
|
@ -5,7 +5,7 @@
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGEBOX_STATUS
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
|
||||
@ -23,13 +23,19 @@ class VulcanHebeMessagesChangeStatus(
|
||||
const val TAG = "VulcanHebeMessagesChangeStatus"
|
||||
}
|
||||
|
||||
init {
|
||||
init { let {
|
||||
val messageKey = messageObject.body?.let { data.parseMessageMeta(it) }?.get("globalKey") ?: run {
|
||||
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
||||
onSuccess()
|
||||
return@let
|
||||
}
|
||||
|
||||
apiPost(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGES_STATUS,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGEBOX_STATUS,
|
||||
payload = JsonObject(
|
||||
"MessageId" to messageObject.id,
|
||||
"LoginId" to data.studentLoginId,
|
||||
"BoxKey" to data.messageBoxKey,
|
||||
"MessageKey" to messageKey,
|
||||
"Status" to 1
|
||||
)
|
||||
) { _: Boolean, _ ->
|
||||
@ -61,5 +67,5 @@ class VulcanHebeMessagesChangeStatus(
|
||||
EventBus.getDefault().postSticky(MessageGetEvent(messageObject))
|
||||
onSuccess()
|
||||
}
|
||||
}
|
||||
}}
|
||||
}
|
||||
|
@ -4,17 +4,20 @@
|
||||
|
||||
package pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.hebe
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import org.greenrobot.eventbus.EventBus
|
||||
import pl.szczodrzynski.edziennik.*
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_MESSAGE_NOT_SENT
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_VULCAN_HEBE_MISSING_SENDER_ENTRY
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGES_SEND
|
||||
import pl.szczodrzynski.edziennik.data.api.VULCAN_HEBE_ENDPOINT_MESSAGEBOX_SEND
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.DataVulcan
|
||||
import pl.szczodrzynski.edziennik.data.api.edziennik.vulcan.data.VulcanHebe
|
||||
import pl.szczodrzynski.edziennik.data.api.events.MessageSentEvent
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Message
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.Teacher
|
||||
import pl.szczodrzynski.edziennik.ext.*
|
||||
import java.util.UUID
|
||||
|
||||
class VulcanHebeSendMessage(
|
||||
override val data: DataVulcan,
|
||||
@ -28,9 +31,9 @@ class VulcanHebeSendMessage(
|
||||
}
|
||||
|
||||
init {
|
||||
if (data.senderAddressName == null || data.senderAddressHash == null) {
|
||||
VulcanHebeMain(data).getStudents(data.profile, null) {
|
||||
if (data.senderAddressName == null || data.senderAddressHash == null) {
|
||||
if (data.messageBoxKey == null || data.messageBoxName == null) {
|
||||
VulcanHebeMessageBoxes(data, 0) {
|
||||
if (data.messageBoxKey == null || data.messageBoxName == null) {
|
||||
data.error(TAG, ERROR_VULCAN_HEBE_MISSING_SENDER_ENTRY)
|
||||
}
|
||||
else {
|
||||
@ -44,47 +47,64 @@ class VulcanHebeSendMessage(
|
||||
}
|
||||
|
||||
private fun sendMessage() {
|
||||
val uuid = UUID.randomUUID().toString()
|
||||
val globalKey = UUID.randomUUID().toString()
|
||||
val partition = "${data.symbol}-${data.schoolSymbol}"
|
||||
|
||||
val recipientsArray = JsonArray()
|
||||
recipients.forEach { teacher ->
|
||||
val loginId = teacher.loginId?.split(";", limit = 3) ?: return@forEach
|
||||
val key = loginId.getOrNull(0) ?: teacher.loginId
|
||||
val group = loginId.getOrNull(1)
|
||||
val name = loginId.getOrNull(2)
|
||||
if (key?.toIntOrNull() != null) {
|
||||
// raise error for old-format (non-UUID) login IDs
|
||||
data.error(TAG, ERROR_MESSAGE_NOT_SENT)
|
||||
return
|
||||
}
|
||||
recipientsArray += JsonObject(
|
||||
"Address" to teacher.fullNameLastFirst,
|
||||
"LoginId" to (teacher.loginId?.toIntOrNull() ?: return@forEach),
|
||||
"Initials" to teacher.initialsLastFirst,
|
||||
"AddressHash" to teacher.fullNameLastFirst.sha1Hex()
|
||||
"Id" to "${data.messageBoxKey}-${key}",
|
||||
"Partition" to partition,
|
||||
"Owner" to data.messageBoxKey,
|
||||
"GlobalKey" to key,
|
||||
"Name" to name,
|
||||
"Group" to group,
|
||||
"Initials" to "",
|
||||
"HasRead" to 0,
|
||||
)
|
||||
}
|
||||
|
||||
val senderName = (profile?.accountName ?: profile?.studentNameLong)
|
||||
?.swapFirstLastName() ?: ""
|
||||
val sender = JsonObject(
|
||||
"Address" to data.senderAddressName,
|
||||
"LoginId" to data.studentLoginId.toString(),
|
||||
"Initials" to senderName.getNameInitials(),
|
||||
"AddressHash" to data.senderAddressHash
|
||||
"Id" to "0",
|
||||
"Partition" to partition,
|
||||
"Owner" to data.messageBoxKey,
|
||||
"GlobalKey" to data.messageBoxKey,
|
||||
"Name" to data.messageBoxName,
|
||||
"Group" to "",
|
||||
"Initials" to "",
|
||||
"HasRead" to 0,
|
||||
)
|
||||
|
||||
apiPost(
|
||||
TAG,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGES_SEND,
|
||||
VULCAN_HEBE_ENDPOINT_MESSAGEBOX_SEND,
|
||||
payload = JsonObject(
|
||||
"Status" to 1,
|
||||
"Sender" to sender,
|
||||
"DateSent" to null,
|
||||
"DateRead" to null,
|
||||
"Content" to text,
|
||||
"Receiver" to recipientsArray,
|
||||
"Id" to 0,
|
||||
"Id" to uuid,
|
||||
"GlobalKey" to globalKey,
|
||||
"Partition" to partition,
|
||||
"ThreadKey" to globalKey, // TODO correct threadKey for reply messages
|
||||
"Subject" to subject,
|
||||
"Attachments" to null,
|
||||
"Self" to null
|
||||
"Content" to text,
|
||||
"Status" to 1,
|
||||
"Owner" to data.messageBoxKey,
|
||||
"DateSent" to buildDateTime(),
|
||||
"DateRead" to null,
|
||||
"Sender" to sender,
|
||||
"Receiver" to recipientsArray,
|
||||
"Attachments" to JsonArray(),
|
||||
)
|
||||
) { json: JsonObject, _ ->
|
||||
val messageId = json.getLong("Id")
|
||||
|
||||
if (messageId == null) {
|
||||
// TODO error
|
||||
return@apiPost
|
||||
}
|
||||
) { _: JsonObject, _ ->
|
||||
// TODO handle errors
|
||||
|
||||
VulcanHebeMessages(data, null) {
|
||||
val message = data.messageList.firstOrNull { it.isSent && it.subject == subject }
|
||||
|
@ -45,6 +45,7 @@ class VulcanHebeTeachers(
|
||||
|
||||
when (subjectName) {
|
||||
"Pedagog" -> teacher.setTeacherType(Teacher.TYPE_PEDAGOGUE)
|
||||
"Dyrektor" -> teacher.setTeacherType(Teacher.TYPE_PRINCIPAL)
|
||||
else -> {
|
||||
val subjectId = data.getSubject(null, subjectName).id
|
||||
if (!teacher.subjects.contains(subjectId))
|
||||
|
@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.App
|
||||
import pl.szczodrzynski.edziennik.BuildConfig
|
||||
import pl.szczodrzynski.edziennik.R
|
||||
import pl.szczodrzynski.edziennik.data.api.ERROR_REQUEST_FAILURE
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.MESSAGE_META
|
||||
import pl.szczodrzynski.edziennik.data.api.interfaces.EndpointCallback
|
||||
import pl.szczodrzynski.edziennik.data.db.AppDb
|
||||
import pl.szczodrzynski.edziennik.data.db.entity.*
|
||||
@ -489,11 +490,19 @@ abstract class Data(val app: App, val profile: Profile?, val loginStore: LoginSt
|
||||
teacherList[id] = this
|
||||
}
|
||||
return obj.also {
|
||||
if (loginId != null && it.loginId != null)
|
||||
if (loginId != null)
|
||||
it.loginId = loginId
|
||||
if (firstName.length > 1)
|
||||
it.name = firstName
|
||||
it.surname = lastName
|
||||
}
|
||||
}
|
||||
|
||||
fun parseMessageMeta(body: String): Map<String, String>? {
|
||||
val match = MESSAGE_META.find(body) ?: return null
|
||||
return match[1].split("&").associateBy(
|
||||
{ it.substringBefore("=") },
|
||||
{ it.substringAfter("=") },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -77,7 +77,7 @@ class MessagesComposeFragment : Fragment(), CoroutineScope {
|
||||
private lateinit var stylingConfig: StylingConfig
|
||||
private lateinit var uiConfig: UIConfig
|
||||
private val enableTextStyling
|
||||
get() = app.profile.loginStoreType != LoginStore.LOGIN_TYPE_VULCAN && app.profile.loginStoreType != LoginStore.LOGIN_TYPE_LIBRUS
|
||||
get() = app.profile.loginStoreType != LoginStore.LOGIN_TYPE_LIBRUS
|
||||
private var changedRecipients = false
|
||||
private var changedSubject = false
|
||||
private var changedBody = false
|
||||
|
@ -15,6 +15,7 @@ import android.text.style.*
|
||||
import androidx.appcompat.widget.AppCompatEditText
|
||||
import androidx.core.graphics.ColorUtils
|
||||
import androidx.core.text.HtmlCompat
|
||||
import pl.szczodrzynski.edziennik.data.api.Regexes.MESSAGE_META
|
||||
import pl.szczodrzynski.edziennik.ext.dp
|
||||
import pl.szczodrzynski.edziennik.ext.getWordBounds
|
||||
import pl.szczodrzynski.edziennik.ext.resolveAttr
|
||||
@ -45,7 +46,7 @@ object BetterHtml {
|
||||
.toRegex(RegexOption.IGNORE_CASE)
|
||||
|
||||
var text = html
|
||||
.replace("\\[META:[A-z0-9]+;[0-9-]+]".toRegex(), "")
|
||||
.replace(MESSAGE_META, "")
|
||||
.replace("background-color: ?$hexPattern;".toRegex(), "")
|
||||
// treat paragraphs as if they had no margin
|
||||
.replace("<p", "<span")
|
||||
|
@ -859,7 +859,7 @@
|
||||
<string name="settings_about_licenses_text">Open-source licenses</string>
|
||||
<string name="settings_about_privacy_policy_text">Privacy policy</string>
|
||||
<string name="settings_card_register_title">E-register</string>
|
||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 - 2022</string>
|
||||
<string name="settings_about_title_subtext">© Kuba Szczodrzyński && Kacper Ziubryniewicz\nSeptember 2018 – 2022</string>
|
||||
<string name="settings_about_update_subtext">Click to check for updates</string>
|
||||
<string name="settings_about_update_text">Update</string>
|
||||
<string name="settings_about_version_text">Version</string>
|
||||
|
@ -23,8 +23,8 @@ buildscript {
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:7.2.2'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||
classpath 'com.google.gms:google-services:4.3.13'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.1'
|
||||
classpath 'com.google.gms:google-services:4.3.14'
|
||||
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.9.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user