[Firebase] Implement Mobidziennik push service.

This commit is contained in:
Kuba Szczodrzyński 2020-01-16 09:27:30 +01:00
parent 5c4d6ed140
commit 6a54e7fef7
22 changed files with 299 additions and 41 deletions

View File

@ -445,24 +445,32 @@ public class App extends androidx.multidex.MultiDexApplication implements Config
try {
final long startTime = System.currentTimeMillis();
FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(instanceIdResult -> {
Log.d(TAG, "Token for App is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId()+". Time is "+(System.currentTimeMillis() - startTime));
config.getSync().setTokenApp(instanceIdResult.getToken());
if (!instanceIdResult.getToken().equals(config.getSync().getTokenApp())) {
Log.d(TAG, "Token for App is " + instanceIdResult.getToken());
config.getSync().setTokenApp(instanceIdResult.getToken());
}
});
/*FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
Log.d(TAG, "Token for Mobidziennik is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
appConfig.fcmTokens.put(LOGIN_TYPE_MOBIDZIENNIK, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
FirebaseInstanceId.getInstance(pushMobidziennikApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
if (!instanceIdResult.getToken().equals(config.getSync().getTokenMobidziennik())) {
Log.d(TAG, "Token for Mobidziennik2 is " + instanceIdResult.getToken());
config.getSync().setTokenMobidziennik(instanceIdResult.getToken());
config.getSync().setTokenMobidziennikList(new ArrayList<>());
}
});
FirebaseInstanceId.getInstance(pushLibrusApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
Log.d(TAG, "Token for Librus is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
appConfig.fcmTokens.put(LOGIN_TYPE_LIBRUS, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
if (!instanceIdResult.getToken().equals(config.getSync().getTokenLibrus())) {
Log.d(TAG, "Token for Librus is " + instanceIdResult.getToken());
config.getSync().setTokenLibrus(instanceIdResult.getToken());
config.getSync().setTokenLibrusList(new ArrayList<>());
}
});
FirebaseInstanceId.getInstance(pushVulcanApp).getInstanceId().addOnSuccessListener(instanceIdResult -> {
Log.d(TAG, "Token for Vulcan is " + instanceIdResult.getToken() + ", ID is " + instanceIdResult.getId());
Pair<String, List<Integer>> pair = appConfig.fcmTokens.get(LOGIN_TYPE_VULCAN);
if (pair == null || pair.first == null || !pair.first.equals(instanceIdResult.getToken())) {
appConfig.fcmTokens.put(LOGIN_TYPE_VULCAN, new Pair<>(instanceIdResult.getToken(), new ArrayList<>()));
if (!instanceIdResult.getToken().equals(config.getSync().getTokenVulcan())) {
Log.d(TAG, "Token for Vulcan is " + instanceIdResult.getToken());
config.getSync().setTokenVulcan(instanceIdResult.getToken());
config.getSync().setTokenVulcanList(new ArrayList<>());
}
});*/
});
FirebaseMessaging.getInstance().subscribeToTopic(getPackageName());

View File

@ -602,6 +602,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onApiTaskFinishedEvent(event: ApiTaskFinishedEvent) {
EventBus.getDefault().removeStickyEvent(event)
if (event.profileId == App.profileId) {
navView.toolbar.apply {
subtitleFormat = R.string.toolbar_subtitle
@ -612,6 +613,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onApiTaskAllFinishedEvent(event: ApiTaskAllFinishedEvent) {
EventBus.getDefault().removeStickyEvent(event)
swipeRefreshLayout.isRefreshing = false
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
@ -627,6 +629,7 @@ class MainActivity : AppCompatActivity(), CoroutineScope {
}
@Subscribe(threadMode = ThreadMode.MAIN, sticky = true)
fun onAppManagerDetectedEvent(event: AppManagerDetectedEvent) {
EventBus.getDefault().removeStickyEvent(event)
if (app.appConfig.dontShowAppManagerDialog)
return
MaterialAlertDialogBuilder(this)

View File

@ -91,7 +91,6 @@ fun Data.prepareFor(loginMethods: List<LoginMethod>, loginMethodId: Int) {
possibleLoginMethods += it.loginMethodId
}
targetEndpointIds.clear()
targetLoginMethodIds.clear()
// check the login method for any dependencies

View File

@ -129,6 +129,8 @@ const val ERROR_MOBIDZIENNIK_WEB_NO_SESSION_VALUE = 216
const val ERROR_MOBIDZIENNIK_WEB_NO_SERVER_ID = 213
const val ERROR_MOBIDZIENNIK_WEB_INVALID_RESPONSE = 214
const val ERROR_LOGIN_MOBIDZIENNIK_WEB_NO_SESSION_ID = 215
const val ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN = 216
const val ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER = 217
const val ERROR_LOGIN_VULCAN_INVALID_SYMBOL = 301
const val ERROR_LOGIN_VULCAN_INVALID_TOKEN = 302

View File

@ -41,6 +41,7 @@ internal const val FEATURE_PUSH_CONFIG = 120
object Features {
private fun getAllNecessary(): List<Int> = listOf(
FEATURE_ALWAYS_NEEDED,
FEATURE_PUSH_CONFIG,
FEATURE_STUDENT_INFO,
FEATURE_STUDENT_NUMBER,
FEATURE_SCHOOL_INFO,

View File

@ -11,6 +11,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginMessages
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginPortal
import pl.szczodrzynski.edziennik.data.api.edziennik.librus.login.LibrusLoginSynergia
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginWeb
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginApi
import pl.szczodrzynski.edziennik.data.api.edziennik.template.login.TemplateLoginWeb
@ -86,11 +87,11 @@ const val LOGIN_METHOD_MOBIDZIENNIK_API2 = 300
val mobidziennikLoginMethods = listOf(
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_WEB, MobidziennikLoginWeb::class.java)
.withIsPossible { _, _ -> true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }/*,
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED },
LoginMethod(LOGIN_TYPE_MOBIDZIENNIK, LOGIN_METHOD_MOBIDZIENNIK_API2, MobidziennikLoginApi2::class.java)
.withIsPossible { _, loginStore -> loginStore.hasLoginData("email") }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }*/
.withIsPossible { profile, _ -> profile?.hasStudentData("email") == true }
.withRequiredLoginMethod { _, _ -> LOGIN_METHOD_NOT_NEEDED }
)
const val LOGIN_TYPE_VULCAN = 4

View File

@ -23,6 +23,10 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
&& webSessionKey.isNotNullNorEmpty()
&& webServerId.isNotNullNorEmpty()
fun isApi2LoginValid() = loginEmail.isNotNullNorEmpty()
&& loginId.isNotNullNorEmpty()
&& globalId.isNotNullNorEmpty()
override fun satisfyLoginMethods() {
loginMethods.clear()
if (isWebLoginValid()) {
@ -44,11 +48,6 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
get() { mLoginServerName = mLoginServerName ?: loginStore.getLoginData("serverName", null); return mLoginServerName }
set(value) { loginStore.putLoginData("serverName", value); mLoginServerName = value }
private var mLoginEmail: String? = null
var loginEmail: String?
get() { mLoginEmail = mLoginEmail ?: loginStore.getLoginData("email", null); return mLoginEmail }
set(value) { loginStore.putLoginData("email", value); mLoginEmail = value }
private var mLoginUsername: String? = null
var loginUsername: String?
get() { mLoginUsername = mLoginUsername ?: loginStore.getLoginData("username", null); return mLoginUsername }
@ -90,6 +89,48 @@ class DataMobidziennik(app: App, profile: Profile?, loginStore: LoginStore) : Da
get() { mWebSessionIdExpiryTime = mWebSessionIdExpiryTime ?: loginStore.getLoginData("sessionIDTime", 0L); return mWebSessionIdExpiryTime ?: 0L }
set(value) { loginStore.putLoginData("sessionIDTime", value); mWebSessionIdExpiryTime = value }
/* _____ _____ ___
/\ | __ \_ _| |__ \
/ \ | |__) || | ) |
/ /\ \ | ___/ | | / /
/ ____ \| | _| |_ / /_
/_/ \_\_| |_____| |___*/
/**
* A global ID (whatever it is) used in API 2
* and Firebase push from Mobidziennik.
*/
var globalId: String?
get() { mGlobalId = mGlobalId ?: profile?.getStudentData("globalId", null); return mGlobalId }
set(value) { profile?.putStudentData("globalId", value) ?: return; mGlobalId = value }
private var mGlobalId: String? = null
/**
* User's email that may or may not
* be retrieved from Web by [MobidziennikWebAccountEmail].
* Used to log in to API 2.
*/
var loginEmail: String?
get() { mLoginEmail = mLoginEmail ?: profile?.getStudentData("email", null); return mLoginEmail }
set(value) { profile?.putStudentData("email", value); mLoginEmail = value }
private var mLoginEmail: String? = null
/**
* A login ID used in the API 2.
* Looks more or less like "7063@2019@zslpoznan".
*/
var loginId: String?
get() { mLoginId = mLoginId ?: profile?.getStudentData("loginId", null); return mLoginId }
set(value) { profile?.putStudentData("loginId", value) ?: return; mLoginId = value }
private var mLoginId: String? = null
/**
* No need to explain.
*/
var ciasteczkoAutoryzacji: String?
get() { mCiasteczkoAutoryzacji = mCiasteczkoAutoryzacji ?: profile?.getStudentData("ciasteczkoAutoryzacji", null); return mCiasteczkoAutoryzacji }
set(value) { profile?.putStudentData("ciasteczkoAutoryzacji", value) ?: return; mCiasteczkoAutoryzacji = value }
private var mCiasteczkoAutoryzacji: String? = null
override fun saveData() {
super.saveData()

View File

@ -22,16 +22,16 @@ const val ENDPOINT_MOBIDZIENNIK_API2_MAIN = 3000
val MobidziennikFeatures = listOf(
// always synced
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_ALWAYS_NEEDED, listOf(
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LOGIN_METHOD_MOBIDZIENNIK_WEB
ENDPOINT_MOBIDZIENNIK_API_MAIN to LOGIN_METHOD_MOBIDZIENNIK_WEB
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB)), // TODO divide features into separate view IDs (all with API_MAIN)
// push config
/*Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
Feature(LOGIN_TYPE_MOBIDZIENNIK, FEATURE_PUSH_CONFIG, listOf(
ENDPOINT_MOBIDZIENNIK_WEB_ACCOUNT_EMAIL to LOGIN_METHOD_MOBIDZIENNIK_WEB,
ENDPOINT_MOBIDZIENNIK_API2_MAIN to LOGIN_METHOD_MOBIDZIENNIK_API2
), listOf(LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data ->
data.app.appConfig.fcmTokens[LOGIN_TYPE_MOBIDZIENNIK]?.second?.contains(data.profileId) == false
},*/
), listOf(LOGIN_METHOD_MOBIDZIENNIK_WEB, LOGIN_METHOD_MOBIDZIENNIK_API2)).withShouldSync { data ->
!data.app.config.sync.tokenMobidziennikList.contains(data.profileId)
},

View File

@ -7,6 +7,7 @@ package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data
import pl.szczodrzynski.edziennik.R
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api.MobidziennikApi
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2.MobidziennikApi2Main
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebCalendar
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebGrades
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.web.MobidziennikWebMessagesAll
@ -44,6 +45,10 @@ class MobidziennikData(val data: DataMobidziennik, val onSuccess: () -> Unit) {
data.startProgress(R.string.edziennik_progress_endpoint_data)
MobidziennikApi(data, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_API2_MAIN -> {
data.startProgress(R.string.edziennik_progress_endpoint_push_config)
MobidziennikApi2Main(data, onSuccess)
}
ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX -> {
data.startProgress(R.string.edziennik_progress_endpoint_messages_inbox)
MobidziennikWebMessagesInbox(data) { onSuccess() }

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-12.
*/
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.api2
import com.google.gson.JsonObject
import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_API2_MAIN
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login.MobidziennikLoginApi2
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.getJsonObject
import pl.szczodrzynski.edziennik.getString
import pl.szczodrzynski.edziennik.utils.Utils
class MobidziennikApi2Main(val data: DataMobidziennik,
val onSuccess: () -> Unit) {
companion object {
private const val TAG = "MobidziennikApi2Main"
}
val profileId
get() = data.profile?.id ?: -1
val profile
get() = data.profile
init {
Utils.d(TAG, "Request: Mobidziennik/Api2/Main - https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {
if (json == null) {
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
.withResponse(response))
return
}
json.getJsonObject("error")?.let {
val text = it.getString("type") ?: it.getString("message")
when (text) {
"LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
// TODO other error types
else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
.withApiResponse(text)
.withResponse(response))
return
}
}
val user = json.getJsonObject("user")
data.ciasteczkoAutoryzacji = user.getString("auth_key")
// sync always: this endpoint has .shouldSync set
data.setSyncNext(ENDPOINT_MOBIDZIENNIK_API2_MAIN, SYNC_ALWAYS)
data.app.config.sync.tokenMobidziennikList =
data.app.config.sync.tokenMobidziennikList + profileId
onSuccess()
}
override fun onFailure(response: Response?, throwable: Throwable?) {
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
.withResponse(response)
.withThrowable(throwable))
}
}
Request.builder()
.url("https://${data.loginServerName}.mobidziennik.pl/api2/logowanie")
.userAgent(MOBIDZIENNIK_USER_AGENT)
.contentType("application/x-www-form-urlencoded; charset=UTF-8")
.addParameter("login", data.loginId)
.addParameter("email", data.loginEmail)
.addParameter("haslo", data.loginPassword)
.addParameter("device", MobidziennikLoginApi2.getDevice(data.app).toString())
.apply {
data.ciasteczkoAutoryzacji?.let { addParameter("ciasteczko_autoryzacji", it) }
}
.post()
.callback(callback)
.build()
.enqueue()
}
}

View File

@ -9,16 +9,16 @@ import pl.szczodrzynski.edziennik.data.api.Regexes
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_CALENDAR
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.entity.Event
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
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) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebCalendar"
}

View File

@ -12,9 +12,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
import pl.szczodrzynski.edziennik.data.api.events.MessageGetEvent
import pl.szczodrzynski.edziennik.data.db.entity.Message
import pl.szczodrzynski.edziennik.data.db.entity.Message.TYPE_RECEIVED
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.full.MessageFull
import pl.szczodrzynski.edziennik.data.db.full.MessageRecipientFull
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.fixName
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.singleOrNull
@ -25,7 +25,7 @@ import pl.szczodrzynski.edziennik.utils.models.Time
class MobidziennikWebGetMessage(
override val data: DataMobidziennik,
private val message: MessageFull,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebGetMessage"
}

View File

@ -11,9 +11,9 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidzienn
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_GRADES
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.api.models.DataRemoveModel
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.entity.Grade
import pl.szczodrzynski.edziennik.data.db.entity.Metadata
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.fixWhiteSpaces
import pl.szczodrzynski.edziennik.get
import pl.szczodrzynski.edziennik.singleOrNull
@ -21,7 +21,7 @@ import pl.szczodrzynski.edziennik.utils.models.Date
import pl.szczodrzynski.edziennik.utils.models.Time
class MobidziennikWebGrades(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebGrades"
}

View File

@ -19,7 +19,7 @@ import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikWebMessagesAll(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebMessagesAll"
}

View File

@ -8,16 +8,16 @@ import org.jsoup.Jsoup
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.ENDPOINT_MOBIDZIENNIK_WEB_MESSAGES_INBOX
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.MobidziennikWeb
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
import pl.szczodrzynski.edziennik.data.db.entity.Message
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.fixName
import pl.szczodrzynski.edziennik.singleOrNull
import pl.szczodrzynski.edziennik.utils.models.Date
class MobidziennikWebMessagesInbox(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebMessagesInbox"
}

View File

@ -10,7 +10,7 @@ import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.data.Mobidzien
import pl.szczodrzynski.edziennik.data.db.entity.SYNC_ALWAYS
class MobidziennikWebNotices(override val data: DataMobidziennik,
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
val onSuccess: () -> Unit) : MobidziennikWeb(data) {
companion object {
private const val TAG = "MobidziennikWebNotices"
}

View File

@ -52,7 +52,7 @@ class MobidziennikLogin(val data: DataMobidziennik, val onSuccess: () -> Unit) {
}
LOGIN_METHOD_MOBIDZIENNIK_API2 -> {
data.startProgress(R.string.edziennik_progress_login_mobidziennik_api2)
//MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
MobidziennikLoginApi2(data) { onSuccess(loginMethodId) }
}
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright (c) Kuba Szczodrzyński 2020-1-12.
*/
package pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.login
import android.os.Build
import com.google.gson.JsonObject
import im.wangchao.mhttp.Request
import im.wangchao.mhttp.Response
import im.wangchao.mhttp.callback.JsonCallbackHandler
import pl.szczodrzynski.edziennik.*
import pl.szczodrzynski.edziennik.data.api.*
import pl.szczodrzynski.edziennik.data.api.edziennik.mobidziennik.DataMobidziennik
import pl.szczodrzynski.edziennik.data.api.models.ApiError
import pl.szczodrzynski.edziennik.utils.Utils
class MobidziennikLoginApi2(val data: DataMobidziennik, val onSuccess: () -> Unit) {
companion object {
private const val TAG = "MobidziennikLoginApi2"
fun getDevice(app: App) = JsonObject(
"available" to true,
"platform" to "Android",
"version" to Build.VERSION.RELEASE,
"uuid" to app.deviceId,
"cordova" to "7.1.2",
"model" to "${Build.MANUFACTURER} ${Build.MODEL}",
"manufacturer" to "Aplikacja Szkolny.eu",
"isVirtual" to false,
"serial" to try { System.getProperty("ro.serialno") ?: System.getProperty("ro.boot.serialno") } catch (_: Exception) { Build.UNKNOWN },
"appVersion" to "10.6, 2020.01.09-12.15.53",
"pushRegistrationId" to app.config.sync.tokenMobidziennik
)
}
init { run {
if (data.isApi2LoginValid()) {
onSuccess()
}
else {
if (data.loginServerName.isNotNullNorEmpty() && data.loginEmail.isNotNullNorEmpty() && data.loginPassword.isNotNullNorEmpty()) {
loginWithCredentials()
}
else {
data.error(ApiError(TAG, ERROR_LOGIN_DATA_MISSING))
}
}
}}
private fun loginWithCredentials() {
Utils.d(TAG, "Request: Mobidziennik/Login/Api2 - https://mobidziennik.pl/logowanie")
val callback = object : JsonCallbackHandler() {
override fun onSuccess(json: JsonObject?, response: Response?) {
if (json == null) {
data.error(ApiError(TAG, ERROR_RESPONSE_EMPTY)
.withResponse(response))
return
}
json.getJsonObject("error")?.let {
val text = it.getString("type") ?: it.getString("message")
when (text) {
"LOGIN_ERROR" -> ERROR_LOGIN_MOBIDZIENNIK_API2_INVALID_LOGIN
// TODO other error types
else -> ERROR_LOGIN_MOBIDZIENNIK_API2_OTHER
}.let { errorCode ->
data.error(ApiError(TAG, errorCode)
.withApiResponse(text)
.withResponse(response))
return
}
}
data.loginEmail = json.getString("email")
data.globalId = json.getString("id_global")
data.loginId = json.getString("login")
onSuccess()
}
override fun onFailure(response: Response?, throwable: Throwable?) {
data.error(ApiError(TAG, ERROR_REQUEST_FAILURE)
.withResponse(response)
.withThrowable(throwable))
}
}
Request.builder()
.url("https://mobidziennik.pl/logowanie")
.userAgent(MOBIDZIENNIK_USER_AGENT)
.contentType("application/x-www-form-urlencoded; charset=UTF-8")
.addParameter("api2", true)
.addParameter("email", data.loginEmail)
.addParameter("haslo", data.loginPassword)
.addParameter("device", getDevice(data.app).toString())
.post()
.callback(callback)
.build()
.enqueue()
}
}

View File

@ -133,7 +133,7 @@ open class FirebaseService : zzc() {
data class Message(val messageId: String?, private val json: JsonObject) {
val data = json.deepCopy()
val from by lazy { s("from") ?: "" }
val from by lazy { s("test.from") ?: s("from") ?: "" }
val to by lazy { s("google.to") }
val messageType by lazy { s("message_type") }
val collapseKey by lazy { s("collapse_key") }

View File

@ -4,6 +4,7 @@
package pl.szczodrzynski.edziennik.data.firebase
import android.content.Context
import android.util.Log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
@ -31,6 +32,10 @@ class MyFirebaseService : FirebaseService(), CoroutineScope {
override fun onMessageReceived(message: Message) {
launch(Dispatchers.Default) {
Log.d(TAG, "Message received from ${message.from}: $message")
app.getSharedPreferences("firebase_service_log", Context.MODE_PRIVATE).edit().apply {
putString(System.currentTimeMillis().toString(), message.toString())
apply()
}
val profiles = app.db.profileDao().profilesForSyncNow
when (message.from) {
"640759989760" -> SzkolnyAppFirebase(app, profiles, message)

View File

@ -4,7 +4,6 @@
package pl.szczodrzynski.edziennik.ui.modules.error
import android.graphics.Color
import android.view.View
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
@ -41,7 +40,7 @@ class ErrorSnackbar(val activity: AppCompatActivity) : CoroutineScope {
if (errors.isNotEmpty()) {
val message = errors.map {
listOf(
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(Color.BLACK),
it.getStringReason(activity).asBoldSpannable().asColoredSpannable(R.attr.colorOnBackground.resolveAttr(activity)),
if (App.devMode)
it.throwable?.stackTraceString ?: it.throwable?.localizedMessage
else

View File

@ -1159,4 +1159,5 @@
<string name="event_manual_remove">Usuwam wydarzenie...</string>
<string name="counter_activity_sync">Synchronizuj</string>
<string name="notification_day_free">Dzień wolny</string>
<string name="edziennik_progress_endpoint_push_config">Konfigurowanie natychmiastowych powiadomień...</string>
</resources>