別アカファボ、ブーストでMisskey アカウントを選べる( https://misskey.m544.net/ で動作確認済)
This commit is contained in:
parent
7c7fc90a2e
commit
dd8534f0f4
|
@ -2890,7 +2890,7 @@ class Column(
|
||||||
task.executeOnExecutor(App1.task_executor)
|
task.executeOnExecutor(App1.task_executor)
|
||||||
}
|
}
|
||||||
|
|
||||||
var bMinIdMatched : Boolean = false
|
private var bMinIdMatched : Boolean = false
|
||||||
|
|
||||||
private fun parseRange(
|
private fun parseRange(
|
||||||
result : TootApiResult?,
|
result : TootApiResult?,
|
||||||
|
|
|
@ -205,8 +205,8 @@ internal class DlgContextMenu(
|
||||||
val canPin = status.canPin(access_info)
|
val canPin = status.canPin(access_info)
|
||||||
btnProfileUnpin.visibility = if(canPin && status.pinned) View.VISIBLE else View.GONE
|
btnProfileUnpin.visibility = if(canPin && status.pinned) View.VISIBLE else View.GONE
|
||||||
btnProfilePin.visibility = if(canPin && ! status.pinned) View.VISIBLE else View.GONE
|
btnProfilePin.visibility = if(canPin && ! status.pinned) View.VISIBLE else View.GONE
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var bShowConversationMute = false
|
var bShowConversationMute = false
|
||||||
if(status != null) {
|
if(status != null) {
|
||||||
if(access_info.isMe(status.account)) {
|
if(access_info.isMe(status.account)) {
|
||||||
|
|
|
@ -2,20 +2,17 @@ package jp.juggler.subwaytooter.api
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
import android.net.Uri
|
|
||||||
import jp.juggler.subwaytooter.*
|
import jp.juggler.subwaytooter.*
|
||||||
import jp.juggler.subwaytooter.api.entity.TootAccount
|
import jp.juggler.subwaytooter.api.entity.TootAccount
|
||||||
|
|
||||||
import org.json.JSONException
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
import jp.juggler.subwaytooter.table.ClientInfo
|
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount
|
|
||||||
import jp.juggler.subwaytooter.api.entity.TootInstance
|
import jp.juggler.subwaytooter.api.entity.TootInstance
|
||||||
import jp.juggler.subwaytooter.api.entity.TootStatus
|
import jp.juggler.subwaytooter.api.entity.TootStatus
|
||||||
|
import jp.juggler.subwaytooter.table.ClientInfo
|
||||||
|
import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
import jp.juggler.subwaytooter.util.*
|
import jp.juggler.subwaytooter.util.*
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
|
@ -1346,16 +1343,32 @@ class TootApiClient(
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TootApiClient.syncAccountByUrl(accessInfo : SavedAccount, who_url : String) : TootApiResult? {
|
private fun parseMisskeyApShow(parser : TootParser, jsonObject : JSONObject?) : Any? {
|
||||||
|
return when(jsonObject?.parseString("type")) {
|
||||||
|
"Note" -> {
|
||||||
|
parser.status(jsonObject.optJSONObject("object"))
|
||||||
|
}
|
||||||
|
|
||||||
|
"User" -> {
|
||||||
|
parser.status(jsonObject.optJSONObject("object"))
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun TootApiClient.syncAccountByUrl(accessInfo : SavedAccount, who_url : String) : TootApiResult? {
|
||||||
|
|
||||||
// misskey由来のアカウントURLは https://host/@user@instance などがある
|
// misskey由来のアカウントURLは https://host/@user@instance などがある
|
||||||
val m = TootAccount.reAccountUrl.matcher(who_url)
|
val m = TootAccount.reAccountUrl.matcher(who_url)
|
||||||
if( m.find() ){
|
if(m.find()) {
|
||||||
// val host = m.group(1)
|
// val host = m.group(1)
|
||||||
val user = m.group(2).unescapeUri()
|
val user = m.group(2).unescapeUri()
|
||||||
val instance = m.groupOrNull(3)?.unescapeUri()
|
val instance = m.groupOrNull(3)?.unescapeUri()
|
||||||
if( instance?.isNotEmpty()==true){
|
if(instance?.isNotEmpty() == true) {
|
||||||
return this.syncAccountByUrl( accessInfo,"https://$instance/@$user")
|
return this.syncAccountByUrl(accessInfo, "https://$instance/@$user")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1447,61 +1460,75 @@ fun TootApiClient.syncAccountByAcct(accessInfo : SavedAccount, acct : String) :
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun TootApiClient.syncStatus(accessInfo : SavedAccount, url : String) : TootApiResult? {
|
fun TootApiClient.syncStatus(accessInfo : SavedAccount, url : String) =
|
||||||
|
|
||||||
// FIXME Misskeyアカウントでも別アカのトゥートをローカルに同期したい!
|
|
||||||
if(accessInfo.isMisskey) {
|
if(accessInfo.isMisskey) {
|
||||||
return TootApiResult("Misskey has no API to sync note from remote to local.")
|
val params = accessInfo.putMisskeyApiToken().put("uri", url)
|
||||||
}
|
val result = request("/api/ap/show", params.toPostRequestBuilder())
|
||||||
|
if(result != null) {
|
||||||
val path = String.format(
|
val obj = parseMisskeyApShow(TootParser(context, accessInfo), result.jsonObject)
|
||||||
Locale.JAPAN,
|
if(obj != null) result.data = obj
|
||||||
Column.PATH_SEARCH,
|
|
||||||
url.encodePercent()
|
|
||||||
) + "&resolve=1"
|
|
||||||
|
|
||||||
val result = request(path)
|
|
||||||
if(result != null) {
|
|
||||||
val tmp = TootParser(context, accessInfo).results(result.jsonObject)
|
|
||||||
if(tmp != null && tmp.statuses.isNotEmpty()) {
|
|
||||||
result.data = tmp.statuses[0]
|
|
||||||
}
|
}
|
||||||
|
result
|
||||||
|
} else {
|
||||||
|
val path = String.format(
|
||||||
|
Locale.JAPAN,
|
||||||
|
Column.PATH_SEARCH,
|
||||||
|
url.encodePercent()
|
||||||
|
) + "&resolve=1"
|
||||||
|
|
||||||
|
val result = request(path)
|
||||||
|
if(result != null) {
|
||||||
|
val tmp = TootParser(context, accessInfo).results(result.jsonObject)
|
||||||
|
if(tmp != null && tmp.statuses.isNotEmpty()) {
|
||||||
|
result.data = tmp.statuses[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
private inline fun <Z:Any?> String?.useNotEmpty( block:(String)->Z? ) :Z? =
|
||||||
|
if(this?.isNotEmpty() == true) {
|
||||||
|
block(this)
|
||||||
|
}else{
|
||||||
|
null
|
||||||
}
|
}
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
fun TootApiClient.syncStatus(
|
fun TootApiClient.syncStatus(
|
||||||
accessInfo : SavedAccount,
|
accessInfo : SavedAccount,
|
||||||
statusRemote : TootStatus
|
statusRemote : TootStatus
|
||||||
) : TootApiResult? {
|
) : TootApiResult? {
|
||||||
|
|
||||||
// FIXME Misskeyアカウントでも別アカのトゥートをローカルに同期したい!
|
// URL->URIの順に試す
|
||||||
if(accessInfo.isMisskey) {
|
|
||||||
return TootApiResult("Misskey has no API to sync note from remote to local.")
|
|
||||||
}
|
|
||||||
|
|
||||||
var result : TootApiResult? = TootApiResult("missing url or uri")
|
val uriList = ArrayList<String>(2)
|
||||||
var sv = statusRemote.url
|
|
||||||
when {
|
statusRemote.url.useNotEmpty {
|
||||||
sv?.isEmpty() != false -> {
|
if( it.contains("/notes/") ){
|
||||||
}
|
|
||||||
|
|
||||||
sv.contains("/notes/") -> {
|
|
||||||
// Misskeyタンスから読んだマストドンの投稿はurlがmisskeyタンス上のものになる
|
// Misskeyタンスから読んだマストドンの投稿はurlがmisskeyタンス上のものになる
|
||||||
// uri で試す
|
// ActivityPub object id としては不適切なので使わない
|
||||||
|
}else {
|
||||||
|
uriList.add(it)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else -> {
|
|
||||||
result = syncStatus(accessInfo, sv)
|
statusRemote.uri.useNotEmpty {
|
||||||
if(result == null || result.data is TootStatus) {
|
// uri の方は↑の問題はない
|
||||||
return result
|
uriList.add(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( accessInfo.isMisskey && uriList.size >1 && uriList[0].contains("@") ){
|
||||||
|
// https://github.com/syuilo/misskey/pull/2832
|
||||||
|
// @user を含むuri はMisskeyだと少し効率が悪いそうなので順序を入れ替える
|
||||||
|
uriList.reverse()
|
||||||
|
}
|
||||||
|
|
||||||
|
for( uri in uriList){
|
||||||
|
val result = syncStatus(accessInfo, uri)
|
||||||
|
if(result == null || result.data is TootStatus) {
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sv = statusRemote.uri
|
return TootApiResult("can't resolve status URL/URI.")
|
||||||
if(sv?.isNotEmpty() == true) {
|
|
||||||
result = syncStatus(accessInfo, sv)
|
|
||||||
}
|
|
||||||
return result
|
|
||||||
}
|
}
|
|
@ -342,9 +342,8 @@ private fun ByteArray.encodeHex() : String {
|
||||||
return sb.toString()
|
return sb.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ByteArray.encodeBase64Url() : String {
|
fun ByteArray.encodeBase64Url() : String =
|
||||||
return Base64.encodeToString(this, Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP)
|
Base64.encodeToString(this, Base64.URL_SAFE or Base64.NO_PADDING or Base64.NO_WRAP)
|
||||||
}
|
|
||||||
|
|
||||||
fun ByteArray.digestSHA256() : ByteArray {
|
fun ByteArray.digestSHA256() : ByteArray {
|
||||||
val digest = MessageDigest.getInstance("SHA-256")
|
val digest = MessageDigest.getInstance("SHA-256")
|
||||||
|
|
Loading…
Reference in New Issue