mirror of
https://github.com/tateisu/SubwayTooter
synced 2025-02-04 04:37:40 +01:00
more fix for whitelist mode
This commit is contained in:
parent
955b6e4850
commit
963d9003c1
@ -1954,8 +1954,8 @@ class ActMain : AsyncActivity(), View.OnClickListener,
|
||||
)?.also {
|
||||
this.ta = parser.account(it.jsonObject)
|
||||
if( ta != null){
|
||||
val (ti, r2) = TootInstance.get(client, forceAccessToken = refToken.get())
|
||||
this.ti = ti ?: return r2
|
||||
val (ti, ri) = TootInstance.getEx(client, forceAccessToken = refToken.get())
|
||||
this.ti = ti ?: return ri
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2124,15 +2124,10 @@ class ActMain : AsyncActivity(), View.OnClickListener,
|
||||
|
||||
override suspend fun background(client: TootApiClient): TootApiResult? {
|
||||
|
||||
val (instance, instanceResult) = TootInstance.get(
|
||||
client,
|
||||
apiHost,
|
||||
forceAccessToken = access_token
|
||||
)
|
||||
instance ?: return instanceResult
|
||||
this.ti = instance
|
||||
val (ti,ri) = TootInstance.getEx(client,forceAccessToken = access_token)
|
||||
this.ti = ti ?: return ri
|
||||
|
||||
val misskeyVersion = instance.misskeyVersion
|
||||
val misskeyVersion = ti.misskeyVersion
|
||||
|
||||
val result = client.getUserCredential(access_token, misskeyVersion = misskeyVersion)
|
||||
|
||||
@ -2140,7 +2135,7 @@ class ActMain : AsyncActivity(), View.OnClickListener,
|
||||
this@ActMain,
|
||||
LinkHelper.create(
|
||||
apiHost,
|
||||
apDomainArg = instance.uri?.let { Host.parse(it) },
|
||||
apDomainArg = ti.uri?.let { Host.parse(it) },
|
||||
misskeyVersion = misskeyVersion
|
||||
)
|
||||
).account(result?.jsonObject)
|
||||
|
@ -1215,31 +1215,17 @@ enum class ColumnType(
|
||||
headerType = HeaderType.Instance,
|
||||
|
||||
loading = { client ->
|
||||
val (instance, instanceResult) = TootInstance.get(
|
||||
val (ti,ri) = TootInstance.getEx(
|
||||
client,
|
||||
Host.parse(column.instance_uri),
|
||||
allowPixelfed = true,
|
||||
forceUpdate = true
|
||||
)
|
||||
if (instance != null) {
|
||||
column.instance_information = instance
|
||||
column.handshake = instanceResult?.response?.handshake
|
||||
if (ti != null) {
|
||||
column.instance_information = ti
|
||||
column.handshake = ri?.response?.handshake
|
||||
}
|
||||
instanceResult
|
||||
//
|
||||
// // 「インスタンス情報」カラムをNAアカウントで開く場合
|
||||
// instance_name != null -> client.instance = instance_name
|
||||
//
|
||||
// val (result, ti) = client.parseInstanceInformation(client.getInstanceInformation())
|
||||
// instance_tmp = ti
|
||||
// return result
|
||||
// }
|
||||
//
|
||||
// val result = getInstanceInformation(client, column.instance_uri)
|
||||
// if(instance_tmp != null) {
|
||||
//
|
||||
// }
|
||||
// result
|
||||
ri
|
||||
}
|
||||
),
|
||||
|
||||
|
@ -25,7 +25,7 @@ object Action_Instance {
|
||||
instance == null -> TootTaskRunner(activity).run(host, object : TootTask {
|
||||
var targetInstance : TootInstance? = null
|
||||
override suspend fun background(client : TootApiClient) : TootApiResult? {
|
||||
val (ti, ri) = TootInstance.get(client, host, allowPixelfed = true)
|
||||
val (ti, ri) = TootInstance.getEx(client, host, allowPixelfed = true)
|
||||
targetInstance = ti
|
||||
return ri
|
||||
}
|
||||
|
@ -120,7 +120,7 @@ class TootApiClient(
|
||||
|
||||
fun getScopeString(ti: TootInstance?) = when {
|
||||
// 古いサーバ
|
||||
ti?.versionGE(TootInstance.VERSION_2_4_0_rc1) == false ->"read+write+follow"
|
||||
ti?.versionGE(TootInstance.VERSION_2_4_0_rc1) == false -> "read+write+follow"
|
||||
// 新しいサーバか、AUTHORIZED_FETCH(3.0.0以降)によりサーバ情報を取得できなかった
|
||||
else -> "read+write+follow+push"
|
||||
|
||||
@ -551,8 +551,7 @@ class TootApiClient(
|
||||
suspend fun request(
|
||||
path: String,
|
||||
request_builder: Request.Builder = Request.Builder(),
|
||||
withoutToken: Boolean = false,
|
||||
forceAccessToken:String? =null,
|
||||
forceAccessToken: String? = null,
|
||||
): TootApiResult? {
|
||||
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
|
||||
if (result.error != null) return result
|
||||
@ -566,12 +565,8 @@ class TootApiClient(
|
||||
|
||||
request_builder.url(url)
|
||||
|
||||
if (!withoutToken) {
|
||||
val access_token = forceAccessToken ?: account?.getAccessToken()
|
||||
if (access_token?.isNotEmpty() == true) {
|
||||
request_builder.header("Authorization", "Bearer $access_token")
|
||||
}
|
||||
}
|
||||
(forceAccessToken ?: account?.getAccessToken())
|
||||
?.notEmpty()?.let { request_builder.header("Authorization", "Bearer $it") }
|
||||
|
||||
request_builder.build()
|
||||
.also { log.d("request: ${it.method} $url") }
|
||||
|
@ -9,14 +9,12 @@ import jp.juggler.subwaytooter.api.TootParser
|
||||
import jp.juggler.subwaytooter.table.SavedAccount
|
||||
import jp.juggler.subwaytooter.util.LinkHelper
|
||||
import jp.juggler.subwaytooter.util.VersionString
|
||||
import jp.juggler.subwaytooter.util.matchHost
|
||||
import jp.juggler.util.*
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.channels.Channel
|
||||
import kotlinx.coroutines.launch
|
||||
import okhttp3.Request
|
||||
import java.lang.NullPointerException
|
||||
import java.util.*
|
||||
import java.util.regex.Pattern
|
||||
import kotlin.collections.ArrayList
|
||||
@ -266,33 +264,43 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||
}
|
||||
|
||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||
private suspend fun TootApiClient.getInstanceInformationMastodon(): TootApiResult? {
|
||||
private suspend fun TootApiClient.getInstanceInformationMastodon(
|
||||
forceAccessToken: String? = null
|
||||
): TootApiResult? {
|
||||
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
|
||||
if (result.error != null) return result
|
||||
|
||||
if (sendRequest(result) {
|
||||
Request.Builder().url("https://${apiHost?.ascii}/api/v1/instance").build()
|
||||
val builder = Request.Builder().url("https://${apiHost?.ascii}/api/v1/instance")
|
||||
|
||||
(forceAccessToken ?: account?.getAccessToken() )
|
||||
?.notEmpty()?.let { builder.header("Authorization", "Bearer $it") }
|
||||
builder.build()
|
||||
}
|
||||
) {
|
||||
parseJson(result) ?: return null
|
||||
}
|
||||
|
||||
// misskeyの事は忘れて本来のエラー情報を返す
|
||||
return result
|
||||
}
|
||||
|
||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||
private suspend fun TootApiClient.getInstanceInformationMisskey(): TootApiResult? {
|
||||
private suspend fun TootApiClient.getInstanceInformationMisskey(
|
||||
forceAccessToken: String? = null
|
||||
): TootApiResult? {
|
||||
val result = TootApiResult.makeWithCaption(apiHost?.pretty)
|
||||
if (result.error != null) return result
|
||||
|
||||
if (sendRequest(result) {
|
||||
JsonObject().apply {
|
||||
jsonObject {
|
||||
put("dummy", 1)
|
||||
}
|
||||
.toPostRequestBuilder()
|
||||
(forceAccessToken ?: account?.misskeyApiToken )
|
||||
?.notEmpty()?.let { put("i", it) }
|
||||
}.toPostRequestBuilder()
|
||||
.url("https://${apiHost?.ascii}/api/meta")
|
||||
.build()
|
||||
}) {
|
||||
}
|
||||
) {
|
||||
parseJson(result) ?: return null
|
||||
|
||||
result.jsonObject?.apply {
|
||||
@ -306,136 +314,71 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||
}
|
||||
|
||||
// 疑似アカウントの追加時に、インスタンスの検証を行う
|
||||
private suspend fun TootApiClient.getInstanceInformation(): TootApiResult? {
|
||||
private suspend fun TootApiClient.getInstanceInformation(
|
||||
forceAccessToken: String? = null
|
||||
): TootApiResult? {
|
||||
|
||||
// misskeyのインスタンス情報を読めたら、それはmisskeyのインスタンス
|
||||
val r2 = getInstanceInformationMisskey() ?: return null
|
||||
val r2 = getInstanceInformationMisskey(forceAccessToken) ?: return null
|
||||
if (r2.jsonObject != null) return r2
|
||||
|
||||
// マストドンのインスタンス情報を読めたら、それはマストドンのインスタンス
|
||||
val r1 = getInstanceInformationMastodon() ?: return null
|
||||
val r1 = getInstanceInformationMastodon(forceAccessToken) ?: return null
|
||||
if (r1.jsonObject != null) return r1
|
||||
|
||||
return r1 // 通信エラーの表示ならr1でもr2でも構わないはず
|
||||
return r1 // ホワイトリストモードの問題があるのでマストドン側のエラーを返す
|
||||
}
|
||||
|
||||
class RequestInfo(
|
||||
val client: TootApiClient,
|
||||
val account: SavedAccount?,
|
||||
class QueuedRequest(
|
||||
val allowPixelfed: Boolean,
|
||||
val forceUpdate: Boolean,
|
||||
val forceAccessToken: String?,
|
||||
val get: suspend (cached: TootInstance?) -> Pair<TootInstance?, TootApiResult?>,
|
||||
) {
|
||||
val result = Channel<Pair<TootInstance?, TootApiResult?>>()
|
||||
}
|
||||
|
||||
fun queuedRequest(
|
||||
allowPixelfed: Boolean,
|
||||
get: suspend (cached: TootInstance?) -> Pair<TootInstance?, TootApiResult?>
|
||||
) = QueuedRequest(allowPixelfed, get)
|
||||
|
||||
// インスタンス情報のキャッシュ。同期オブジェクトを兼ねる
|
||||
class CacheEntry {
|
||||
// インスタンス情報のキャッシュ
|
||||
var cacheData: TootInstance? = null
|
||||
|
||||
private suspend fun getImpl(ri: RequestInfo): Pair<TootInstance?, TootApiResult?> {
|
||||
|
||||
var item: TootInstance?
|
||||
|
||||
if (!ri.forceUpdate && ri.forceAccessToken == null) {
|
||||
// re-use cached item.
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
item = cacheData
|
||||
if (item != null && now - item.time_parse <= EXPIRE) {
|
||||
if (item.instanceType == InstanceType.Pixelfed &&
|
||||
!Pref.bpEnablePixelfed(App1.pref) &&
|
||||
!ri.allowPixelfed
|
||||
) {
|
||||
return Pair(
|
||||
null,
|
||||
TootApiResult("currently Pixelfed instance is not supported.")
|
||||
)
|
||||
}
|
||||
return Pair(item, TootApiResult())
|
||||
}
|
||||
}
|
||||
|
||||
// get new information
|
||||
val result = when {
|
||||
// マストドンのホワイトリストモード用
|
||||
ri.forceAccessToken != null ->
|
||||
ri.client.request(
|
||||
"/api/v1/instance",
|
||||
forceAccessToken = ri.forceAccessToken
|
||||
)
|
||||
|
||||
ri.account == null ->
|
||||
ri.client.getInstanceInformation()
|
||||
|
||||
ri.account.isMisskey ->
|
||||
ri.client.request(
|
||||
"/api/meta",
|
||||
JsonObject().apply { put("dummy", 1) }.toPostRequestBuilder(),
|
||||
withoutToken = true
|
||||
)
|
||||
|
||||
else ->
|
||||
ri.client.request(
|
||||
"/api/v1/instance",
|
||||
withoutToken = true
|
||||
)
|
||||
}
|
||||
|
||||
val json = result?.jsonObject ?: return Pair(null, result)
|
||||
|
||||
item = parseItem(
|
||||
::TootInstance,
|
||||
TootParser(
|
||||
ri.client.context,
|
||||
linkHelper = ri.account ?: LinkHelper.create(
|
||||
ri.client.apiHost!!,
|
||||
misskeyVersion = parseMisskeyVersion(json)
|
||||
)
|
||||
),
|
||||
json
|
||||
)
|
||||
|
||||
return when {
|
||||
item == null -> Pair(
|
||||
null,
|
||||
result.setError("instance information parse error.")
|
||||
)
|
||||
|
||||
item.instanceType == InstanceType.Pixelfed &&
|
||||
!Pref.bpEnablePixelfed(App1.pref) &&
|
||||
!ri.allowPixelfed ->
|
||||
Pair(
|
||||
null,
|
||||
result.setError("currently Pixelfed instance is not supported.")
|
||||
)
|
||||
|
||||
else -> Pair(item.also { cacheData = it }, result)
|
||||
}
|
||||
}
|
||||
|
||||
// ホストごとに同時に1つしか実行しない、インスタンス情報更新キュー
|
||||
val requestQueue = Channel<RequestInfo>(capacity = Channel.UNLIMITED)
|
||||
val requestQueue = Channel<QueuedRequest>(capacity = Channel.UNLIMITED)
|
||||
|
||||
private suspend fun loop() {
|
||||
while (true) {
|
||||
requestQueue.receive().let { req ->
|
||||
req.result.send(
|
||||
try {
|
||||
getImpl(req)
|
||||
} catch (ex: Throwable) {
|
||||
Pair(
|
||||
null,
|
||||
TootApiResult(ex.withCaption("can't get server information."))
|
||||
)
|
||||
}
|
||||
private suspend fun handleRequest(req: QueuedRequest) = try {
|
||||
val pair = req.get(cacheData)
|
||||
|
||||
pair.first?.let { cacheData = it }
|
||||
|
||||
when {
|
||||
|
||||
pair.first?.instanceType == InstanceType.Pixelfed &&
|
||||
!Pref.bpEnablePixelfed(App1.pref) &&
|
||||
!req.allowPixelfed ->
|
||||
Pair(
|
||||
null, TootApiResult("currently Pixelfed instance is not supported.")
|
||||
)
|
||||
}
|
||||
|
||||
else -> pair
|
||||
}
|
||||
|
||||
} catch (ex: Throwable) {
|
||||
Pair(
|
||||
null,
|
||||
TootApiResult(ex.withCaption("can't get server information."))
|
||||
)
|
||||
}
|
||||
|
||||
init {
|
||||
GlobalScope.launch(Dispatchers.IO) { loop() }
|
||||
GlobalScope.launch(Dispatchers.IO) {
|
||||
while (true) {
|
||||
requestQueue.receive().let { it.result.send(handleRequest(it)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -456,50 +399,95 @@ class TootInstance(parser: TootParser, src: JsonObject) {
|
||||
// no request, no expiration check
|
||||
fun getCached(host: String) = Host.parse(host).getCacheEntry().cacheData
|
||||
|
||||
suspend fun get(
|
||||
client: TootApiClient,
|
||||
host: String,
|
||||
account: SavedAccount? = client.account?.takeIf { it.matchHost(host) },
|
||||
allowPixelfed: Boolean = false,
|
||||
forceUpdate: Boolean = false
|
||||
): Pair<TootInstance?, TootApiResult?> =
|
||||
get(client, Host.parse(host), account, allowPixelfed, forceUpdate)
|
||||
suspend fun get(client: TootApiClient): Pair<TootInstance?, TootApiResult?> = getEx(client)
|
||||
|
||||
suspend fun get(
|
||||
suspend fun getEx(
|
||||
client: TootApiClient,
|
||||
hostArg: Host? = null,
|
||||
account: SavedAccount? = if (hostArg == client.apiHost) client.account else null,
|
||||
account: SavedAccount? = null,
|
||||
allowPixelfed: Boolean = false,
|
||||
forceUpdate: Boolean = false,
|
||||
forceAccessToken: String? = null, // マストドンのwhitelist modeでアカウント追加時に必要
|
||||
): Pair<TootInstance?, TootApiResult?> {
|
||||
|
||||
val tmpInstance = client.apiHost
|
||||
val tmpAccount = client.account
|
||||
try {
|
||||
// this may write client.apiHost
|
||||
if (account != null) client.account = account
|
||||
// update client.apiHost
|
||||
if (hostArg != null) client.apiHost = hostArg
|
||||
val cacheEntry = (hostArg ?: account?.apiHost ?: client.apiHost)?.getCacheEntry()
|
||||
?: return Pair(null, TootApiResult("missing host."))
|
||||
|
||||
val host = client.apiHost
|
||||
?: throw NullPointerException("missing host to get server information.")
|
||||
// ホスト名ごとに用意したオブジェクトで同期する
|
||||
return queuedRequest(allowPixelfed) { cached ->
|
||||
|
||||
// ホスト名ごとに用意したオブジェクトで同期する
|
||||
return RequestInfo(
|
||||
client = client,
|
||||
account = account,
|
||||
allowPixelfed = allowPixelfed,
|
||||
forceUpdate = forceUpdate,
|
||||
forceAccessToken = forceAccessToken
|
||||
// may use cached item.
|
||||
if (!forceUpdate && forceAccessToken == null && cached!=null) {
|
||||
val now = SystemClock.elapsedRealtime()
|
||||
if ( now - cached.time_parse <= EXPIRE)
|
||||
return@queuedRequest Pair(cached, TootApiResult())
|
||||
}
|
||||
|
||||
val tmpInstance = client.apiHost
|
||||
val tmpAccount = client.account
|
||||
|
||||
val linkHelper: LinkHelper?
|
||||
|
||||
// get new information
|
||||
val result = when {
|
||||
|
||||
// ストリームマネジャから呼ばれる
|
||||
account != null -> try {
|
||||
linkHelper = account
|
||||
client.account = account // this may change client.apiHost
|
||||
if (account.isMisskey) {
|
||||
client.getInstanceInformationMisskey()
|
||||
} else {
|
||||
client.getInstanceInformationMastodon()
|
||||
}
|
||||
} finally {
|
||||
client.account = tmpAccount
|
||||
client.apiHost = tmpInstance // must be last.
|
||||
}
|
||||
|
||||
// サーバ情報カラムやProfileDirectoryを開く場合
|
||||
hostArg != null && hostArg != tmpInstance -> try {
|
||||
linkHelper = null
|
||||
client.account = null // don't use access token.
|
||||
client.apiHost = hostArg
|
||||
client.getInstanceInformation()
|
||||
} finally {
|
||||
client.account = tmpAccount
|
||||
client.apiHost = tmpInstance // must be last.
|
||||
}
|
||||
|
||||
// client にすでにあるアクセス情報でサーバ情報を取得する
|
||||
// マストドンのホワイトリストモード用にアクセストークンを指定できる
|
||||
else -> {
|
||||
linkHelper = client.account // may null
|
||||
client.getInstanceInformation(
|
||||
forceAccessToken = forceAccessToken
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val json = result?.jsonObject
|
||||
?: return@queuedRequest Pair(null, result)
|
||||
|
||||
val item = parseItem(
|
||||
::TootInstance,
|
||||
TootParser(
|
||||
client.context,
|
||||
linkHelper = linkHelper ?: LinkHelper.create(
|
||||
hostArg!!,
|
||||
misskeyVersion = parseMisskeyVersion(json)
|
||||
)
|
||||
),
|
||||
json
|
||||
) ?: return@queuedRequest Pair(
|
||||
null,
|
||||
result.setError("instance information parse error.")
|
||||
)
|
||||
.also { host.getCacheEntry().requestQueue.send(it) }
|
||||
.result.receive()
|
||||
|
||||
} finally {
|
||||
client.account = tmpAccount
|
||||
client.apiHost = tmpInstance // must be last.
|
||||
Pair(item, result)
|
||||
}
|
||||
.also { cacheEntry.requestQueue.send(it) }
|
||||
.result.receive()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ class StreamManager(val appState: AppState) {
|
||||
if (errorAcct.contains(acct)) return null
|
||||
var acctGroup = newMap[acct]
|
||||
if (acctGroup == null) {
|
||||
var (ti, ri) = TootInstance.get(client, account = accessInfo)
|
||||
var (ti, ri) = TootInstance.getEx(client, account = accessInfo)
|
||||
if (ti == null) {
|
||||
log.d("can't get server info. ${ri?.error}")
|
||||
val tiOld = acctGroups[acct]?.ti
|
||||
|
Loading…
x
Reference in New Issue
Block a user