diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/App.java b/app/src/main/java/pl/szczodrzynski/edziennik/App.java index 0c0ecb88..56342064 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/App.java +++ b/app/src/main/java/pl/szczodrzynski/edziennik/App.java @@ -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> 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()); diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt index 597c65a3..eac5f03c 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/MainActivity.kt @@ -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) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt index 2cdd33f9..24872b27 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/EndpointChooser.kt @@ -91,7 +91,6 @@ fun Data.prepareFor(loginMethods: List, loginMethodId: Int) { possibleLoginMethods += it.loginMethodId } - targetEndpointIds.clear() targetLoginMethodIds.clear() // check the login method for any dependencies diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt index 37e63142..4941ade6 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Errors.kt @@ -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 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt index 14aca79f..0e75753b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/Features.kt @@ -41,6 +41,7 @@ internal const val FEATURE_PUSH_CONFIG = 120 object Features { private fun getAllNecessary(): List = listOf( FEATURE_ALWAYS_NEEDED, + FEATURE_PUSH_CONFIG, FEATURE_STUDENT_INFO, FEATURE_STUDENT_NUMBER, FEATURE_SCHOOL_INFO, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt index c9a2568f..9526bb96 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/LoginMethods.kt @@ -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 diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt index be2b2cd4..8f32d59b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/DataMobidziennik.kt @@ -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() diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt index c08846c9..7c5ca4e5 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/MobidziennikFeatures.kt @@ -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) + }, diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt index 0ceeb49a..a51e6130 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/MobidziennikData.kt @@ -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() } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt new file mode 100644 index 00000000..187b1d59 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/api2/MobidziennikApi2Main.kt @@ -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() + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt index ee823a99..7dfe2861 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebCalendar.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt index bbf9e59a..272c6425 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGetMessage.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt index 70f7bd71..8866f884 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebGrades.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt index a9786280..5a134cf3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesAll.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt index 8bfd8e15..aabb05a1 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebMessagesInbox.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt index f197f389..275d876f 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/data/web/MobidziennikWebNotices.kt @@ -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" } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt index 498ab2e3..7bc79a7b 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLogin.kt @@ -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) } } } } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt new file mode 100644 index 00000000..db750981 --- /dev/null +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/api/edziennik/mobidziennik/login/MobidziennikLoginApi2.kt @@ -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() + } +} diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/FirebaseService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/FirebaseService.kt index 53e9d94b..a8f6e762 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/FirebaseService.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/FirebaseService.kt @@ -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") } diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/MyFirebaseService.kt b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/MyFirebaseService.kt index b5eb6811..8099da42 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/MyFirebaseService.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/data/firebase/MyFirebaseService.kt @@ -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) diff --git a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorSnackbar.kt b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorSnackbar.kt index a0488509..607501c3 100644 --- a/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorSnackbar.kt +++ b/app/src/main/java/pl/szczodrzynski/edziennik/ui/modules/error/ErrorSnackbar.kt @@ -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 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e7c8eb56..e3783e30 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1159,4 +1159,5 @@ Usuwam wydarzenie... Synchronizuj Dzień wolny + Konfigurowanie natychmiastowych powiadomień...