リファクタ

This commit is contained in:
tateisu 2019-01-17 00:27:37 +09:00
parent 8df3657f43
commit 956ec7128a
12 changed files with 215 additions and 224 deletions

View File

@ -509,7 +509,10 @@ class ActAccountSetting
R.id.btnAccountRemove -> performAccountRemove() R.id.btnAccountRemove -> performAccountRemove()
R.id.btnVisibility -> performVisibility() R.id.btnVisibility -> performVisibility()
R.id.btnOpenBrowser -> App1.openBrowser(this@ActAccountSetting,"https://" + account.host + "/") R.id.btnOpenBrowser -> App1.openBrowser(
this@ActAccountSetting,
"https://" + account.host + "/"
)
R.id.btnPushSubscription -> startTest() R.id.btnPushSubscription -> startTest()
R.id.btnUserCustom -> ActNickname.open( R.id.btnUserCustom -> ActNickname.open(
@ -727,8 +730,8 @@ class ActAccountSetting
private fun initializeProfile() { private fun initializeProfile() {
// 初期状態 // 初期状態
val question_id = R.drawable.wide_question val question_id = R.drawable.wide_question
ivProfileAvatar.setErrorImage( defaultColorIcon(this,question_id)) ivProfileAvatar.setErrorImage(defaultColorIcon(this, question_id))
ivProfileAvatar.setDefaultImage( defaultColorIcon(this,question_id)) ivProfileAvatar.setDefaultImage(defaultColorIcon(this, question_id))
val loadingText = when(account.isPseudo) { val loadingText = when(account.isPseudo) {
true -> "(disabled for pseudo account)" true -> "(disabled for pseudo account)"
@ -778,8 +781,8 @@ class ActAccountSetting
} else { } else {
var result = account.checkConfirmed(this@ActAccountSetting,client) var result = account.checkConfirmed(this@ActAccountSetting, client)
if(result == null || result.error!=null) return result if(result == null || result.error != null) return result
result = client.request("/api/v1/accounts/verify_credentials") result = client.request("/api/v1/accounts/verify_credentials")
val jsonObject = result?.jsonObject val jsonObject = result?.jsonObject
@ -942,7 +945,7 @@ class ActAccountSetting
private fun uploadImageMisskey( private fun uploadImageMisskey(
client : TootApiClient, client : TootApiClient,
opener : InputStreamOpener opener : InputStreamOpener
) : TootApiResult? { ) : Pair<TootApiResult?, TootAttachment?> {
val size = getStreamSize(true, opener.open()) val size = getStreamSize(true, opener.open())
@ -982,21 +985,19 @@ class ActAccountSetting
} }
) )
var ta : TootAttachment? = null
val result = client.request( val result = client.request(
"/api/drive/files/create", "/api/drive/files/create",
multipart_builder.build().toPost() multipart_builder.build().toPost()
) )?.also { result ->
val jsonObject = result.jsonObject
val jsonObject = result?.jsonObject
if(jsonObject != null) { if(jsonObject != null) {
val a = parseItem(::TootAttachment, ServiceType.MISSKEY, jsonObject) ta = parseItem(::TootAttachment, ServiceType.MISSKEY, jsonObject)
if(a == null) { if(ta == null) result.error = "TootAttachment.parse failed"
result.error = "TootAttachment.parse failed"
} else {
result.data = a
} }
} }
return result
return Pair(result, ta)
} }
var data : TootAccount? = null var data : TootAccount? = null
@ -1024,8 +1025,8 @@ class ActAccountSetting
is Boolean -> params.put(misskeyKey, value) is Boolean -> params.put(misskeyKey, value)
is InputStreamOpener -> { is InputStreamOpener -> {
val result = uploadImageMisskey(client, value) val (result, ta) = uploadImageMisskey(client, value)
val ta = result?.data as? TootAttachment ?: return result ta ?: return result
params.put(misskeyKey, ta.id) params.put(misskeyKey, ta.id)
} }
} }
@ -1084,8 +1085,6 @@ class ActAccountSetting
} }
} }
val result = client.request( val result = client.request(
"/api/v1/accounts/update_credentials", "/api/v1/accounts/update_credentials",
multipart_body_builder.build().toPatch() multipart_body_builder.build().toPatch()
@ -1184,13 +1183,16 @@ class ActAccountSetting
// Mastodon 2.7 でnoteの文字数計算が変わる // Mastodon 2.7 でnoteの文字数計算が変わる
// https://github.com/tootsuite/mastodon/commit/45899cfa691b1e4f43da98c456ae8faa584eb437 // https://github.com/tootsuite/mastodon/commit/45899cfa691b1e4f43da98c456ae8faa584eb437
private val reLinkUrl = Pattern.compile("""(https?://[\w/:%#@${'$'}&?!()\[\]~.=+\-]+)""") private val reLinkUrl = Pattern.compile("""(https?://[\w/:%#@${'$'}&?!()\[\]~.=+\-]+)""")
private val reMention =Pattern.compile("""(?<=^|[^/\w\p{Pc}])@((\w+([\w.-]+\w+)?)(?:@[a-z0-9.\-]+[a-z0-9]+)?)""",Pattern.CASE_INSENSITIVE) private val reMention = Pattern.compile(
private val strUrlReplacement = (0 until 23).map{ ' '}.joinToString() """(?<=^|[^/\w\p{Pc}])@((\w+([\w.-]+\w+)?)(?:@[a-z0-9.\-]+[a-z0-9]+)?)""",
private fun countNoteText(s:String):Int{ Pattern.CASE_INSENSITIVE
)
private val strUrlReplacement = (0 until 23).map { ' ' }.joinToString()
private fun countNoteText(s : String) : Int {
val s2 = s val s2 = s
.replaceAll(reLinkUrl,strUrlReplacement) .replaceAll(reLinkUrl, strUrlReplacement)
.replaceAll(reMention,"@\\2") .replaceAll(reMention, "@\\2")
return s2.codePointCount(0,s2.length) return s2.codePointCount(0, s2.length)
} }
private fun sendLocked(willLocked : Boolean) { private fun sendLocked(willLocked : Boolean) {

View File

@ -232,6 +232,8 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
private fun updateBackground(uriArg : Uri) { private fun updateBackground(uriArg : Uri) {
TootTaskRunner(this).run(object : TootTask { TootTaskRunner(this).run(object : TootTask {
var bgUri : String? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
try { try {
val backgroundDir = Column.getBackgroundImageDir(this@ActColumnCustomize) val backgroundDir = Column.getBackgroundImageDir(this@ActColumnCustomize)
@ -271,9 +273,8 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
} }
} }
val result = TootApiResult() bgUri = fileUri.toString()
result.data = fileUri.toString() return TootApiResult()
return result
} catch(ex : Throwable) { } catch(ex : Throwable) {
log.trace(ex) log.trace(ex)
return TootApiResult(ex.withCaption("can't update background image.")) return TootApiResult(ex.withCaption("can't update background image."))
@ -281,14 +282,16 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {
val bgUri = this.bgUri
when { when {
result == null -> return result == null -> return
result.error != null -> showToast(this@ActColumnCustomize, true, result.error)
else -> { bgUri != null -> {
column.column_bg_image = result.data as String column.column_bg_image = bgUri
show() show()
} }
else -> showToast(this@ActColumnCustomize, true, result.error ?: "?")
} }
} }
}) })
@ -448,10 +451,10 @@ class ActColumnCustomize : AppCompatActivity(), View.OnClickListener, ColorPicke
private fun loadImage(ivColumnBackground : ImageView, url : String) { private fun loadImage(ivColumnBackground : ImageView, url : String) {
try { try {
if( url.isEmpty() ){ if(url.isEmpty()) {
closeBitmaps() closeBitmaps()
return return
}else if(url == last_image_uri) { } else if(url == last_image_uri) {
// 今表示してるのと同じ // 今表示してるのと同じ
return return
} }

View File

@ -612,7 +612,7 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
return bitmap2 return bitmap2
} }
fun getHttpCached(client : TootApiClient, url : String) : TootApiResult? { fun getHttpCached(client : TootApiClient, url : String) : Pair<TootApiResult?,ByteArray?> {
val result = TootApiResult.makeWithCaption(url) val result = TootApiResult.makeWithCaption(url)
val request = Request.Builder() val request = Request.Builder()
@ -626,46 +626,49 @@ class ActMediaViewer : AppCompatActivity(), View.OnClickListener {
tmpOkhttpClient = App1.ok_http_client_media_viewer tmpOkhttpClient = App1.ok_http_client_media_viewer
) { ) {
request request
}) return result }
) return Pair(result,null)
if(client.isApiCancelled) return Pair(null,null)
if(client.isApiCancelled) return null
val response = requireNotNull(result.response) val response = requireNotNull(result.response)
if(! response.isSuccessful) { if(! response.isSuccessful) {
return result.setError(TootApiClient.formatResponse(response, result.caption)) result.setError(TootApiClient.formatResponse(response, result.caption))
return Pair(result,null)
} }
// log.d("cached=${ response.cacheResponse() != null }")
try { try {
result.data = ProgressResponseBody.bytes(response) { bytesRead, bytesTotal -> val ba = ProgressResponseBody.bytes(response) { bytesRead, bytesTotal ->
// 50MB以上のデータはキャンセルする // 50MB以上のデータはキャンセルする
if(Math.max(bytesRead, bytesTotal) >= 50000000) { if(Math.max(bytesRead, bytesTotal) >= 50000000) {
throw RuntimeException("media attachment is larger than 50000000") throw RuntimeException("media attachment is larger than 50000000")
} }
client.publishApiProgressRatio(bytesRead.toInt(), bytesTotal.toInt()) client.publishApiProgressRatio(bytesRead.toInt(), bytesTotal.toInt())
} }
if(client.isApiCancelled) return null if(client.isApiCancelled) return Pair(null,null)
return Pair(result,ba)
} catch(ex : Throwable) { } catch(ex : Throwable) {
result.setError(TootApiClient.formatResponse(response, result.caption, "?")) result.setError(TootApiClient.formatResponse(response, result.caption, "?"))
return Pair(result,null)
} }
return result
} }
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
if(urlList.isEmpty()) return TootApiResult("missing url") if(urlList.isEmpty()) return TootApiResult("missing url")
var result : TootApiResult? = null var lastResult : TootApiResult? = null
for(url in urlList) { for(url in urlList) {
result = getHttpCached(client, url) val(result,ba) = getHttpCached(client, url)
val data = result?.data as? ByteArray lastResult = result
if(data != null) { if( ba != null){
client.publishApiProgress("decoding image…") client.publishApiProgress("decoding image…")
val bitmap = decodeBitmap(data, 2048) val bitmap = decodeBitmap(ba, 2048)
if(bitmap != null) { if(bitmap != null) {
this.bitmap = bitmap this.bitmap = bitmap
break break
} }
} }
} }
return result return lastResult
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {

View File

@ -1294,14 +1294,8 @@ class ActPost : AppCompatActivity(),
var target_status : TootStatus? = null var target_status : TootStatus? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
val (result, localStatus) = client.syncStatus(access_info, in_reply_to_url)
val result = client.syncStatus(access_info, in_reply_to_url) target_status = localStatus
if(result?.data != null) {
target_status = result.data as? TootStatus
if(target_status == null) {
return TootApiResult(getString(R.string.status_id_conversion_failed))
}
}
return result return result
} }

View File

@ -2008,8 +2008,8 @@ class Column(
} else { } else {
// カラムに紐付けられたアカウントのタンスのインスタンス情報 // カラムに紐付けられたアカウントのタンスのインスタンス情報
} }
val result = client.parseInstanceInformation(client.getInstanceInformation()) val(result,ti) = client.parseInstanceInformation(client.getInstanceInformation())
instance_tmp = result?.data as? TootInstance instance_tmp = ti
return result return result
} }

View File

@ -343,18 +343,15 @@ internal class StreamReader(
TootTaskRunner(context).run(access_info, object : TootTask { TootTaskRunner(context).run(access_info, object : TootTask {
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
val result = client.webSocket(end_point, this@Reader) val( result ,ws) = client.webSocket(end_point, this@Reader)
if(result == null) { when {
result == null -> {
log.d("startRead: cancelled.") log.d("startRead: cancelled.")
bListening.set(false) bListening.set(false)
fireListeningChanged() fireListeningChanged()
} else { }
val ws = result.data as? WebSocket ws == null -> {
if(ws != null) {
socket.set(ws)
fireListeningChanged()
} else {
val error = result.error val error = result.error
log.d("startRead: error. $error") log.d("startRead: error. $error")
bListening.set(false) bListening.set(false)
@ -363,6 +360,10 @@ internal class StreamReader(
handler.removeCallbacks(proc_reconnect) handler.removeCallbacks(proc_reconnect)
handler.postDelayed(proc_reconnect, 5000L) handler.postDelayed(proc_reconnect, 5000L)
} }
else->{
socket.set(ws)
fireListeningChanged()
}
} }
return result return result
} }

View File

@ -120,13 +120,16 @@ object Action_Instance {
columnType : Int columnType : Int
) { ) {
TootTaskRunner(activity).run(access_info, object : TootTask { TootTaskRunner(activity).run(access_info, object : TootTask {
var localStatus: TootStatus? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
return client.syncStatus(access_info, status) val(result,localStatus) = client.syncStatus(access_info, status)
this.localStatus = localStatus
return result
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {
result ?: return result ?: return
val localStatus = result.data as? TootStatus val localStatus = this.localStatus
if(localStatus != null) { if(localStatus != null) {
timelinePublicAround2(activity, access_info, pos, localStatus.id, columnType) timelinePublicAround2(activity, access_info, pos, localStatus.id, columnType)
} else { } else {

View File

@ -118,59 +118,52 @@ object Action_Toot {
var new_status : TootStatus? = null var new_status : TootStatus? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
var result : TootApiResult?
val target_status : TootStatus val target_status = if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
result = client.syncStatus(access_info, arg_status) val(result,status) = client.syncStatus(access_info, arg_status)
if(result?.data == null) return result status ?: return result
target_status = result.data as? TootStatus if(status.favourited) {
?:
return TootApiResult(activity.getString(R.string.status_id_conversion_failed))
if(target_status.favourited) {
return TootApiResult(activity.getString(R.string.already_favourited)) return TootApiResult(activity.getString(R.string.already_favourited))
} }
status
} else { } else {
target_status = arg_status arg_status
} }
if(access_info.isMisskey) {
val params = access_info.putMisskeyApiToken(JSONObject())
.put("noteId", target_status.id.toString())
result = client.request( return if(access_info.isMisskey) {
client.request(
if(bSet) { if(bSet) {
"/api/notes/favorites/create" "/api/notes/favorites/create"
} else { } else {
"/api/notes/favorites/delete" "/api/notes/favorites/delete"
} },
, params.toPostRequestBuilder() access_info
) .putMisskeyApiToken(JSONObject())
.put("noteId", target_status.id.toString())
.toPostRequestBuilder()
)?.also{ result->
// 正常レスポンスは 204 no content // 正常レスポンスは 204 no content
// 既にお気に入り済みならエラー文字列に'already favorited' が返る // 既にお気に入り済みならエラー文字列に'already favorited' が返る
if(result?.response?.code() == 204 if(result.response?.code() == 204
|| result?.error?.contains("already favorited") == true || result.error?.contains("already favorited") == true
|| result?.error?.contains("already not favorited") == true || result.error?.contains("already not favorited") == true
) { ) {
// 成功した // 成功した
target_status.favourited = bSet new_status = target_status.apply{
new_status = target_status favourited = bSet
}
}
} }
} else { } else {
result = client.request( client.request(
"/api/v1/statuses/${target_status.id}/${if(bSet) "favourite" else "unfavourite"}", "/api/v1/statuses/${target_status.id}/${if(bSet) "favourite" else "unfavourite"}",
"".toRequestBody().toPost() "".toRequestBody().toPost()
) )?.also{ result->
val jsonObject = result?.jsonObject new_status = TootParser(activity, access_info).status(result.jsonObject)
new_status = TootParser(activity, access_info).status(jsonObject) }
} }
return result
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {
@ -364,34 +357,29 @@ object Action_Toot {
val parser = TootParser(activity, access_info) val parser = TootParser(activity, access_info)
var result : TootApiResult?
val target_status : TootStatus
if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
result = client.syncStatus(access_info, arg_status) val target_status = if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
if(result?.data == null) return result val(result,status) = client.syncStatus(access_info, arg_status)
target_status = result.data as? TootStatus if(status == null) return result
?: if(status.reblogged) {
return TootApiResult(activity.getString(R.string.status_id_conversion_failed))
if(target_status.reblogged) {
return TootApiResult(activity.getString(R.string.already_boosted)) return TootApiResult(activity.getString(R.string.already_boosted))
} }
status
} else { } else {
// 既に自タンスのステータスがある // 既に自タンスのステータスがある
target_status = arg_status arg_status
} }
if(access_info.isMisskey) { if(access_info.isMisskey) {
if(! bSet) { if(! bSet) {
return TootApiResult("Misskey has no 'unrenote' API.") return TootApiResult("Misskey has no 'unrenote' API.")
} else { } else {
val params = access_info.putMisskeyApiToken(JSONObject()) val params = access_info.putMisskeyApiToken(JSONObject())
.put("renoteId", target_status.id.toString()) .put("renoteId", target_status.id.toString())
result = client.request("/api/notes/create", params.toPostRequestBuilder()) val result = client.request("/api/notes/create", params.toPostRequestBuilder())
val jsonObject = result?.jsonObject val jsonObject = result?.jsonObject
if(jsonObject != null) { if(jsonObject != null) {
val new_status = parser.status( val new_status = parser.status(
@ -405,8 +393,7 @@ object Action_Toot {
} }
} else { } else {
val result = client.request(
result = client.request(
"/api/v1/statuses/${target_status.id}/${if(bSet) "reblog" else "unreblog"}", "/api/v1/statuses/${target_status.id}/${if(bSet) "reblog" else "unreblog"}",
"".toRequestBody().toPost() "".toRequestBody().toPost()
) )
@ -749,11 +736,10 @@ object Action_Toot {
.run(access_info, object : TootTask { .run(access_info, object : TootTask {
var local_status_id : EntityId? = null var local_status_id : EntityId? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? =
var result : TootApiResult?
if(access_info.isPseudo) { if(access_info.isPseudo) {
// 疑似アカウントではURLからIDを取得するのにHTMLと正規表現を使う // 疑似アカウントではURLからIDを取得するのにHTMLと正規表現を使う
result = client.getHttp(remote_status_url) val result = client.getHttp(remote_status_url)
val string = result?.string val string = result?.string
if(string != null) { if(string != null) {
try { try {
@ -765,21 +751,18 @@ object Action_Toot {
log.e(ex, "openStatusRemote: can't parse status id from HTML data.") log.e(ex, "openStatusRemote: can't parse status id from HTML data.")
} }
if(local_status_id == null) { if(result.error == null && local_status_id == null) {
result = TootApiResult( result.setError(activity.getString(R.string.status_id_conversion_failed))
activity.getString(R.string.status_id_conversion_failed)
)
} }
} }
result
} else { } else {
result = client.syncStatus(access_info, remote_status_url) val(result,status) = client.syncStatus(access_info, remote_status_url)
if(result?.data == null) return result if(status != null){
val status = result.data as? TootStatus
?: return TootApiResult(activity.getString(R.string.status_id_conversion_failed))
local_status_id = status.id local_status_id = status.id
log.d("status id conversion %s => %s", remote_status_url, status.id) log.d("status id conversion %s => %s", remote_status_url, status.id)
} }
return result result
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {
@ -888,11 +871,8 @@ object Action_Toot {
var local_status : TootStatus? = null var local_status : TootStatus? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
val result = client.syncStatus(access_info, remote_status_url) val (result,status) = client.syncStatus(access_info, remote_status_url)
if(result?.data == null) return result local_status = status
local_status = result.data as? TootStatus
?:
return TootApiResult(activity.getString(R.string.status_id_conversion_failed))
return result return result
} }
@ -1108,21 +1088,21 @@ object Action_Toot {
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
val target_status : TootStatus val target_status = if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
if(nCrossAccountMode == CROSS_ACCOUNT_REMOTE_INSTANCE) {
val result = client.syncStatus(access_info, arg_status) val(result,status) = client.syncStatus(access_info, arg_status)
if(result?.data == null) return result
target_status = result.data as? TootStatus status?: return result
?: return TootApiResult(
activity.getString(R.string.status_id_conversion_failed) if(status.myReaction != null) {
)
if(target_status.myReaction != null) {
return TootApiResult(activity.getString(R.string.already_reactioned)) return TootApiResult(activity.getString(R.string.already_reactioned))
} }
status
} else { } else {
// 既に自タンスのステータスがある // 既に自タンスのステータスがある
target_status = arg_status arg_status
} }

View File

@ -544,21 +544,18 @@ class TootApiClient(
} }
// インスタンス情報を取得する // インスタンス情報を取得する
internal fun parseInstanceInformation(result : TootApiResult?) : TootApiResult? { internal fun parseInstanceInformation(result : TootApiResult?) : Pair<TootApiResult?,TootInstance?> {
var ti: TootInstance? = null
val json = result?.jsonObject val json = result?.jsonObject
if(json != null) { if(json != null) {
val parser = TootParser( val parser = TootParser(
context, context,
LinkHelper.newLinkHelper(instance, isMisskey = json.optBoolean(KEY_IS_MISSKEY)) LinkHelper.newLinkHelper(instance, isMisskey = json.optBoolean(KEY_IS_MISSKEY))
) )
val ti = parser.instance(json) ti = parser.instance(json)
if(ti != null) { if(ti == null) result.setError("can't parse data in instance information.")
result.data = ti
} else {
result.setError("can't parse data in instance information.")
} }
} return Pair(result,ti)
return result
} }
private fun getAppInfoMisskey(appId : String?) : TootApiResult? { private fun getAppInfoMisskey(appId : String?) : TootApiResult? {
@ -1054,21 +1051,26 @@ class TootApiClient(
// クライアントを登録してブラウザで開くURLを生成する // クライアントを登録してブラウザで開くURLを生成する
fun authentication1(clientNameArg : String) : TootApiResult? { fun authentication1(clientNameArg : String) : TootApiResult? {
var lastRi : TootApiResult? = null
// misskeyのインスタンス情報 // misskeyのインスタンス情報
var ri = parseInstanceInformation(getInstanceInformationMisskey()) run{
var ti = ri?.data as? TootInstance val (ri ,ti) = parseInstanceInformation(getInstanceInformationMisskey())
lastRi = ri
if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) { if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) {
return authentication1Misskey(clientNameArg, ti) return authentication1Misskey(clientNameArg, ti)
} }
}
// マストドンのインスタンス情報 // マストドンのインスタンス情報
ri = parseInstanceInformation(getInstanceInformationMastodon()) run{
ti = ri?.data as? TootInstance val (ri,ti) = parseInstanceInformation(getInstanceInformationMastodon())
lastRi = ri
if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) { if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) {
return authentication1Mastodon(clientNameArg, ti) return authentication1Mastodon(clientNameArg, ti)
} }
}
return ri return lastRi
} }
// oAuth2認証の続きを行う // oAuth2認証の続きを行う
@ -1172,16 +1174,21 @@ class TootApiClient(
} }
fun createUser1(clientNameArg : String) : TootApiResult? { fun createUser1(clientNameArg : String) : TootApiResult? {
var lastRi : TootApiResult? = null
// misskeyのインスタンス情報 // misskeyのインスタンス情報
var ri = parseInstanceInformation(getInstanceInformationMisskey()) run {
var ti = ri?.data as? TootInstance val (ri, ti) = parseInstanceInformation(getInstanceInformationMisskey())
lastRi = ri
if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) { if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) {
return TootApiResult("Misskey has no API to create new account") return TootApiResult("Misskey has no API to create new account")
} }
}
// マストドンのインスタンス情報 // マストドンのインスタンス情報
ri = parseInstanceInformation(getInstanceInformationMastodon()) run {
ti = ri?.data as? TootInstance val (ri, ti) = parseInstanceInformation(getInstanceInformationMastodon())
lastRi = ri
if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) { if(ti != null && (ri?.response?.code() ?: 0) in 200 until 300) {
if(ti.version?.matches("""\bPleroma\b""".toRegex()) == true) { if(ti.version?.matches("""\bPleroma\b""".toRegex()) == true) {
return TootApiResult("Pleroma has no API to create new account") return TootApiResult("Pleroma has no API to create new account")
@ -1189,8 +1196,8 @@ class TootApiClient(
// result.jsonObject に credentialつきのclient_info を格納して返す // result.jsonObject に credentialつきのclient_info を格納して返す
return prepareClientMastodon(clientNameArg, ti) return prepareClientMastodon(clientNameArg, ti)
} }
}
return ri return lastRi
} }
// ユーザ名入力の後に呼ばれる // ユーザ名入力の後に呼ばれる
@ -1354,21 +1361,24 @@ class TootApiClient(
return result return result
} }
fun getHttpBytes(url : String) : TootApiResult? { fun getHttpBytes(url : String) :Pair<TootApiResult?,ByteArray?> {
val result = TootApiResult.makeWithCaption(url) val result = TootApiResult.makeWithCaption(url)
if(result.error != null) return result if(result.error != null) return Pair(result,null)
if(! sendRequest(result, progressPath = url) { if( !sendRequest(result, progressPath = url) {
Request.Builder().url(url).build() Request.Builder().url(url).build()
}) return result }) {
return parseBytes(result) return Pair(result, null)
}
val r2 = parseBytes(result)
return Pair(r2,r2?.data as? ByteArray)
} }
fun webSocket(path : String, ws_listener : WebSocketListener) : TootApiResult? { fun webSocket(path : String, ws_listener : WebSocketListener) : Pair<TootApiResult?,WebSocket?> {
var ws:WebSocket? = null
val result = TootApiResult.makeWithCaption(instance) val result = TootApiResult.makeWithCaption(instance)
if(result.error != null) return result if(result.error != null) return Pair(result,null)
val account = this.account ?: return TootApiResult("account is null") val account = this.account ?: return Pair(TootApiResult("account is null"),null)
try { try {
var url = "wss://$instance$path" var url = "wss://$instance$path"
@ -1382,18 +1392,16 @@ class TootApiClient(
val request = request_builder.url(url).build() val request = request_builder.url(url).build()
publishApiProgress(context.getString(R.string.request_api, request.method(), path)) publishApiProgress(context.getString(R.string.request_api, request.method(), path))
val ws = httpClient.getWebSocket(request, ws_listener) ws = httpClient.getWebSocket(request, ws_listener)
if(isApiCancelled) { if(isApiCancelled) {
ws.cancel() ws.cancel()
return null return Pair(null,null)
} }
result.data = ws
} catch(ex : Throwable) { } catch(ex : Throwable) {
log.trace(ex) log.trace(ex)
result.error = result.error = "${result.caption}: ${ex.withCaption(context.resources, R.string.network_error)}"
"${result.caption}: ${ex.withCaption(context.resources, R.string.network_error)}"
} }
return result return Pair(result,ws)
} }
@ -1497,7 +1505,7 @@ fun TootApiClient.syncAccountByAcct(
return Pair(result, ar) return Pair(result, ar)
} }
fun TootApiClient.syncStatus(accessInfo : SavedAccount, urlArg : String) : TootApiResult? { fun TootApiClient.syncStatus(accessInfo : SavedAccount, urlArg : String) : Pair<TootApiResult?,TootStatus?> {
var url = urlArg var url = urlArg
@ -1516,7 +1524,6 @@ fun TootApiClient.syncStatus(accessInfo : SavedAccount, urlArg : String) : TootA
.put("noteId", noteId) .put("noteId", noteId)
.toPostRequestBuilder() .toPostRequestBuilder()
) )
?.also { result -> ?.also { result ->
TootParser( TootParser(
context, context,
@ -1526,19 +1533,19 @@ fun TootApiClient.syncStatus(accessInfo : SavedAccount, urlArg : String) : TootA
.status(result.jsonObject) .status(result.jsonObject)
?.apply { ?.apply {
if(host.equals(accessInfo.host, ignoreCase = true)) { if(host.equals(accessInfo.host, ignoreCase = true)) {
result.data = this return Pair(result,this)
return result
} }
uri.letNotEmpty { url = it } uri.letNotEmpty { url = it }
} }
}
?: return null // cancelled. }
?: return Pair(null,null) // cancelled.
} }
// 使いたいタンス上の投稿IDを取得する // 使いたいタンス上の投稿IDを取得する
val parser = TootParser(context, accessInfo) val parser = TootParser(context, accessInfo)
return if(accessInfo.isMisskey) { var targetStatus :TootStatus? = null
val result = if(accessInfo.isMisskey) {
request( request(
"/api/ap/show", "/api/ap/show",
accessInfo.putMisskeyApiToken() accessInfo.putMisskeyApiToken()
@ -1546,26 +1553,27 @@ fun TootApiClient.syncStatus(accessInfo : SavedAccount, urlArg : String) : TootA
.toPostRequestBuilder() .toPostRequestBuilder()
) )
?.apply { ?.apply {
data = parser.parseMisskeyApShow(jsonObject) targetStatus = parser.parseMisskeyApShow(jsonObject) as? TootStatus
if(data == null && error == null) { if(targetStatus == null && error == null) {
setError(context.getString(R.string.cant_sync_toot)) setError(context.getString(R.string.cant_sync_toot))
} }
} }
} else { } else {
request("/api/v1/search?q=${url.encodePercent()}&resolve=true") request("/api/v1/search?q=${url.encodePercent()}&resolve=true")
?.apply { ?.apply {
data = parser.results(jsonObject)?.statuses?.firstOrNull() targetStatus = parser.results(jsonObject)?.statuses?.firstOrNull()
if(data == null && error == null) { if(targetStatus == null && error == null) {
setError(context.getString(R.string.cant_sync_toot)) setError(context.getString(R.string.cant_sync_toot))
} }
} }
} }
return Pair(result,targetStatus)
} }
fun TootApiClient.syncStatus( fun TootApiClient.syncStatus(
accessInfo : SavedAccount, accessInfo : SavedAccount,
statusRemote : TootStatus statusRemote : TootStatus
) : TootApiResult? { ) : Pair<TootApiResult?,TootStatus?> {
// URL->URIの順に試す // URL->URIの順に試す
@ -1592,11 +1600,11 @@ fun TootApiClient.syncStatus(
} }
for(uri in uriList) { for(uri in uriList) {
val result = syncStatus(accessInfo, uri) val pair = syncStatus(accessInfo, uri)
if(result == null || result.data is TootStatus) { if( pair.second != null || pair.first == null ) {
return result return pair
} }
} }
return TootApiResult("can't resolve status URL/URI.") return Pair(TootApiResult("can't resolve status URL/URI."),null)
} }

View File

@ -90,18 +90,15 @@ class DlgFocusPoint(val activity : Activity, val attachment : TootAttachment) :
var bitmap : Bitmap? = null var bitmap : Bitmap? = null
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
val result = client.getHttpBytes(url)
try { try {
val data = result?.data as? ByteArray ?: return result val(result,data) = client.getHttpBytes(url)
data ?: return result
bitmap = decodeBitmap(data, 1024) bitmap = decodeBitmap(data, 1024)
if(bitmap == null) return TootApiResult("image decode failed.") if(bitmap == null) return TootApiResult("image decode failed.")
return result
} catch(ex : Throwable) { } catch(ex : Throwable) {
return TootApiResult(ex.withCaption("preview loading failed.")) return TootApiResult(ex.withCaption("preview loading failed."))
} }
return result
} }
override fun handleResult(result : TootApiResult?) { override fun handleResult(result : TootApiResult?) {

View File

@ -175,8 +175,8 @@ class DlgListMember(
override fun background(client : TootApiClient) : TootApiResult? { override fun background(client : TootApiClient) : TootApiResult? {
// リストに追加したいアカウントの自タンスでのアカウントIDを取得する // リストに追加したいアカウントの自タンスでのアカウントIDを取得する
var result = client.syncAccountByAcct(list_owner,target_user_full_acct) var (result,ar) = client.syncAccountByAcct(list_owner,target_user_full_acct)
val local_who = (result?.data as? TootAccountRef)?.get() val local_who = ar?.get()
?: return TootApiResult(activity.getString(R.string.account_sync_failed)) ?: return TootApiResult(activity.getString(R.string.account_sync_failed))
this@DlgListMember.local_who = local_who this@DlgListMember.local_who = local_who

View File

@ -231,8 +231,8 @@ class PushSubscriptionHelper(
if(oldSubscription == null) { if(oldSubscription == null) {
// 現在の購読状況が分からない場合はインスタンスのバージョンを調べる必要がある // 現在の購読状況が分からない場合はインスタンスのバージョンを調べる必要がある
r = client.parseInstanceInformation(client.getInstanceInformation()) val(result,ti) = client.parseInstanceInformation(client.getInstanceInformation())
val ti = r?.data as? TootInstance ?: return r ti ?: return result
if(! ti.versionGE(TootInstance.VERSION_2_4_0_rc1)) { if(! ti.versionGE(TootInstance.VERSION_2_4_0_rc1)) {
// 2.4.0rc1 未満にはプッシュ購読APIはない // 2.4.0rc1 未満にはプッシュ購読APIはない