2021-06-28 09:09:00 +02:00
|
|
|
package jp.juggler.subwaytooter.column
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
import jp.juggler.subwaytooter.api.TootApiClient
|
|
|
|
import jp.juggler.subwaytooter.api.TootParser
|
|
|
|
import jp.juggler.subwaytooter.api.entity.*
|
|
|
|
import jp.juggler.subwaytooter.table.AcctSet
|
|
|
|
import jp.juggler.subwaytooter.table.TagSet
|
|
|
|
import jp.juggler.subwaytooter.table.UserRelation
|
2021-06-28 09:35:09 +02:00
|
|
|
import jp.juggler.util.LogCategory
|
2021-05-17 16:13:04 +02:00
|
|
|
import jp.juggler.util.toJsonArray
|
|
|
|
import jp.juggler.util.toPostRequestBuilder
|
|
|
|
import java.util.HashSet
|
|
|
|
|
2021-06-28 09:35:09 +02:00
|
|
|
class UserRelationLoader(val column: Column) {
|
|
|
|
companion object {
|
|
|
|
private val log = LogCategory("UserRelationLoader")
|
|
|
|
}
|
2021-05-17 16:13:04 +02:00
|
|
|
|
2021-06-20 15:12:25 +02:00
|
|
|
val whoSet = HashSet<EntityId>()
|
|
|
|
val acctSet = HashSet<String>()
|
2021-10-27 22:58:19 +02:00
|
|
|
private val tagSet = HashSet<String>()
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
fun add(whoRef: TootAccountRef?) {
|
|
|
|
add(whoRef?.get())
|
|
|
|
}
|
|
|
|
|
|
|
|
fun add(who: TootAccount?) {
|
|
|
|
who ?: return
|
2021-06-20 15:12:25 +02:00
|
|
|
whoSet.add(who.id)
|
|
|
|
val fullAcct = column.accessInfo.getFullAcct(who)
|
|
|
|
acctSet.add("@${fullAcct.ascii}")
|
|
|
|
acctSet.add("@${fullAcct.pretty}")
|
2021-05-17 16:13:04 +02:00
|
|
|
//
|
|
|
|
add(who.movedRef)
|
|
|
|
}
|
|
|
|
|
|
|
|
fun add(s: TootStatus?) {
|
|
|
|
if (s == null) return
|
|
|
|
add(s.accountRef)
|
|
|
|
add(s.reblog)
|
2021-06-20 15:12:25 +02:00
|
|
|
s.tags?.forEach { tagSet.add(it.name) }
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun add(n: TootNotification?) {
|
|
|
|
if (n == null) return
|
|
|
|
add(n.accountRef)
|
|
|
|
add(n.status)
|
|
|
|
}
|
|
|
|
|
|
|
|
suspend fun update(client: TootApiClient, parser: TootParser) {
|
|
|
|
|
|
|
|
var n: Int
|
|
|
|
var size: Int
|
|
|
|
|
|
|
|
if (column.isMisskey) {
|
|
|
|
|
|
|
|
// parser内部にアカウントIDとRelationのマップが生成されるので、それをデータベースに記録する
|
|
|
|
run {
|
|
|
|
val now = System.currentTimeMillis()
|
2021-06-20 15:12:25 +02:00
|
|
|
val whoList =
|
2021-05-17 16:13:04 +02:00
|
|
|
parser.misskeyUserRelationMap.entries.toMutableList()
|
|
|
|
var start = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
val end = whoList.size
|
2021-05-17 16:13:04 +02:00
|
|
|
while (start < end) {
|
|
|
|
var step = end - start
|
|
|
|
if (step > Column.RELATIONSHIP_LOAD_STEP) step = Column.RELATIONSHIP_LOAD_STEP
|
2021-06-20 15:12:25 +02:00
|
|
|
UserRelation.saveListMisskey(now, column.accessInfo.db_id, whoList, start, step)
|
2021-05-17 16:13:04 +02:00
|
|
|
start += step
|
|
|
|
}
|
2021-06-28 09:35:09 +02:00
|
|
|
log.d("updateRelation: update $end relations.")
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 2018/11/1 Misskeyにもリレーション取得APIができた
|
|
|
|
// アカウントIDの集合からRelationshipを取得してデータベースに記録する
|
|
|
|
|
2021-06-20 15:12:25 +02:00
|
|
|
size = whoSet.size
|
2021-05-17 16:13:04 +02:00
|
|
|
if (size > 0) {
|
2021-06-20 15:12:25 +02:00
|
|
|
val whoList = ArrayList<EntityId>(size)
|
|
|
|
whoList.addAll(whoSet)
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
val now = System.currentTimeMillis()
|
|
|
|
|
|
|
|
n = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
while (n < whoList.size) {
|
2021-05-17 16:13:04 +02:00
|
|
|
val userIdList = ArrayList<EntityId>(Column.RELATIONSHIP_LOAD_STEP)
|
|
|
|
for (i in 0 until Column.RELATIONSHIP_LOAD_STEP) {
|
|
|
|
if (n >= size) break
|
2021-06-20 15:12:25 +02:00
|
|
|
if (!parser.misskeyUserRelationMap.containsKey(whoList[n])) {
|
|
|
|
userIdList.add(whoList[n])
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
++n
|
|
|
|
}
|
|
|
|
if (userIdList.isEmpty()) continue
|
|
|
|
|
|
|
|
val result = client.request(
|
|
|
|
"/api/users/relation",
|
2021-06-20 15:12:25 +02:00
|
|
|
column.accessInfo.putMisskeyApiToken().apply {
|
2021-05-17 16:13:04 +02:00
|
|
|
put(
|
|
|
|
"userId",
|
|
|
|
userIdList.map { it.toString() }.toJsonArray()
|
|
|
|
)
|
|
|
|
}.toPostRequestBuilder()
|
|
|
|
)
|
|
|
|
|
|
|
|
if (result == null || result.response?.code in 400 until 500) break
|
|
|
|
|
|
|
|
val list = parseList(::TootRelationShip, parser, result.jsonArray)
|
|
|
|
if (list.size == userIdList.size) {
|
|
|
|
for (i in 0 until list.size) {
|
|
|
|
list[i].id = userIdList[i]
|
|
|
|
}
|
2021-06-27 23:55:52 +02:00
|
|
|
UserRelation.saveListMisskeyRelationApi(now, column.accessInfo.db_id, list)
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
}
|
2021-06-28 09:35:09 +02:00
|
|
|
log.d("updateRelation: update $n relations.")
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// アカウントIDの集合からRelationshipを取得してデータベースに記録する
|
2021-06-20 15:12:25 +02:00
|
|
|
size = whoSet.size
|
2021-05-17 16:13:04 +02:00
|
|
|
if (size > 0) {
|
2021-06-20 15:12:25 +02:00
|
|
|
val whoList = ArrayList<EntityId>(size)
|
|
|
|
whoList.addAll(whoSet)
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
val now = System.currentTimeMillis()
|
|
|
|
|
|
|
|
n = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
while (n < whoList.size) {
|
2021-05-17 16:13:04 +02:00
|
|
|
val sb = StringBuilder()
|
|
|
|
sb.append("/api/v1/accounts/relationships")
|
|
|
|
for (i in 0 until Column.RELATIONSHIP_LOAD_STEP) {
|
|
|
|
if (n >= size) break
|
|
|
|
sb.append(if (i == 0) '?' else '&')
|
|
|
|
sb.append("id[]=")
|
2021-06-20 15:12:25 +02:00
|
|
|
sb.append(whoList[n++].toString())
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
val result = client.request(sb.toString()) ?: break // cancelled.
|
|
|
|
val list = parseList(::TootRelationShip, parser, result.jsonArray)
|
|
|
|
if (list.size > 0) UserRelation.saveListMastodon(
|
|
|
|
now,
|
2021-06-20 15:12:25 +02:00
|
|
|
column.accessInfo.db_id,
|
2021-05-17 16:13:04 +02:00
|
|
|
list
|
|
|
|
)
|
|
|
|
}
|
2021-06-28 09:35:09 +02:00
|
|
|
log.d("updateRelation: update $n relations.")
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 出現したacctをデータベースに記録する
|
2021-06-20 15:12:25 +02:00
|
|
|
size = acctSet.size
|
2021-05-17 16:13:04 +02:00
|
|
|
if (size > 0) {
|
2021-06-20 15:12:25 +02:00
|
|
|
val acctList = ArrayList<String?>(size)
|
|
|
|
acctList.addAll(acctSet)
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
val now = System.currentTimeMillis()
|
|
|
|
|
|
|
|
n = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
while (n < acctList.size) {
|
2021-05-17 16:13:04 +02:00
|
|
|
var length = size - n
|
|
|
|
if (length > Column.ACCT_DB_STEP) length = Column.ACCT_DB_STEP
|
2021-06-20 15:12:25 +02:00
|
|
|
AcctSet.saveList(now, acctList, n, length)
|
2021-05-17 16:13:04 +02:00
|
|
|
n += length
|
|
|
|
}
|
2021-06-28 09:35:09 +02:00
|
|
|
log.d("updateRelation: update $n acct.")
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// 出現したタグをデータベースに記録する
|
2021-06-20 15:12:25 +02:00
|
|
|
size = tagSet.size
|
2021-05-17 16:13:04 +02:00
|
|
|
if (size > 0) {
|
2021-06-20 15:12:25 +02:00
|
|
|
val tagList = ArrayList<String?>(size)
|
|
|
|
tagList.addAll(tagSet)
|
2021-05-17 16:13:04 +02:00
|
|
|
|
|
|
|
val now = System.currentTimeMillis()
|
|
|
|
|
|
|
|
n = 0
|
2021-06-20 15:12:25 +02:00
|
|
|
while (n < tagList.size) {
|
2021-05-17 16:13:04 +02:00
|
|
|
var length = size - n
|
|
|
|
if (length > Column.ACCT_DB_STEP) length = Column.ACCT_DB_STEP
|
2021-06-20 15:12:25 +02:00
|
|
|
TagSet.saveList(now, tagList, n, length)
|
2021-05-17 16:13:04 +02:00
|
|
|
n += length
|
|
|
|
}
|
2021-06-28 09:35:09 +02:00
|
|
|
log.d("updateRelation: update $n tag.")
|
2021-05-17 16:13:04 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|