feat: 保存 baiduid
This commit is contained in:
parent
9a59e2bac4
commit
aea5ca4988
|
|
@ -1,6 +1,5 @@
|
||||||
package com.huanchengfly.tieba.post.activities
|
package com.huanchengfly.tieba.post.activities
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Handler
|
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.fragments.WebViewFragment
|
||||||
import com.huanchengfly.tieba.post.interfaces.WebViewListener
|
import com.huanchengfly.tieba.post.interfaces.WebViewListener
|
||||||
import com.huanchengfly.tieba.post.utils.AccountUtil
|
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.ThemeUtil
|
||||||
import com.huanchengfly.tieba.post.utils.Util
|
import com.huanchengfly.tieba.post.utils.Util
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|
@ -21,6 +21,8 @@ import kotlinx.coroutines.flow.flowOn
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
class LoginActivity : BaseActivity(), WebViewListener {
|
class LoginActivity : BaseActivity(), WebViewListener {
|
||||||
|
private var isLoadingAccount = false
|
||||||
|
|
||||||
private var toolbar: Toolbar? = null
|
private var toolbar: Toolbar? = null
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
@ -48,49 +50,66 @@ class LoginActivity : BaseActivity(), WebViewListener {
|
||||||
toolbar!!.title = newTitle
|
toolbar!!.title = newTitle
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 从 Cookies 字符串解析出每个 Cookie
|
||||||
|
fun parseCookies(cookies: String): Map<String, String> {
|
||||||
|
val cookieMap = mutableMapOf<String, String>()
|
||||||
|
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) {
|
override fun onPageFinished(view: WebView, url: String) {
|
||||||
|
if (isLoadingAccount) {
|
||||||
|
return
|
||||||
|
}
|
||||||
val cookieManager = CookieManager.getInstance()
|
val cookieManager = CookieManager.getInstance()
|
||||||
val cookies = cookieManager.getCookie(url)
|
val cookiesStr = cookieManager.getCookie(url) ?: ""
|
||||||
if (cookies != null) {
|
val cookies = parseCookies(cookiesStr)
|
||||||
val bdussSplit = cookies.split("BDUSS=")
|
val bduss = cookies["BDUSS"]
|
||||||
val sTokenSplit = cookies.split("STOKEN=")
|
val sToken = cookies["STOKEN"]
|
||||||
if (bdussSplit.size > 1 && sTokenSplit.size > 1) {
|
val baiduId = cookies["BAIDUID"]
|
||||||
val bduss = bdussSplit[1].split(";")[0]
|
if (url.startsWith("https://tieba.baidu.com/index/tbwise/") || url.startsWith("https://tiebac.baidu.com/index/tbwise/")) {
|
||||||
val sToken = sTokenSplit[1].split(";")[0]
|
if (bduss == null || sToken == null) {
|
||||||
if (url.startsWith("https://tieba.baidu.com/index/tbwise/") || url.startsWith("https://tiebac.baidu.com/index/tbwise/")) {
|
return
|
||||||
val snackBar = Util.createSnackbar(view, "请稍后…", Snackbar.LENGTH_INDEFINITE)
|
}
|
||||||
snackBar.show()
|
if (!baiduId.isNullOrEmpty() && ClientUtils.baiduId.isNullOrEmpty()) launch {
|
||||||
launch {
|
ClientUtils.saveBaiduId(
|
||||||
AccountUtil.fetchAccountFlow(bduss, sToken, cookies)
|
this@LoginActivity,
|
||||||
.flowOn(Dispatchers.IO)
|
baiduId
|
||||||
.catch { e ->
|
)
|
||||||
snackBar.setText("登录失败 ${e.getErrorMessage()}")
|
}
|
||||||
|
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")
|
view.loadUrl("https://wappass.baidu.com/passport?login&u=https%3A%2F%2Ftieba.baidu.com%2Findex%2Ftbwise%2Fmine")
|
||||||
handler.postDelayed({ snackBar.dismiss() }, 1500)
|
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("登录失败 未知错误")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ object Header {
|
||||||
const val DROP_HEADERS = "drop_headers"
|
const val DROP_HEADERS = "drop_headers"
|
||||||
const val NO_COMMON_PARAMS = "no_common_params"
|
const val NO_COMMON_PARAMS = "no_common_params"
|
||||||
|
|
||||||
const val ADD_COOKIE = "add_cookie"
|
const val ADD_WEB_COOKIE = "add_cookie"
|
||||||
const val ADD_COOKIE_FALSE = "false"
|
const val ADD_WEB_COOKIE_FALSE = "false"
|
||||||
|
|
||||||
const val ACCEPT_LANGUAGE = "Accept-Language"
|
const val ACCEPT_LANGUAGE = "Accept-Language"
|
||||||
const val ACCEPT_LANGUAGE_VALUE = "zh-CN,zh;q=0.9"
|
const val ACCEPT_LANGUAGE_VALUE = "zh-CN,zh;q=0.9"
|
||||||
|
|
|
||||||
|
|
@ -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.DeferredCallAdapterFactory
|
||||||
import com.huanchengfly.tieba.post.api.retrofit.adapter.FlowCallAdapterFactory
|
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.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.CommonHeaderInterceptor
|
||||||
import com.huanchengfly.tieba.post.api.retrofit.interceptors.CommonParamInterceptor
|
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.DropInterceptor
|
||||||
import com.huanchengfly.tieba.post.api.retrofit.interceptors.FailureResponseInterceptor
|
import com.huanchengfly.tieba.post.api.retrofit.interceptors.FailureResponseInterceptor
|
||||||
import com.huanchengfly.tieba.post.api.retrofit.interceptors.ForceLoginInterceptor
|
import com.huanchengfly.tieba.post.api.retrofit.interceptors.ForceLoginInterceptor
|
||||||
|
|
@ -98,7 +99,8 @@ object RetrofitTiebaApi {
|
||||||
Header.CHARSET to { "UTF-8" },
|
Header.CHARSET to { "UTF-8" },
|
||||||
Header.HOST to { "tieba.baidu.com" },
|
Header.HOST to { "tieba.baidu.com" },
|
||||||
),
|
),
|
||||||
AddCookieInterceptor)
|
AddWebCookieInterceptor
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val MINI_TIEBA_API: MiniTiebaApi by lazy {
|
val MINI_TIEBA_API: MiniTiebaApi by lazy {
|
||||||
|
|
@ -247,6 +249,7 @@ object RetrofitTiebaApi {
|
||||||
addInterceptor(DropInterceptor)
|
addInterceptor(DropInterceptor)
|
||||||
addInterceptor(ProtoFailureResponseInterceptor)
|
addInterceptor(ProtoFailureResponseInterceptor)
|
||||||
addInterceptor(ForceLoginInterceptor)
|
addInterceptor(ForceLoginInterceptor)
|
||||||
|
addInterceptor(CookieInterceptor)
|
||||||
addInterceptor(sortAndSignInterceptor)
|
addInterceptor(sortAndSignInterceptor)
|
||||||
connectionPool(connectionPool)
|
connectionPool(connectionPool)
|
||||||
}.build())
|
}.build())
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ import com.huanchengfly.tieba.post.utils.AccountUtil
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
|
|
||||||
object AddCookieInterceptor : Interceptor {
|
object AddWebCookieInterceptor : Interceptor {
|
||||||
override fun intercept(chain: Interceptor.Chain): Response {
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
val request = chain.request()
|
val request = chain.request()
|
||||||
var headers = request.headers
|
var headers = request.headers
|
||||||
|
|
@ -13,11 +13,11 @@ object AddCookieInterceptor : Interceptor {
|
||||||
val body = request.body
|
val body = request.body
|
||||||
|
|
||||||
var addCookie = true
|
var addCookie = true
|
||||||
val addCookieHeader = headers[Header.ADD_COOKIE]
|
val addCookieHeader = headers[Header.ADD_WEB_COOKIE]
|
||||||
if (addCookieHeader != null) {
|
if (addCookieHeader != null) {
|
||||||
if (addCookieHeader == Header.ADD_COOKIE_FALSE) addCookie = false
|
if (addCookieHeader == Header.ADD_WEB_COOKIE_FALSE) addCookie = false
|
||||||
headers = headers.newBuilder()
|
headers = headers.newBuilder()
|
||||||
.removeAll(Header.ADD_COOKIE)
|
.removeAll(Header.ADD_WEB_COOKIE)
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -117,7 +117,7 @@ interface WebTiebaApi {
|
||||||
): Deferred<ApiResult<ForumBean>>
|
): Deferred<ApiResult<ForumBean>>
|
||||||
|
|
||||||
@Headers(
|
@Headers(
|
||||||
"${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}"
|
"${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}"
|
||||||
)
|
)
|
||||||
@GET("/mo/q/newmoindex?need_user=1")
|
@GET("/mo/q/newmoindex?need_user=1")
|
||||||
fun myInfo(
|
fun myInfo(
|
||||||
|
|
@ -125,7 +125,7 @@ interface WebTiebaApi {
|
||||||
): Call<MyInfoBean>
|
): Call<MyInfoBean>
|
||||||
|
|
||||||
@Headers(
|
@Headers(
|
||||||
"${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}"
|
"${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}"
|
||||||
)
|
)
|
||||||
@GET("/mo/q/newmoindex?need_user=1")
|
@GET("/mo/q/newmoindex?need_user=1")
|
||||||
fun myInfoAsync(
|
fun myInfoAsync(
|
||||||
|
|
@ -133,7 +133,7 @@ interface WebTiebaApi {
|
||||||
): Deferred<ApiResult<MyInfoBean>>
|
): Deferred<ApiResult<MyInfoBean>>
|
||||||
|
|
||||||
@Headers(
|
@Headers(
|
||||||
"${Header.ADD_COOKIE}: ${Header.ADD_COOKIE_FALSE}"
|
"${Header.ADD_WEB_COOKIE}: ${Header.ADD_WEB_COOKIE_FALSE}"
|
||||||
)
|
)
|
||||||
@GET("/mo/q/newmoindex?need_user=1")
|
@GET("/mo/q/newmoindex?need_user=1")
|
||||||
fun myInfoFlow(
|
fun myInfoFlow(
|
||||||
|
|
|
||||||
|
|
@ -14,14 +14,17 @@ import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
|
|
||||||
object ClientUtils {
|
object ClientUtils {
|
||||||
const val CLIENT_ID = "client_id"
|
private const val CLIENT_ID = "client_id"
|
||||||
const val SAMPLE_ID = "sample_id"
|
private const val SAMPLE_ID = "sample_id"
|
||||||
|
private const val BAIDU_ID = "baidu_id"
|
||||||
|
|
||||||
private val clientIdKey = stringPreferencesKey(CLIENT_ID)
|
private val clientIdKey = stringPreferencesKey(CLIENT_ID)
|
||||||
private val sampleIdKey = stringPreferencesKey(SAMPLE_ID)
|
private val sampleIdKey = stringPreferencesKey(SAMPLE_ID)
|
||||||
|
private val baiduIdKey = stringPreferencesKey(BAIDU_ID)
|
||||||
|
|
||||||
var clientId: String? = null
|
var clientId: String? = null
|
||||||
var sampleId: String? = null
|
var sampleId: String? = null
|
||||||
|
var baiduId: String? = null
|
||||||
|
|
||||||
fun init(context: Context) {
|
fun init(context: Context) {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
|
@ -31,10 +34,20 @@ object ClientUtils {
|
||||||
sampleId = withContext(Dispatchers.IO) {
|
sampleId = withContext(Dispatchers.IO) {
|
||||||
context.dataStore.data.map { it[sampleIdKey] }.firstOrNull()
|
context.dataStore.data.map { it[sampleIdKey] }.firstOrNull()
|
||||||
}
|
}
|
||||||
|
baiduId = withContext(Dispatchers.IO) {
|
||||||
|
context.dataStore.data.map { it[baiduIdKey] }.firstOrNull()
|
||||||
|
}
|
||||||
sync(context)
|
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) {
|
private suspend fun save(context: Context, clientId: String, sampleId: String) {
|
||||||
context.dataStore.edit {
|
context.dataStore.edit {
|
||||||
it[clientIdKey] = clientId
|
it[clientIdKey] = clientId
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue