From aea5ca4988287eb8ee1e2ee4540d7a61547653ef Mon Sep 17 00:00:00 2001 From: HuanCheng65 <22636177+HuanCheng65@users.noreply.github.com> Date: Sat, 18 Feb 2023 17:30:48 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BF=9D=E5=AD=98=20baiduid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tieba/post/activities/LoginActivity.kt | 95 +++++++++++-------- .../tieba/post/api/HttpConstant.kt | 4 +- .../post/api/retrofit/RetrofitTiebaApi.kt | 7 +- ...erceptor.kt => AddWebCookieInterceptor.kt} | 8 +- .../interceptors/CookieInterceptor.kt | 33 +++++++ .../api/retrofit/interfaces/WebTiebaApi.kt | 6 +- .../tieba/post/utils/ClientUtils.kt | 17 +++- 7 files changed, 119 insertions(+), 51 deletions(-) rename app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/{AddCookieInterceptor.kt => AddWebCookieInterceptor.kt} (80%) create mode 100644 app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/CookieInterceptor.kt diff --git a/app/src/main/java/com/huanchengfly/tieba/post/activities/LoginActivity.kt b/app/src/main/java/com/huanchengfly/tieba/post/activities/LoginActivity.kt index 376f8ea8..92197289 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/activities/LoginActivity.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/activities/LoginActivity.kt @@ -1,6 +1,5 @@ package com.huanchengfly.tieba.post.activities -import android.content.Intent import android.graphics.Bitmap import android.os.Bundle import android.os.Handler @@ -13,6 +12,7 @@ import com.huanchengfly.tieba.post.api.retrofit.exception.getErrorMessage import com.huanchengfly.tieba.post.fragments.WebViewFragment import com.huanchengfly.tieba.post.interfaces.WebViewListener import com.huanchengfly.tieba.post.utils.AccountUtil +import com.huanchengfly.tieba.post.utils.ClientUtils import com.huanchengfly.tieba.post.utils.ThemeUtil import com.huanchengfly.tieba.post.utils.Util import kotlinx.coroutines.Dispatchers @@ -21,6 +21,8 @@ import kotlinx.coroutines.flow.flowOn import kotlinx.coroutines.launch class LoginActivity : BaseActivity(), WebViewListener { + private var isLoadingAccount = false + private var toolbar: Toolbar? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) @@ -48,49 +50,66 @@ class LoginActivity : BaseActivity(), WebViewListener { toolbar!!.title = newTitle } + // 从 Cookies 字符串解析出每个 Cookie + fun parseCookies(cookies: String): Map { + val cookieMap = mutableMapOf() + cookies.split(";").forEach { + val cookie = it.trim() + val cookieSplit = cookie.split("=").toMutableList() + if (cookieSplit.size > 1) { + val name = cookieSplit.removeFirst() + cookieMap[name] = cookieSplit.joinToString("=") + } + } + return cookieMap + } + override fun onPageFinished(view: WebView, url: String) { + if (isLoadingAccount) { + return + } val cookieManager = CookieManager.getInstance() - val cookies = cookieManager.getCookie(url) - if (cookies != null) { - val bdussSplit = cookies.split("BDUSS=") - val sTokenSplit = cookies.split("STOKEN=") - if (bdussSplit.size > 1 && sTokenSplit.size > 1) { - val bduss = bdussSplit[1].split(";")[0] - val sToken = sTokenSplit[1].split(";")[0] - if (url.startsWith("https://tieba.baidu.com/index/tbwise/") || url.startsWith("https://tiebac.baidu.com/index/tbwise/")) { - val snackBar = Util.createSnackbar(view, "请稍后…", Snackbar.LENGTH_INDEFINITE) - snackBar.show() - launch { - AccountUtil.fetchAccountFlow(bduss, sToken, cookies) - .flowOn(Dispatchers.IO) - .catch { e -> - snackBar.setText("登录失败 ${e.getErrorMessage()}") + val cookiesStr = cookieManager.getCookie(url) ?: "" + val cookies = parseCookies(cookiesStr) + val bduss = cookies["BDUSS"] + val sToken = cookies["STOKEN"] + val baiduId = cookies["BAIDUID"] + if (url.startsWith("https://tieba.baidu.com/index/tbwise/") || url.startsWith("https://tiebac.baidu.com/index/tbwise/")) { + if (bduss == null || sToken == null) { + return + } + if (!baiduId.isNullOrEmpty() && ClientUtils.baiduId.isNullOrEmpty()) launch { + ClientUtils.saveBaiduId( + this@LoginActivity, + baiduId + ) + } + val snackBar = Util.createSnackbar(view, "请稍后…", Snackbar.LENGTH_INDEFINITE) + isLoadingAccount = true + snackBar.show() + launch { + AccountUtil.fetchAccountFlow(bduss, sToken, cookiesStr) + .flowOn(Dispatchers.IO) + .catch { e -> + snackBar.setText("登录失败 ${e.getErrorMessage()}") + isLoadingAccount = false + view.loadUrl("https://wappass.baidu.com/passport?login&u=https%3A%2F%2Ftieba.baidu.com%2Findex%2Ftbwise%2Fmine") + handler.postDelayed({ snackBar.dismiss() }, 1500) + } + .flowOn(Dispatchers.Main) + .collect { account -> + AccountUtil.newAccount(account.uid, account) { + isLoadingAccount = false + if (it) { + AccountUtil.switchUser(this@LoginActivity, account.id) + snackBar.setText("登录成功,即将跳转") + } else { + snackBar.setText("登录失败 未知错误") view.loadUrl("https://wappass.baidu.com/passport?login&u=https%3A%2F%2Ftieba.baidu.com%2Findex%2Ftbwise%2Fmine") handler.postDelayed({ snackBar.dismiss() }, 1500) } - .flowOn(Dispatchers.Main) - .collect { account -> - AccountUtil.newAccount(account.uid, account) { - if (it) { - AccountUtil.switchUser(this@LoginActivity, account.id) - snackBar.setText("登录成功,即将跳转") - handler.postDelayed({ - snackBar.dismiss() - finish() - startActivity( - Intent( - this@LoginActivity, - UpdateInfoActivity::class.java - ) - ) - }, 1500) - } else { - snackBar.setText("登录失败 未知错误") - } - } - } + } } - } } } } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/HttpConstant.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/HttpConstant.kt index ea00b4f8..98cebac4 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/HttpConstant.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/HttpConstant.kt @@ -30,8 +30,8 @@ object Header { const val DROP_HEADERS = "drop_headers" const val NO_COMMON_PARAMS = "no_common_params" - const val ADD_COOKIE = "add_cookie" - const val ADD_COOKIE_FALSE = "false" + const val ADD_WEB_COOKIE = "add_cookie" + const val ADD_WEB_COOKIE_FALSE = "false" const val ACCEPT_LANGUAGE = "Accept-Language" const val ACCEPT_LANGUAGE_VALUE = "zh-CN,zh;q=0.9" diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt index 2c417744..97f307d4 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/RetrofitTiebaApi.kt @@ -9,9 +9,10 @@ import com.huanchengfly.tieba.post.api.models.OAID import com.huanchengfly.tieba.post.api.retrofit.adapter.DeferredCallAdapterFactory import com.huanchengfly.tieba.post.api.retrofit.adapter.FlowCallAdapterFactory import com.huanchengfly.tieba.post.api.retrofit.converter.gson.GsonConverterFactory -import com.huanchengfly.tieba.post.api.retrofit.interceptors.AddCookieInterceptor +import com.huanchengfly.tieba.post.api.retrofit.interceptors.AddWebCookieInterceptor import com.huanchengfly.tieba.post.api.retrofit.interceptors.CommonHeaderInterceptor import com.huanchengfly.tieba.post.api.retrofit.interceptors.CommonParamInterceptor +import com.huanchengfly.tieba.post.api.retrofit.interceptors.CookieInterceptor import com.huanchengfly.tieba.post.api.retrofit.interceptors.DropInterceptor import com.huanchengfly.tieba.post.api.retrofit.interceptors.FailureResponseInterceptor import com.huanchengfly.tieba.post.api.retrofit.interceptors.ForceLoginInterceptor @@ -98,7 +99,8 @@ object RetrofitTiebaApi { Header.CHARSET to { "UTF-8" }, Header.HOST to { "tieba.baidu.com" }, ), - AddCookieInterceptor) + AddWebCookieInterceptor + ) } val MINI_TIEBA_API: MiniTiebaApi by lazy { @@ -247,6 +249,7 @@ object RetrofitTiebaApi { addInterceptor(DropInterceptor) addInterceptor(ProtoFailureResponseInterceptor) addInterceptor(ForceLoginInterceptor) + addInterceptor(CookieInterceptor) addInterceptor(sortAndSignInterceptor) connectionPool(connectionPool) }.build()) diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddCookieInterceptor.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddWebCookieInterceptor.kt similarity index 80% rename from app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddCookieInterceptor.kt rename to app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddWebCookieInterceptor.kt index 8d49c0cf..4ae41553 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddCookieInterceptor.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/AddWebCookieInterceptor.kt @@ -5,7 +5,7 @@ import com.huanchengfly.tieba.post.utils.AccountUtil import okhttp3.Interceptor import okhttp3.Response -object AddCookieInterceptor : Interceptor { +object AddWebCookieInterceptor : Interceptor { override fun intercept(chain: Interceptor.Chain): Response { val request = chain.request() var headers = request.headers @@ -13,11 +13,11 @@ object AddCookieInterceptor : Interceptor { val body = request.body var addCookie = true - val addCookieHeader = headers[Header.ADD_COOKIE] + val addCookieHeader = headers[Header.ADD_WEB_COOKIE] if (addCookieHeader != null) { - if (addCookieHeader == Header.ADD_COOKIE_FALSE) addCookie = false + if (addCookieHeader == Header.ADD_WEB_COOKIE_FALSE) addCookie = false headers = headers.newBuilder() - .removeAll(Header.ADD_COOKIE) + .removeAll(Header.ADD_WEB_COOKIE) .build() } diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/CookieInterceptor.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/CookieInterceptor.kt new file mode 100644 index 00000000..54ac5682 --- /dev/null +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interceptors/CookieInterceptor.kt @@ -0,0 +1,33 @@ +package com.huanchengfly.tieba.post.api.retrofit.interceptors + +import com.huanchengfly.tieba.post.App +import com.huanchengfly.tieba.post.utils.ClientUtils +import kotlinx.coroutines.MainScope +import kotlinx.coroutines.launch +import okhttp3.Interceptor +import okhttp3.Response + +object CookieInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + val response = chain.proceed(chain.request()) + + val cookies = response.headers("Set-Cookie") + if (cookies.isNotEmpty()) { + cookies.forEach { + val cookieName = it.substringBefore("=") + val cookieValue = it.substringAfter("=").substringBefore(";") + if (cookieName.equals( + "BAIDUID", + ignoreCase = true + ) && ClientUtils.baiduId.isNullOrEmpty() + ) { + MainScope().launch { + ClientUtils.saveBaiduId(App.INSTANCE, cookieValue) + } + } + } + } + + return response + } +} \ No newline at end of file diff --git a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/WebTiebaApi.kt b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/WebTiebaApi.kt index 4f8e2066..c9162f89 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/WebTiebaApi.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/api/retrofit/interfaces/WebTiebaApi.kt @@ -117,7 +117,7 @@ interface WebTiebaApi { ): Deferred> @Headers( - "${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}" + "${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}" ) @GET("/mo/q/newmoindex?need_user=1") fun myInfo( @@ -125,7 +125,7 @@ interface WebTiebaApi { ): Call @Headers( - "${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}" + "${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}" ) @GET("/mo/q/newmoindex?need_user=1") fun myInfoAsync( @@ -133,7 +133,7 @@ interface WebTiebaApi { ): Deferred> @Headers( - "${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}" + "${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}" ) @GET("/mo/q/newmoindex?need_user=1") fun myInfoFlow( diff --git a/app/src/main/java/com/huanchengfly/tieba/post/utils/ClientUtils.kt b/app/src/main/java/com/huanchengfly/tieba/post/utils/ClientUtils.kt index c27b0170..810da07e 100644 --- a/app/src/main/java/com/huanchengfly/tieba/post/utils/ClientUtils.kt +++ b/app/src/main/java/com/huanchengfly/tieba/post/utils/ClientUtils.kt @@ -14,14 +14,17 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext object ClientUtils { - const val CLIENT_ID = "client_id" - const val SAMPLE_ID = "sample_id" + private const val CLIENT_ID = "client_id" + private const val SAMPLE_ID = "sample_id" + private const val BAIDU_ID = "baidu_id" private val clientIdKey = stringPreferencesKey(CLIENT_ID) private val sampleIdKey = stringPreferencesKey(SAMPLE_ID) + private val baiduIdKey = stringPreferencesKey(BAIDU_ID) var clientId: String? = null var sampleId: String? = null + var baiduId: String? = null fun init(context: Context) { CoroutineScope(Dispatchers.IO).launch { @@ -31,10 +34,20 @@ object ClientUtils { sampleId = withContext(Dispatchers.IO) { context.dataStore.data.map { it[sampleIdKey] }.firstOrNull() } + baiduId = withContext(Dispatchers.IO) { + context.dataStore.data.map { it[baiduIdKey] }.firstOrNull() + } sync(context) } } + suspend fun saveBaiduId(context: Context, id: String) { + baiduId = id + context.dataStore.edit { + it[baiduIdKey] = id + } + } + private suspend fun save(context: Context, clientId: String, sampleId: String) { context.dataStore.edit { it[clientIdKey] = clientId