[APIv2/Mobidziennik] Add Lucky number, Class calendar, better exception handling

This commit is contained in:
Kuba Szczodrzyński 2019-10-10 18:56:05 +02:00
parent 2730c73413
commit 7b3e2a9ea0
9 changed files with 162 additions and 8 deletions

View File

@ -122,4 +122,5 @@ const val ERROR_TEMPLATE_WEB_OTHER = 801
const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901 const val EXCEPTION_LOGIN_LIBRUS_API_TOKEN = 901
const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902 const val EXCEPTION_LOGIN_LIBRUS_PORTAL_TOKEN = 902
const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903 const val EXCEPTION_LIBRUS_PORTAL_SYNERGIA_TOKEN = 903
const val EXCEPTION_LIBRUS_API_REQUEST = 904 const val EXCEPTION_LIBRUS_API_REQUEST = 904
const val EXCEPTION_MOBIDZIENNIK_WEB_REQUEST = 905

View File

@ -4,8 +4,6 @@
package pl.szczodrzynski.edziennik.api.v2 package pl.szczodrzynski.edziennik.api.v2
import java.util.regex.Pattern
object Regexes { object Regexes {
val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy { val MOBIDZIENNIK_GRADES_SUBJECT_NAME by lazy {
"<div.*?>\\n*\\s*(.+?)\\s*\\n*(?:<.*?)??</div>".toRegex(RegexOption.DOT_MATCHES_ALL) "<div.*?>\\n*\\s*(.+?)\\s*\\n*(?:<.*?)??</div>".toRegex(RegexOption.DOT_MATCHES_ALL)
@ -13,4 +11,10 @@ object Regexes {
val MOBIDZIENNIK_EVENT_TYPE by lazy { val MOBIDZIENNIK_EVENT_TYPE by lazy {
"\\(([0-9A-ząęóżźńśłć]*?)\\)$".toRegex(RegexOption.DOT_MATCHES_ALL) "\\(([0-9A-ząęóżźńśłć]*?)\\)$".toRegex(RegexOption.DOT_MATCHES_ALL)
} }
val MOBIDZIENNIK_LUCKY_NUMBER by lazy {
"class=\"szczesliwy_numerek\".*>0*([0-9]+)(?:/0*[0-9]+)*</a>".toRegex(RegexOption.DOT_MATCHES_ALL)
}
val MOBIDZIENNIK_CLASS_CALENDAR by lazy {
"events: (.+),$".toRegex(RegexOption.DOT_MATCHES_ALL)
}
} }

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data
import pl.szczodrzynski.edziennik.R import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.* import pl.szczodrzynski.edziennik.api.v2.mobidziennik.*
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikApi import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikApi
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web.MobidziennikWebCalendar
import pl.szczodrzynski.edziennik.utils.Utils import pl.szczodrzynski.edziennik.utils.Utils
class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) { class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
@ -46,11 +47,11 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL -> { ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_ALL -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages) data.startProgress(R.string.edziennik_progress_endpoint_messages)
MobidziennikWebMessagesAll(data) { onSuccess() } MobidziennikWebMessagesAll(data) { onSuccess() }
} }*/
ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR -> { ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR -> {
data.startProgress(R.string.edziennik_progress_endpoint_calendar) data.startProgress(R.string.edziennik_progress_endpoint_calendar)
MobidziennikWebCalendar(data) { onSuccess() } MobidziennikWebCalendar(data) { onSuccess() }
} }/*
ENDPOINT_MOBIDZIENNIK_WEB_GRADES -> { ENDPOINT_MOBIDZIENNIK_WEB_GRADES -> {
data.startProgress(R.string.edziennik_progress_endpoint_grades) data.startProgress(R.string.edziennik_progress_endpoint_grades)
MobidziennikWebGrades(data) { onSuccess() } MobidziennikWebGrades(data) { onSuccess() }

View File

@ -49,13 +49,22 @@ open class MobidziennikWeb(open val data: DataMobidziennik) {
.withResponse(response)) .withResponse(response))
return return
} }
if (text == "Nie jestes zalogowany") { if (text == "Nie jestes zalogowany"
|| text.contains("przypomnij_haslo_email")) {
data.error(ApiError(TAG, ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED) data.error(ApiError(TAG, ERROR_MOBIDZIENNIK_WEB_ACCESS_DENIED)
.withResponse(response)) .withResponse(response))
return return
} }
onSuccess(text) try {
onSuccess(text)
} catch (e: Exception) {
data.error(ApiError(tag, EXCEPTION_MOBIDZIENNIK_WEB_REQUEST)
.withResponse(response)
.withThrowable(e)
.withApiResponse(text)
.setCritical(false))
}
} }
override fun onFailure(response: Response?, throwable: Throwable?) { override fun onFailure(response: Response?, throwable: Throwable?) {

View File

@ -0,0 +1,32 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-10.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
import pl.szczodrzynski.edziennik.api.v2.Regexes
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikLuckyNumberExtractor(val data: DataMobidziennik, text: String) {
init {
data.profile?.luckyNumber = -1
data.profile?.luckyNumberDate = Date.getToday()
Regexes.MOBIDZIENNIK_LUCKY_NUMBER.find(text)?.let {
try {
val luckyNumber = it.groupValues[1].toInt()
data.profile?.luckyNumber = luckyNumber
data.profile?.luckyNumberDate = Date.getToday()
data.luckyNumberList.add(
LuckyNumber(
data.profileId,
Date.getToday(),
luckyNumber
))
} catch (_: Exception){}
}
}
}

View File

@ -0,0 +1,97 @@
/*
* Copyright (c) Kuba Szczodrzyński 2019-10-10.
*/
package pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.web
import com.google.gson.JsonParser
import pl.szczodrzynski.edziennik.api.v2.Regexes
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.api.v2.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.db.modules.events.Event
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.Utils.crc16
import pl.szczodrzynski.edziennik.utils.models.Date
import java.util.*
class MobidziennikWebCalendar(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebCalendar"
}
init {
webGet(TAG, "/dziennik/kalendarzklasowy") { text ->
MobidziennikLuckyNumberExtractor(data, text)
Regexes.MOBIDZIENNIK_CLASS_CALENDAR.find(text)?.let {
val events = JsonParser().parse(it.groupValues[1]).asJsonArray
for (eventEl in events) {
val event = eventEl.asJsonObject
val idStr = event.getString("id")
if (idStr?.startsWith("kalendarz;") != true) {
continue
}
val idParts = idStr.split(";")
if (idParts.size < 2) {
continue
}
var id = idParts[2].toLongOrNull() ?: -1
val studentId = idParts[1].toIntOrNull() ?: continue
if (studentId != data.studentId)
continue
val dateString = event.getString("start") ?: continue
val eventDate = Date.fromY_m_d(dateString)
val eventType = when (event.getString("color")?.toLowerCase(Locale.getDefault())) {
"#c54449" -> Event.TYPE_SHORT_QUIZ
"#ab0001" -> Event.TYPE_EXAM
"#008928" -> Event.TYPE_CLASS_EVENT
"#b66000" -> Event.TYPE_EXCURSION
else -> Event.TYPE_INFORMATION
}
val title = event.getString("title")
val comment = event.getString("comment")
var topic = title
if (title != comment) {
topic += "\n" + comment
}
if (id == -1L) {
id = crc16(topic?.toByteArray()).toLong()
}
val eventObject = Event(
profileId,
id,
eventDate, null,
topic,
-1,
eventType,
false,
-1,
-1,
data.teamClass?.id ?: -1
)
data.eventList.add(eventObject)
data.metadataList.add(
Metadata(
profileId,
Metadata.TYPE_EVENT,
eventObject.id,
profile?.empty ?: false,
profile?.empty ?: false,
System.currentTimeMillis() /* no addedDate here though */
))
}
}
onSuccess()
}
}
}

View File

@ -34,7 +34,7 @@ class MobidziennikApiEvents(val data: DataMobidziennik, rows: List<String>) {
var type = Event.TYPE_DEFAULT var type = Event.TYPE_DEFAULT
var topic = cols[5] var topic = cols[5]
Regexes.MOBIDZIENNIK_EVENT_TYPE.find(topic)?.let { Regexes.MOBIDZIENNIK_EVENT_TYPE.find(topic)?.let {
val typeText = it.value val typeText = it.groupValues[1]
when (typeText) { when (typeText) {
"sprawdzian" -> type = Event.TYPE_EXAM "sprawdzian" -> type = Event.TYPE_EXAM
"kartkówka" -> type = Event.TYPE_SHORT_QUIZ "kartkówka" -> type = Event.TYPE_SHORT_QUIZ

View File

@ -19,6 +19,7 @@ import pl.szczodrzynski.edziennik.data.db.modules.lessons.Lesson
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonChange
import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange import pl.szczodrzynski.edziennik.data.db.modules.lessons.LessonRange
import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore import pl.szczodrzynski.edziennik.data.db.modules.login.LoginStore
import pl.szczodrzynski.edziennik.data.db.modules.luckynumber.LuckyNumber
import pl.szczodrzynski.edziennik.data.db.modules.messages.Message import pl.szczodrzynski.edziennik.data.db.modules.messages.Message
import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient import pl.szczodrzynski.edziennik.data.db.modules.messages.MessageRecipient
import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata import pl.szczodrzynski.edziennik.data.db.modules.metadata.Metadata
@ -134,6 +135,8 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
var announcementsToRemove: DataRemoveModel? = null var announcementsToRemove: DataRemoveModel? = null
val announcementList = mutableListOf<Announcement>() val announcementList = mutableListOf<Announcement>()
val luckyNumberList = mutableListOf<LuckyNumber>()
val messageList = mutableListOf<Message>() val messageList = mutableListOf<Message>()
val messageRecipientList = mutableListOf<MessageRecipient>() val messageRecipientList = mutableListOf<MessageRecipient>()
val messageRecipientIgnoreList = mutableListOf<MessageRecipient>() val messageRecipientIgnoreList = mutableListOf<MessageRecipient>()
@ -179,6 +182,7 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
noticeList.clear() noticeList.clear()
attendanceList.clear() attendanceList.clear()
announcementList.clear() announcementList.clear()
luckyNumberList.clear()
messageList.clear() messageList.clear()
messageRecipientList.clear() messageRecipientList.clear()
messageRecipientIgnoreList.clear() messageRecipientIgnoreList.clear()
@ -229,6 +233,9 @@ open class Data(val app: App, val profile: Profile?, val loginStore: LoginStore)
db.attendanceDao().addAll(attendanceList) db.attendanceDao().addAll(attendanceList)
if (announcementList.isNotEmpty()) if (announcementList.isNotEmpty())
db.announcementDao().addAll(announcementList) db.announcementDao().addAll(announcementList)
if (luckyNumberList.isNotEmpty())
db.luckyNumberDao().addAll(luckyNumberList)
if (messageList.isNotEmpty()) if (messageList.isNotEmpty())
db.messageDao().addAllIgnore(messageList) db.messageDao().addAllIgnore(messageList)
if (messageRecipientList.isNotEmpty()) if (messageRecipientList.isNotEmpty())

View File

@ -15,6 +15,9 @@ public interface LuckyNumberDao {
@Insert(onConflict = OnConflictStrategy.REPLACE) @Insert(onConflict = OnConflictStrategy.REPLACE)
void add(LuckyNumber luckyNumber); void add(LuckyNumber luckyNumber);
@Insert(onConflict = OnConflictStrategy.REPLACE)
void addAll(List<LuckyNumber> luckyNumberList);
@Query("DELETE FROM luckyNumbers WHERE profileId = :profileId") @Query("DELETE FROM luckyNumbers WHERE profileId = :profileId")
void clear(int profileId); void clear(int profileId);