getFullAcctOrNull はホスト-ドメインのペアを複数受け取る

This commit is contained in:
tateisu 2020-09-23 10:32:18 +09:00
parent f5e3608883
commit ed55c4c212
6 changed files with 62 additions and 64 deletions

View File

@ -2451,7 +2451,6 @@ class ActMain : AsyncActivity(), Column.Callback, View.OnClickListener,
val mention = opener.linkInfo?.mention
if(mention != null) {
val fullAcct = getFullAcctOrNull(mention.acct, mention.url, accessInfo)
.validFull()
if(fullAcct != null) {
if(fullAcct.host != null) {
when(fullAcct.host.ascii) {

View File

@ -80,7 +80,7 @@ class Acct private constructor(
@Suppress("unused")
private fun valid() : Acct? = if(isValid) this else null
private val isValidFull : Boolean
val isValidFull : Boolean
get() = username.isNotEmpty() && username != "?" && (host?.isValid == true)
fun validFull() : Acct? = if(isValidFull) this else null

View File

@ -172,6 +172,7 @@ class TootStatus(parser : TootParser, src : JsonObject) : TimelineItem() {
// quote toot かどうか。
var isQuoteToot = false
private var quote_id : EntityId? = null
// このstatusがquoteだった場合、ミュート済みかどうか示すフラグ
var quote_muted = false
@ -348,11 +349,9 @@ class TootStatus(parser : TootParser, src : JsonObject) : TimelineItem() {
(decoded_spoiler_text as? MisskeyMarkdownDecoder.SpannableStringBuilderEx)?.mentions
this.mentions = mergeMentions(mentions1, mentions2)
this.decoded_mentions = HTMLDecoder.decodeMentions(
parser.linkHelper,
this.mentions,
this
) ?: EMPTY_SPANNABLE
this.decoded_mentions =
HTMLDecoder.decodeMentions(parser.linkHelper, this)
?: EMPTY_SPANNABLE
// contentを読んだ後にアンケートのデコード
this.enquete = TootPolls.parse(
@ -515,18 +514,15 @@ class TootStatus(parser : TootParser, src : JsonObject) : TimelineItem() {
this.in_reply_to_account_id =
EntityId.mayNull(src.string("in_reply_to_account_id"))
this.mentions = parseListOrNull(::TootMention, src.jsonArray("mentions"), log)
this.tags = TootTag.parseListOrNull(parser,src.jsonArray("tags"))
this.tags = TootTag.parseListOrNull(parser, src.jsonArray("tags"))
this.application =
parseItem(::TootApplication, parser, src.jsonObject("application"), log)
this.pinned = parser.pinned || src.optBoolean("pinned")
this.muted = src.optBoolean("muted")
this.language = src.string("language")?.notEmpty()
this.decoded_mentions = HTMLDecoder.decodeMentions(
parser.linkHelper,
this.mentions,
this
) ?: EMPTY_SPANNABLE
// this.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
this.decoded_mentions =
HTMLDecoder.decodeMentions(parser.linkHelper, this)
?: EMPTY_SPANNABLE
val quote = when {
! parser.decodeQuote -> null

View File

@ -497,10 +497,13 @@ object HTMLDecoder {
fun decodeMentions(
linkHelper : LinkHelper,
mentionList : List<TootMention>?,
link_tag : Any?
status:TootStatus
) : Spannable? {
val mentionList : List<TootMention>? = status.mentions
val link_tag : Any? = status
if(mentionList == null || mentionList.isEmpty()) return null
val sb = SpannableStringBuilder()
for(item in mentionList) {
if(sb.isNotEmpty()) sb.append(" ")
@ -508,8 +511,9 @@ object HTMLDecoder {
val fullAcct = getFullAcctOrNull(
item.acct,
item.url,
linkHelper, // メンション情報がある場合、ドメインが省略されたら閲覧者のドメインを補う。投稿者のドメインではない
).validFull()
linkHelper,
status.account
)
val linkInfo = if(fullAcct != null) {
LinkInfo(
@ -602,21 +606,24 @@ object HTMLDecoder {
// @mention
'@' -> {
fun afterFullAcctResolved(fullAcct:Acct){
linkInfo.ac = AcctColor.load(fullAcct)
if(options.mentionFullAcct || Pref.bpMentionFullAcct(App1.pref)) {
linkInfo.caption = "@${fullAcct.pretty}"
}
}
// https://github.com/tateisu/SubwayTooter/issues/108
// check mentions to skip getAcctFromUrl
val mention = options.mentions?.find { it.url == href }
if( mention != null ){
// メンション情報がある場合、ドメイン省略時のデフォルトは閲覧者のドメイン
getFullAcctOrNull(
mention.acct,
href,
defaultHostDomain = options.linkHelper ?: unknownHostAndDomain
).validFull()?.let{fullAcct ->
linkInfo.ac = AcctColor.load(fullAcct)
if(options.mentionFullAcct || Pref.bpMentionFullAcct(App1.pref)) {
linkInfo.caption = "@${fullAcct.pretty}"
}
}
options.linkHelper,
options.mentionDefaultHostDomain
)?.let{afterFullAcctResolved(it)}
}else{
// case A
@ -628,28 +635,28 @@ object HTMLDecoder {
// リモートのMisskeyからMastodonに流れてきた投稿をSTで見ると
// (元タンスでの)ローカルメンションに対して間違って閲覧者のドメインが補われる
// STのバグかと思ったけど、データみたらmentionsメタデータに一つ目のメンションのURLが含まれてない。
// どっちかのサーバにも問題があるらしい。
// 閲覧者ではなく投稿者のドメインを補うべき
// 閲覧サーバがメンションに含まれるアカウントを解決できなかった際に発生するらしい。
// 上記の理由から
// メンション情報がない場合は閲覧者ではなく投稿者のドメインを補うべき
// メンション情報がない場合がありうる。
// acctのドメイン部分を補う際、閲覧者のドメインや投稿者のドメインへの変換を試みる
val rawAcct = Acct.parse(originalCaption.toString().substring(1))
getFullAcctOrNull(
rawAcct,
href,
defaultHostDomain = options.mentionDefaultHostDomain
).validFull()?.let{ fullAcct ->
options.linkHelper,
options.mentionDefaultHostDomain
)?.let{ fullAcct ->
// mentionメタデータを捏造する
linkInfo.mention = TootMention(
id = EntityId.DEFAULT,
url = href,
acct = fullAcct,
username = rawAcct.username
)
linkInfo.ac = AcctColor.load(fullAcct)
if(options.mentionFullAcct || Pref.bpMentionFullAcct(App1.pref)) {
linkInfo.caption = "@${fullAcct.pretty}"
}
afterFullAcctResolved(fullAcct)
}
}
}

View File

@ -34,7 +34,8 @@ interface LinkHelper : HostAndDomain {
else -> src.followHost(apDomain.valid() ?: apiHost.valid() ?: Host.UNKNOWN)
}
companion object{
companion object {
val unknown = object : LinkHelper {
override val apiHost : Host = Host.UNKNOWN
override val apDomain : Host = Host.UNKNOWN
@ -55,9 +56,6 @@ interface LinkHelper : HostAndDomain {
}
}
fun LinkHelper.matchHost(src : String?) = apiHost.match(src) || apDomain.match(src)
fun LinkHelper.matchHost(src : Host?) = apiHost == src || apDomain == src
fun LinkHelper.matchHost(src : LinkHelper) =
@ -72,25 +70,22 @@ fun LinkHelper.matchHost(src : TootAccount) =
fun getFullAcctOrNull(
rawAcct : Acct,
url : String,
// 以下の2つは閲覧者や投稿者のホストとドメインを指定する。
// 閲覧者と投稿者のどちらを使うべきかは状況により異なる。
defaultHostDomain : HostAndDomain,
) : Acct {
// 記載がfull acctならそれを使う
if(rawAcct.host != null) return rawAcct
// URLのホスト名部分を見つける
val urlHost =
TootAccount.reHostInUrl.matcher(url).findOrNull()?.groupEx(1)?.let { Host.parse(it) }
// URLのホストが見つかって、mentionDefaultApiHostではないならそれを使う。
// さもなくば mentionDefaultApDomain を補う。
return rawAcct.followHost(
when(urlHost) {
defaultHostDomain.apiHost, null -> defaultHostDomain.apDomain
else -> urlHost
}
)
}
hostDomain1 : HostAndDomain? = null,
hostDomain2 : HostAndDomain? = null
) =
if(rawAcct.isValidFull) {
// 記載がfull acctならそれを使う
rawAcct
} else {
// URL中のホスト名を使うが、引数でホストとドメインの対応が提供されていればドメインへの変換を試みる
rawAcct.followHost(
when(val host = TootAccount.reHostInUrl.matcher(url)
.findOrNull()?.groupEx(1)?.let { Host.parse(it) }
?: Host.UNKNOWN
) {
hostDomain1?.apiHost -> hostDomain1.apDomain
hostDomain2?.apiHost -> hostDomain2.apDomain
else -> host
}
).validFull()
}

View File

@ -806,8 +806,9 @@ object MisskeyMarkdownDecoder {
getFullAcctOrNull(
rawAcct = Acct.parse(text.substring(1)),
url = url,
defaultHostDomain = options.mentionDefaultHostDomain
).validFull()
options.linkHelper,
options.mentionDefaultHostDomain,
)
}
val linkInfo = LinkInfo(