試験機能:misskeyのタンスを疑似アカウントで追加して、ローカルTLとグローバルTLを見れる
This commit is contained in:
parent
b58552c990
commit
7ceb9e4f51
|
@ -101,7 +101,8 @@ class App1 : Application() {
|
||||||
// 2018/5/16 v252 24=>25 SubscriptionServerKey テーブルを追加
|
// 2018/5/16 v252 24=>25 SubscriptionServerKey テーブルを追加
|
||||||
// 2018/5/16 v252 25=>26 SubscriptionServerKey テーブルを丸ごと変更
|
// 2018/5/16 v252 25=>26 SubscriptionServerKey テーブルを丸ごと変更
|
||||||
// 2018/8/5 v264 26 => 27 SavedAccountテーブルに項目追加
|
// 2018/8/5 v264 26 => 27 SavedAccountテーブルに項目追加
|
||||||
internal const val DB_VERSION = 27
|
// 2018/8/17 v267 27 => 28 SavedAccountテーブルに項目追加
|
||||||
|
internal const val DB_VERSION = 28
|
||||||
|
|
||||||
private val tableList = arrayOf(
|
private val tableList = arrayOf(
|
||||||
LogData,
|
LogData,
|
||||||
|
|
|
@ -7,19 +7,17 @@ import android.os.AsyncTask
|
||||||
import android.os.SystemClock
|
import android.os.SystemClock
|
||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import jp.juggler.subwaytooter.api.*
|
import jp.juggler.subwaytooter.api.*
|
||||||
|
|
||||||
import org.json.JSONException
|
|
||||||
import org.json.JSONObject
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
|
||||||
import java.util.regex.Pattern
|
|
||||||
|
|
||||||
import jp.juggler.subwaytooter.api.entity.*
|
import jp.juggler.subwaytooter.api.entity.*
|
||||||
import jp.juggler.subwaytooter.table.*
|
import jp.juggler.subwaytooter.table.*
|
||||||
import jp.juggler.subwaytooter.util.*
|
import jp.juggler.subwaytooter.util.*
|
||||||
|
import org.json.JSONArray
|
||||||
|
import org.json.JSONException
|
||||||
|
import org.json.JSONObject
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
enum class StreamingIndicatorState {
|
enum class StreamingIndicatorState {
|
||||||
NONE,
|
NONE,
|
||||||
|
@ -309,6 +307,9 @@ class Column(
|
||||||
|
|
||||||
private val streamPath : String?
|
private val streamPath : String?
|
||||||
get() {
|
get() {
|
||||||
|
// misskeyの疑似アカウントはストリーミング対応していない
|
||||||
|
if(access_info.isPseudo && access_info.isMisskey) return null
|
||||||
|
|
||||||
return when(column_type) {
|
return when(column_type) {
|
||||||
TYPE_HOME, TYPE_NOTIFICATIONS -> "/api/v1/streaming/?stream=user"
|
TYPE_HOME, TYPE_NOTIFICATIONS -> "/api/v1/streaming/?stream=user"
|
||||||
TYPE_LOCAL -> "/api/v1/streaming/?stream=public:local"
|
TYPE_LOCAL -> "/api/v1/streaming/?stream=public:local"
|
||||||
|
@ -320,7 +321,7 @@ class Column(
|
||||||
TYPE_HASHTAG -> when(instance_local) {
|
TYPE_HASHTAG -> when(instance_local) {
|
||||||
true -> "/api/v1/streaming/?stream=" + Uri.encode("hashtag:local") + "&tag=" + hashtag.encodePercent()
|
true -> "/api/v1/streaming/?stream=" + Uri.encode("hashtag:local") + "&tag=" + hashtag.encodePercent()
|
||||||
else -> "/api/v1/streaming/?stream=hashtag&tag=" + hashtag.encodePercent()
|
else -> "/api/v1/streaming/?stream=hashtag&tag=" + hashtag.encodePercent()
|
||||||
// タグ先頭の#を含まない
|
// タグ先頭の#を含まない
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
@ -816,7 +817,7 @@ class Column(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeUser(targetAccount : SavedAccount,columnType:Int,who_id:Long){
|
fun removeUser(targetAccount : SavedAccount, columnType : Int, who_id : Long) {
|
||||||
if(column_type == columnType && targetAccount.acct == access_info.acct) {
|
if(column_type == columnType && targetAccount.acct == access_info.acct) {
|
||||||
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
val tmp_list = ArrayList<TimelineItem>(list_data.size)
|
||||||
for(o in list_data) {
|
for(o in list_data) {
|
||||||
|
@ -1502,13 +1503,36 @@ class Column(
|
||||||
log.d("getStatusesPinned: list size=%s", list_pinned?.size ?: - 1)
|
log.d("getStatusesPinned: list size=%s", list_pinned?.size ?: - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getStatuses(client : TootApiClient, path_base : String) : TootApiResult? {
|
fun getStatuses(
|
||||||
|
client : TootApiClient,
|
||||||
|
path_base : String,
|
||||||
|
isMisskey : Boolean = false
|
||||||
|
) : TootApiResult? {
|
||||||
|
|
||||||
|
val params = JSONObject()
|
||||||
|
if(isMisskey) {
|
||||||
|
parser.serviceType = ServiceType.MISSKEY
|
||||||
|
params.put("limit", 100)
|
||||||
|
if(with_attachment) {
|
||||||
|
params.put("mediaOnly", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
val result = client.request(path_base)
|
val result = if(isMisskey) {
|
||||||
|
client.request(path_base, params.toPostRequestBuilder())
|
||||||
|
} else {
|
||||||
|
client.request(path_base)
|
||||||
|
}
|
||||||
|
|
||||||
var jsonArray = result?.jsonArray
|
var jsonArray = result?.jsonArray
|
||||||
if(jsonArray != null) {
|
if(jsonArray != null) {
|
||||||
saveRange(result, true, true)
|
if(isMisskey) {
|
||||||
|
saveRangeMisskey(jsonArray, true, true)
|
||||||
|
} else {
|
||||||
|
saveRange(result, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
var src = parser.statusList(jsonArray)
|
var src = parser.statusList(jsonArray)
|
||||||
|
|
||||||
|
@ -1540,9 +1564,16 @@ class Column(
|
||||||
log.d("loading-statuses: timeout.")
|
log.d("loading-statuses: timeout.")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
val path = path_base + delimiter + "max_id=" + max_id
|
val result2 = if(isMisskey) {
|
||||||
val result2 = client.request(path)
|
params.put("untilId", max_id)
|
||||||
|
client.request(path_base, params.toPostRequestBuilder())
|
||||||
|
} else {
|
||||||
|
val path = path_base + delimiter + "max_id=" + max_id
|
||||||
|
client.request(path)
|
||||||
|
}
|
||||||
|
|
||||||
jsonArray = result2?.jsonArray
|
jsonArray = result2?.jsonArray
|
||||||
|
|
||||||
if(jsonArray == null) {
|
if(jsonArray == null) {
|
||||||
log.d("loading-statuses: error or cancelled.")
|
log.d("loading-statuses: error or cancelled.")
|
||||||
break
|
break
|
||||||
|
@ -1552,9 +1583,16 @@ class Column(
|
||||||
|
|
||||||
addWithFilterStatus(list_tmp, src)
|
addWithFilterStatus(list_tmp, src)
|
||||||
|
|
||||||
if(! saveRangeEnd(result2)) {
|
if(isMisskey) {
|
||||||
log.d("loading-statuses: missing range info.")
|
if(! saveRangeEndMisskey(jsonArray)) {
|
||||||
break
|
log.d("loading-statuses: missing range info.")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(! saveRangeEnd(result2)) {
|
||||||
|
log.d("loading-statuses: missing range info.")
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1748,9 +1786,22 @@ class Column(
|
||||||
|
|
||||||
TYPE_DIRECT_MESSAGES -> return getStatuses(client, PATH_DIRECT_MESSAGES)
|
TYPE_DIRECT_MESSAGES -> return getStatuses(client, PATH_DIRECT_MESSAGES)
|
||||||
|
|
||||||
TYPE_LOCAL -> return getStatuses(client, makePublicLocalUrl())
|
TYPE_LOCAL -> return when(access_info.isMisskey) {
|
||||||
|
true -> getStatuses(
|
||||||
TYPE_FEDERATE -> return getStatuses(client, makePublicFederateUrl())
|
client,
|
||||||
|
"/api/notes/local-timeline",
|
||||||
|
isMisskey = true
|
||||||
|
)
|
||||||
|
else -> getStatuses(client, makePublicLocalUrl())
|
||||||
|
}
|
||||||
|
TYPE_FEDERATE -> return when(access_info.isMisskey) {
|
||||||
|
true -> getStatuses(
|
||||||
|
client,
|
||||||
|
"/api/notes/global-timeline",
|
||||||
|
isMisskey = true
|
||||||
|
)
|
||||||
|
else -> return getStatuses(client, makePublicFederateUrl())
|
||||||
|
}
|
||||||
|
|
||||||
TYPE_PROFILE -> {
|
TYPE_PROFILE -> {
|
||||||
|
|
||||||
|
@ -1903,7 +1954,10 @@ class Column(
|
||||||
//
|
//
|
||||||
} else {
|
} else {
|
||||||
this.list_tmp = addOne(this.list_tmp, target_status)
|
this.list_tmp = addOne(this.list_tmp, target_status)
|
||||||
this.list_tmp = addOne(this.list_tmp, TootMessageHolder(context.getString(R.string.toot_context_parse_failed)))
|
this.list_tmp = addOne(
|
||||||
|
this.list_tmp,
|
||||||
|
TootMessageHolder(context.getString(R.string.toot_context_parse_failed))
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// カードを取得する
|
// カードを取得する
|
||||||
|
@ -2132,6 +2186,31 @@ class Column(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveRangeMisskey(src : JSONArray?, bBottom : Boolean, bTop : Boolean) {
|
||||||
|
src ?: return
|
||||||
|
var id_min : String? = null
|
||||||
|
var id_max : String? = null
|
||||||
|
for(i in 0 until src.length()) {
|
||||||
|
val id = src.optJSONObject(i)?.optString("id", null) ?: continue
|
||||||
|
if(id_min == null || id < id_min) id_min = id
|
||||||
|
if(id_max == null || id > id_max) id_max = id
|
||||||
|
}
|
||||||
|
if(bBottom) {
|
||||||
|
when {
|
||||||
|
id_min == null -> max_id = ""
|
||||||
|
max_id.isEmpty() || id_min < max_id -> max_id = id_min
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(bTop) {
|
||||||
|
when {
|
||||||
|
id_max == null -> {
|
||||||
|
}
|
||||||
|
|
||||||
|
since_id.isEmpty() || id_max > since_id -> since_id = id_max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun saveRangeEnd(result : TootApiResult?) : Boolean {
|
private fun saveRangeEnd(result : TootApiResult?) : Boolean {
|
||||||
if(result != null) {
|
if(result != null) {
|
||||||
if(result.link_older == null) {
|
if(result.link_older == null) {
|
||||||
|
@ -2147,6 +2226,23 @@ class Column(
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun saveRangeEndMisskey(src : JSONArray?) : Boolean {
|
||||||
|
if(src != null) {
|
||||||
|
var id_min : String? = null
|
||||||
|
for(i in 0 until src.length()) {
|
||||||
|
val id = src.optJSONObject(i)?.optString("id", null) ?: continue
|
||||||
|
if(id_min == null || id < id_min) id_min = id
|
||||||
|
}
|
||||||
|
if(id_min?.isEmpty() != false) {
|
||||||
|
max_id = ""
|
||||||
|
} else {
|
||||||
|
max_id = id_min
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
private fun addRange(bBottom : Boolean, path : String) : String {
|
private fun addRange(bBottom : Boolean, path : String) : String {
|
||||||
val delimiter = if(- 1 != path.indexOf('?')) '&' else '?'
|
val delimiter = if(- 1 != path.indexOf('?')) '&' else '?'
|
||||||
if(bBottom) {
|
if(bBottom) {
|
||||||
|
@ -2610,18 +2706,43 @@ class Column(
|
||||||
|
|
||||||
fun getStatusList(
|
fun getStatusList(
|
||||||
client : TootApiClient,
|
client : TootApiClient,
|
||||||
path_base : String
|
path_base : String,
|
||||||
|
isMisskey : Boolean = false
|
||||||
) : TootApiResult? {
|
) : TootApiResult? {
|
||||||
|
|
||||||
|
val params = JSONObject()
|
||||||
|
if(isMisskey) {
|
||||||
|
parser.serviceType = ServiceType.MISSKEY
|
||||||
|
params.put("limit", 100)
|
||||||
|
if(with_attachment) {
|
||||||
|
params.put("mediaOnly", true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val time_start = SystemClock.elapsedRealtime()
|
val time_start = SystemClock.elapsedRealtime()
|
||||||
|
|
||||||
val delimiter = if(- 1 != path_base.indexOf('?')) '&' else '?'
|
val delimiter = if(- 1 != path_base.indexOf('?')) '&' else '?'
|
||||||
val last_since_id = since_id
|
val last_since_id = since_id
|
||||||
|
|
||||||
val result = client.request(addRange(bBottom, path_base))
|
val result = if(isMisskey) {
|
||||||
|
if(bBottom) {
|
||||||
|
if(max_id.isNotEmpty()) params.put("untilId", max_id)
|
||||||
|
} else {
|
||||||
|
if(since_id.isNotEmpty()) params.put("sinceId", since_id)
|
||||||
|
}
|
||||||
|
client.request(path_base, params.toPostRequestBuilder())
|
||||||
|
} else {
|
||||||
|
client.request(addRange(bBottom, path_base))
|
||||||
|
}
|
||||||
|
|
||||||
var jsonArray = result?.jsonArray
|
var jsonArray = result?.jsonArray
|
||||||
if(jsonArray != null) {
|
if(jsonArray != null) {
|
||||||
saveRange(result, bBottom, ! bBottom)
|
if(isMisskey) {
|
||||||
|
saveRangeMisskey(jsonArray, bBottom, ! bBottom)
|
||||||
|
} else {
|
||||||
|
saveRange(result, bBottom, ! bBottom)
|
||||||
|
}
|
||||||
|
|
||||||
var src = parser.statusList(jsonArray)
|
var src = parser.statusList(jsonArray)
|
||||||
list_tmp = addWithFilterStatus(null, src)
|
list_tmp = addWithFilterStatus(null, src)
|
||||||
|
|
||||||
|
@ -2657,8 +2778,14 @@ class Column(
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
val path = path_base + delimiter + "max_id=" + max_id
|
val result2 = if(isMisskey) {
|
||||||
val result2 = client.request(path)
|
params.put("untilId", max_id)
|
||||||
|
client.request(path_base, params.toPostRequestBuilder())
|
||||||
|
} else {
|
||||||
|
val path = path_base + delimiter + "max_id=" + max_id
|
||||||
|
client.request(path)
|
||||||
|
}
|
||||||
|
|
||||||
jsonArray = result2?.jsonArray
|
jsonArray = result2?.jsonArray
|
||||||
if(jsonArray == null) {
|
if(jsonArray == null) {
|
||||||
log.d("refresh-status-bottom: error or cancelled.")
|
log.d("refresh-status-bottom: error or cancelled.")
|
||||||
|
@ -2669,9 +2796,16 @@ class Column(
|
||||||
|
|
||||||
addWithFilterStatus(list_tmp, src)
|
addWithFilterStatus(list_tmp, src)
|
||||||
|
|
||||||
if(! saveRangeEnd(result2)) {
|
if(isMisskey) {
|
||||||
log.d("refresh-status-bottom: saveRangeEnd failed.")
|
if(! saveRangeEndMisskey(jsonArray)) {
|
||||||
break
|
log.d("refresh-status-bottom: saveRangeEnd failed.")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(! saveRangeEnd(result2)) {
|
||||||
|
log.d("refresh-status-bottom: saveRangeEnd failed.")
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2711,6 +2845,13 @@ class Column(
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(isMisskey) {
|
||||||
|
log.d("refresh-status-offset: misskey does not allows gap reading.")
|
||||||
|
addOne(list_tmp, TootGap(max_id, last_since_id))
|
||||||
|
bGapAdded = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
val path =
|
val path =
|
||||||
path_base + delimiter + "max_id=" + max_id + "&since_id=" + last_since_id
|
path_base + delimiter + "max_id=" + max_id + "&since_id=" + last_since_id
|
||||||
val result2 = client.request(path)
|
val result2 = client.request(path)
|
||||||
|
@ -2767,9 +2908,23 @@ class Column(
|
||||||
|
|
||||||
TYPE_DIRECT_MESSAGES -> getStatusList(client, PATH_DIRECT_MESSAGES)
|
TYPE_DIRECT_MESSAGES -> getStatusList(client, PATH_DIRECT_MESSAGES)
|
||||||
|
|
||||||
TYPE_LOCAL -> getStatusList(client, makePublicLocalUrl())
|
TYPE_LOCAL -> when(access_info.isMisskey) {
|
||||||
|
true -> getStatusList(
|
||||||
|
client,
|
||||||
|
"/api/notes/local-timeline",
|
||||||
|
isMisskey = true
|
||||||
|
)
|
||||||
|
else -> getStatusList(client, makePublicLocalUrl())
|
||||||
|
}
|
||||||
|
|
||||||
TYPE_FEDERATE -> getStatusList(client, makePublicFederateUrl())
|
TYPE_FEDERATE -> when(access_info.isMisskey) {
|
||||||
|
true -> getStatusList(
|
||||||
|
client,
|
||||||
|
"/api/notes/global-timeline",
|
||||||
|
isMisskey = true
|
||||||
|
)
|
||||||
|
else -> getStatusList(client, makePublicFederateUrl())
|
||||||
|
}
|
||||||
|
|
||||||
TYPE_FAVOURITES -> getStatusList(client, PATH_FAVOURITES)
|
TYPE_FAVOURITES -> getStatusList(client, PATH_FAVOURITES)
|
||||||
|
|
||||||
|
@ -3015,15 +3170,15 @@ class Column(
|
||||||
//
|
//
|
||||||
val scroll_save = this@Column.scroll_save
|
val scroll_save = this@Column.scroll_save
|
||||||
when {
|
when {
|
||||||
// ViewHolderがある場合は増加件数分+deltaの位置にスクロールする
|
// ViewHolderがある場合は増加件数分+deltaの位置にスクロールする
|
||||||
sp != null -> {
|
sp != null -> {
|
||||||
sp.adapterIndex += added
|
sp.adapterIndex += added
|
||||||
val delta = if(bSilent) 0f else - 20f
|
val delta = if(bSilent) 0f else - 20f
|
||||||
holder?.setScrollPosition(sp, delta)
|
holder?.setScrollPosition(sp, delta)
|
||||||
}
|
}
|
||||||
// ViewHolderがなくて保存中の位置がある場合、増加件数分ずらす。deltaは難しいので反映しない
|
// ViewHolderがなくて保存中の位置がある場合、増加件数分ずらす。deltaは難しいので反映しない
|
||||||
scroll_save != null -> scroll_save.adapterIndex += added
|
scroll_save != null -> scroll_save.adapterIndex += added
|
||||||
// 保存中の位置がない場合、保存中の位置を新しく作る
|
// 保存中の位置がない場合、保存中の位置を新しく作る
|
||||||
else -> this@Column.scroll_save =
|
else -> this@Column.scroll_save =
|
||||||
ScrollPosition(toAdapterIndex(added), 0)
|
ScrollPosition(toAdapterIndex(added), 0)
|
||||||
}
|
}
|
||||||
|
@ -3054,6 +3209,8 @@ class Column(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
viewHolder?.refreshLayout?.isRefreshing = true
|
viewHolder?.refreshLayout?.isRefreshing = true
|
||||||
|
|
||||||
bRefreshLoading = true
|
bRefreshLoading = true
|
||||||
|
@ -3557,9 +3714,9 @@ class Column(
|
||||||
log.d("onStart: column is in initial loading.")
|
log.d("onStart: column is in initial loading.")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// フィルタ一覧のリロードが必要
|
// フィルタ一覧のリロードが必要
|
||||||
if( filter_reload_required ){
|
if(filter_reload_required) {
|
||||||
filter_reload_required = false
|
filter_reload_required = false
|
||||||
startLoading()
|
startLoading()
|
||||||
return
|
return
|
||||||
|
@ -3659,8 +3816,11 @@ class Column(
|
||||||
return canStreaming() && column_type != TYPE_NOTIFICATIONS
|
return canStreaming() && column_type != TYPE_NOTIFICATIONS
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun canStreaming() : Boolean {
|
internal fun canStreaming() = when {
|
||||||
return ! access_info.isNA && if(access_info.isPseudo) isPublicStream else streamPath != null
|
access_info.isNA -> false
|
||||||
|
access_info.isMisskey -> false
|
||||||
|
access_info.isPseudo -> isPublicStream
|
||||||
|
else -> streamPath != null
|
||||||
}
|
}
|
||||||
|
|
||||||
private val streamCallback = object : StreamReader.StreamCallback {
|
private val streamCallback = object : StreamReader.StreamCallback {
|
||||||
|
@ -3918,6 +4078,7 @@ class Column(
|
||||||
} else {
|
} else {
|
||||||
PATH_LOCAL
|
PATH_LOCAL
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun makePublicFederateUrl() : String {
|
private fun makePublicFederateUrl() : String {
|
||||||
|
@ -3940,7 +4101,7 @@ class Column(
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadFilter2(client : TootApiClient) : ArrayList<TootFilter>? {
|
private fun loadFilter2(client : TootApiClient) : ArrayList<TootFilter>? {
|
||||||
if( access_info.isPseudo ) return null
|
if(access_info.isPseudo) return null
|
||||||
val column_context = getFilterContext()
|
val column_context = getFilterContext()
|
||||||
if(column_context == 0) return null
|
if(column_context == 0) return null
|
||||||
val result = client.request(PATH_FILTERS)
|
val result = client.request(PATH_FILTERS)
|
||||||
|
@ -3955,10 +4116,12 @@ class Column(
|
||||||
val tree = WordTrieTree()
|
val tree = WordTrieTree()
|
||||||
for(filter in filterList) {
|
for(filter in filterList) {
|
||||||
if((filter.context and column_context) != 0) {
|
if((filter.context and column_context) != 0) {
|
||||||
tree.add(filter.phrase,validator = when(filter.whole_word){
|
tree.add(
|
||||||
true -> WordTrieTree.WORD_VALIDATOR
|
filter.phrase, validator = when(filter.whole_word) {
|
||||||
|
true -> WordTrieTree.WORD_VALIDATOR
|
||||||
else -> WordTrieTree.EMPTY_VALIDATOR
|
else -> WordTrieTree.EMPTY_VALIDATOR
|
||||||
})
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tree
|
return tree
|
||||||
|
@ -4023,5 +4186,4 @@ class Column(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1028,7 +1028,13 @@ internal class ItemViewHolder(
|
||||||
}
|
}
|
||||||
|
|
||||||
btnSearchTag, llTrendTag -> when(item) {
|
btnSearchTag, llTrendTag -> when(item) {
|
||||||
is TootGap -> column.startGap(item)
|
is TootGap -> {
|
||||||
|
if( access_info.isMisskey){
|
||||||
|
showToast(activity,false, "Misskey does not allows gap reading.")
|
||||||
|
}else {
|
||||||
|
column.startGap(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
is TootDomainBlock -> {
|
is TootDomainBlock -> {
|
||||||
val domain = item.domain
|
val domain = item.domain
|
||||||
|
|
|
@ -25,7 +25,7 @@ internal fun findAccountByName(
|
||||||
) {
|
) {
|
||||||
TootTaskRunner(activity).run(access_info, object : TootTask {
|
TootTaskRunner(activity).run(access_info, object : TootTask {
|
||||||
|
|
||||||
internal var who : TootAccount? = null
|
var who : TootAccount? = null
|
||||||
|
|
||||||
override fun background(client : TootApiClient) : TootApiResult? {
|
override fun background(client : TootApiClient) : TootApiResult? {
|
||||||
|
|
||||||
|
@ -38,10 +38,9 @@ internal fun findAccountByName(
|
||||||
for(i in 0 until array.length()) {
|
for(i in 0 until array.length()) {
|
||||||
val a = parser.account(array.optJSONObject(i))
|
val a = parser.account(array.optJSONObject(i))
|
||||||
if(a != null) {
|
if(a != null) {
|
||||||
if(a.username == user && access_info.getFullAcct(a).equals(
|
if(a.username == user
|
||||||
user + "@" + host,
|
&& access_info.getFullAcct(a).equals("$user@$host", ignoreCase = true)
|
||||||
ignoreCase = true
|
) {
|
||||||
)) {
|
|
||||||
who = a
|
who = a
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -62,11 +61,14 @@ internal fun findAccountByName(
|
||||||
// 既に存在する場合は再利用する
|
// 既に存在する場合は再利用する
|
||||||
// 実アカウントを返すことはない
|
// 実アカウントを返すことはない
|
||||||
internal fun addPseudoAccount(
|
internal fun addPseudoAccount(
|
||||||
context : Context, host : String
|
context : Context,
|
||||||
|
host : String,
|
||||||
|
isMisskey : Boolean = false
|
||||||
) : SavedAccount? {
|
) : SavedAccount? {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val username = "?"
|
val username = "?"
|
||||||
val full_acct = username + "@" + host
|
val full_acct = "$username@$host"
|
||||||
|
|
||||||
var account = SavedAccount.loadAccountByAcct(context, full_acct)
|
var account = SavedAccount.loadAccountByAcct(context, full_acct)
|
||||||
if(account != null) {
|
if(account != null) {
|
||||||
|
@ -77,7 +79,8 @@ internal fun addPseudoAccount(
|
||||||
account_info.put("username", username)
|
account_info.put("username", username)
|
||||||
account_info.put("acct", username)
|
account_info.put("acct", username)
|
||||||
|
|
||||||
val row_id = SavedAccount.insert(host, full_acct, account_info, JSONObject())
|
val row_id =
|
||||||
|
SavedAccount.insert(host, full_acct, account_info, JSONObject(), isMisskey = isMisskey)
|
||||||
account = SavedAccount.loadAccount(context, row_id)
|
account = SavedAccount.loadAccount(context, row_id)
|
||||||
if(account == null) {
|
if(account == null) {
|
||||||
throw RuntimeException("loadAccount returns null.")
|
throw RuntimeException("loadAccount returns null.")
|
||||||
|
@ -132,7 +135,7 @@ internal fun loadRelation1(
|
||||||
client : TootApiClient, access_info : SavedAccount, who_id : Long
|
client : TootApiClient, access_info : SavedAccount, who_id : Long
|
||||||
) : RelationResult {
|
) : RelationResult {
|
||||||
val rr = RelationResult()
|
val rr = RelationResult()
|
||||||
rr.result = client.request("/api/v1/accounts/relationships?id=" + who_id)
|
rr.result = client.request("/api/v1/accounts/relationships?id=$who_id")
|
||||||
val r2 = rr.result
|
val r2 = rr.result
|
||||||
val jsonArray = r2?.jsonArray
|
val jsonArray = r2?.jsonArray
|
||||||
if(jsonArray != null) {
|
if(jsonArray != null) {
|
||||||
|
|
|
@ -95,7 +95,7 @@ object Action_Account {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// 疑似アカウントを追加
|
// 疑似アカウントを追加
|
||||||
val a = addPseudoAccount(activity, instance)
|
val a = addPseudoAccount(activity, instance, data.optBoolean("isMisskey",false))
|
||||||
if(a != null) {
|
if(a != null) {
|
||||||
showToast(activity, false, R.string.server_confirmed)
|
showToast(activity, false, R.string.server_confirmed)
|
||||||
val pos = App1.getAppState(activity).column_list.size
|
val pos = App1.getAppState(activity).column_list.size
|
||||||
|
|
|
@ -18,6 +18,7 @@ object TootAccountMap{
|
||||||
ServiceType.MASTODON -> requireNotNull(parser.linkHelper.host)
|
ServiceType.MASTODON -> requireNotNull(parser.linkHelper.host)
|
||||||
ServiceType.TOOTSEARCH -> "?tootsearch"
|
ServiceType.TOOTSEARCH -> "?tootsearch"
|
||||||
ServiceType.MSP -> "?msp"
|
ServiceType.MSP -> "?msp"
|
||||||
|
ServiceType.MISSKEY -> "?misskey"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -445,10 +445,36 @@ class TootApiClient(
|
||||||
fun getInstanceInformation() : TootApiResult? {
|
fun getInstanceInformation() : TootApiResult? {
|
||||||
val result = TootApiResult.makeWithCaption(instance)
|
val result = TootApiResult.makeWithCaption(instance)
|
||||||
if(result.error != null) return result
|
if(result.error != null) return result
|
||||||
if(! sendRequest(result) {
|
|
||||||
|
if(sendRequest(result) {
|
||||||
Request.Builder().url("https://$instance/api/v1/instance").build()
|
Request.Builder().url("https://$instance/api/v1/instance").build()
|
||||||
}) return result
|
}
|
||||||
return parseJson(result)
|
&& parseJson(result) != null
|
||||||
|
&& result.jsonObject != null
|
||||||
|
) {
|
||||||
|
// インスタンス情報のjsonを読めたらマストドンのインスタンス
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// misskeyか試してみる
|
||||||
|
val r2 = TootApiResult.makeWithCaption(instance)
|
||||||
|
if(sendRequest(r2) {
|
||||||
|
Request.Builder().post(RequestBody.create(MEDIA_TYPE_JSON,JSONObject().apply{
|
||||||
|
put("dummy",1)
|
||||||
|
}.toString()))
|
||||||
|
.url("https://$instance/api/notes/local-timeline").build()
|
||||||
|
}
|
||||||
|
) {
|
||||||
|
if(parseJson(r2) != null && r2.jsonArray != null) {
|
||||||
|
r2.data = JSONObject().apply{
|
||||||
|
put("isMisskey", true)
|
||||||
|
}
|
||||||
|
return r2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// misskeyの事は忘れて本来のエラー情報を返す
|
||||||
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
// インスタンス情報を取得する
|
// インスタンス情報を取得する
|
||||||
|
@ -845,7 +871,7 @@ class TootApiClient(
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// JSONデータ以外を扱うリクエスト
|
// JSONデータ以外を扱うリクエスト
|
||||||
|
|
||||||
fun http(req:Request) : TootApiResult? {
|
fun http(req : Request) : TootApiResult? {
|
||||||
val result = TootApiResult.makeWithCaption(req.url().host())
|
val result = TootApiResult.makeWithCaption(req.url().host())
|
||||||
if(result.error != null) return result
|
if(result.error != null) return result
|
||||||
|
|
||||||
|
@ -853,20 +879,19 @@ class TootApiClient(
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
fun requestJson(req:Request) : TootApiResult? {
|
fun requestJson(req : Request) : TootApiResult? {
|
||||||
val result = TootApiResult.makeWithCaption(req.url().host())
|
val result = TootApiResult.makeWithCaption(req.url().host())
|
||||||
if(result.error != null) return result
|
if(result.error != null) return result
|
||||||
if( sendRequest(result, progressPath = null) { req } ){
|
if(sendRequest(result, progressPath = null) { req }) {
|
||||||
parseJson(result)
|
parseJson(result)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// 疑似アカウントでステータスURLからステータスIDを取得するためにHTMLを取得する
|
// 疑似アカウントでステータスURLからステータスIDを取得するためにHTMLを取得する
|
||||||
fun getHttp(url:String): TootApiResult? {
|
fun getHttp(url : String) : TootApiResult? {
|
||||||
val result = http(Request.Builder().url(url).build())
|
val result = http(Request.Builder().url(url).build())
|
||||||
if(result !=null && result.error == null){
|
if(result != null && result.error == null) {
|
||||||
parseString(result)
|
parseString(result)
|
||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
|
|
|
@ -4,4 +4,5 @@ enum class ServiceType {
|
||||||
MASTODON,
|
MASTODON,
|
||||||
TOOTSEARCH,
|
TOOTSEARCH,
|
||||||
MSP,
|
MSP,
|
||||||
|
MISSKEY,
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,106 +90,155 @@ open class TootAccount(
|
||||||
init {
|
init {
|
||||||
var sv : String?
|
var sv : String?
|
||||||
|
|
||||||
// 絵文字データは先に読んでおく
|
if(parser.serviceType == ServiceType.MISSKEY) {
|
||||||
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"))
|
|
||||||
this.profile_emojis = parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"))
|
|
||||||
|
|
||||||
// 疑似アカウントにacctとusernameだけ
|
|
||||||
this.url = src.parseString("url")
|
|
||||||
this.username = src.notEmptyOrThrow("username")
|
|
||||||
|
|
||||||
//
|
|
||||||
sv = src.parseString("display_name")
|
|
||||||
this.display_name = if(sv?.isNotEmpty() == true) sv.sanitizeBDI() else username
|
|
||||||
|
|
||||||
//
|
|
||||||
this.note = src.parseString("note")
|
|
||||||
|
|
||||||
this.source = parseSource(src.optJSONObject("source"))
|
|
||||||
this.movedRef = TootAccountRef.mayNull(
|
|
||||||
parser,
|
|
||||||
src.optJSONObject("moved")?.let {
|
|
||||||
TootAccount(parser, it)
|
|
||||||
}
|
|
||||||
)
|
|
||||||
this.locked = src.optBoolean("locked")
|
|
||||||
|
|
||||||
this.fields = parseFields(src.optJSONArray("fields"))
|
|
||||||
|
|
||||||
this.bot = src.optBoolean("bot", false)
|
|
||||||
|
|
||||||
// this.user_hides_network = src.optBoolean("user_hides_network")
|
|
||||||
|
|
||||||
when(parser.serviceType) {
|
|
||||||
ServiceType.MASTODON -> {
|
|
||||||
|
|
||||||
val hostAccess = parser.linkHelper.host
|
|
||||||
|
|
||||||
this.id = src.parseLong("id") ?: INVALID_ID
|
|
||||||
|
|
||||||
this.acct = src.notEmptyOrThrow("acct")
|
|
||||||
this.host = findHostFromUrl(acct, hostAccess, url)
|
|
||||||
?: throw RuntimeException("can't get host from acct or url")
|
|
||||||
|
|
||||||
this.followers_count = src.parseLong("followers_count")
|
|
||||||
this.following_count = src.parseLong("following_count")
|
|
||||||
this.statuses_count = src.parseLong("statuses_count")
|
|
||||||
|
|
||||||
this.created_at = src.parseString("created_at")
|
|
||||||
this.time_created_at = TootStatus.parseTime(this.created_at)
|
|
||||||
|
|
||||||
this.avatar = src.parseString("avatar")
|
|
||||||
this.avatar_static = src.parseString("avatar_static")
|
|
||||||
this.header = src.parseString("header")
|
|
||||||
this.header_static = src.parseString("header_static")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceType.TOOTSEARCH -> {
|
val instance = src.parseString("host") ?: parser.linkHelper.host ?: error("missing host")
|
||||||
// tootsearch のアカウントのIDはどのタンス上のものか分からないので役に立たない
|
|
||||||
this.id = INVALID_ID // src.parseLong( "id", INVALID_ID)
|
|
||||||
|
|
||||||
sv = src.notEmptyOrThrow("acct")
|
|
||||||
this.host = findHostFromUrl(sv, null, url)
|
|
||||||
?: throw RuntimeException("can't get host from acct or url")
|
|
||||||
this.acct = this.username + "@" + this.host
|
|
||||||
|
|
||||||
this.followers_count = src.parseLong("followers_count")
|
|
||||||
this.following_count = src.parseLong("following_count")
|
|
||||||
this.statuses_count = src.parseLong("statuses_count")
|
|
||||||
|
|
||||||
this.created_at = src.parseString("created_at")
|
|
||||||
this.time_created_at = TootStatus.parseTime(this.created_at)
|
|
||||||
|
|
||||||
this.avatar = src.parseString("avatar")
|
|
||||||
this.avatar_static = src.parseString("avatar_static")
|
|
||||||
this.header = src.parseString("header")
|
|
||||||
this.header_static = src.parseString("header_static")
|
|
||||||
}
|
|
||||||
|
|
||||||
ServiceType.MSP -> {
|
this.custom_emojis = null
|
||||||
this.id = src.parseLong("id") ?: INVALID_ID
|
this.profile_emojis = null
|
||||||
|
|
||||||
// MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない
|
|
||||||
this.host = findHostFromUrl(null, null, url)
|
|
||||||
?: throw RuntimeException("can't get host from url")
|
|
||||||
this.acct = this.username + "@" + host
|
|
||||||
|
|
||||||
this.followers_count = null
|
|
||||||
this.following_count = null
|
|
||||||
this.statuses_count = null
|
|
||||||
|
|
||||||
this.created_at = null
|
|
||||||
this.time_created_at = 0L
|
|
||||||
|
|
||||||
val avatar = src.parseString("avatar")
|
|
||||||
this.avatar = avatar
|
|
||||||
this.avatar_static = avatar
|
|
||||||
this.header = null
|
|
||||||
this.header_static = null
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
this.username = src.notEmptyOrThrow("username")
|
||||||
|
this.url = "https://$instance/@$username"
|
||||||
|
|
||||||
|
//
|
||||||
|
sv = src.parseString("name")
|
||||||
|
this.display_name = if(sv?.isNotEmpty() == true) sv.sanitizeBDI() else username
|
||||||
|
|
||||||
|
//
|
||||||
|
this.note = src.parseString("description")
|
||||||
|
|
||||||
|
this.source = null
|
||||||
|
this.movedRef = null
|
||||||
|
this.locked = src.optBoolean("isLocked")
|
||||||
|
|
||||||
|
this.fields = null
|
||||||
|
|
||||||
|
this.bot = src.optBoolean("isBot", false)
|
||||||
|
|
||||||
|
// this.user_hides_network = src.optBoolean("user_hides_network")
|
||||||
|
|
||||||
|
this.id = INVALID_ID
|
||||||
|
|
||||||
|
this.acct = "$username@$instance"
|
||||||
|
this.host = instance
|
||||||
|
|
||||||
|
this.followers_count = src.parseLong("followersCount") ?: -1L
|
||||||
|
this.following_count = src.parseLong("followingCount") ?: -1L
|
||||||
|
this.statuses_count = src.parseLong("notesCount") ?: -1L
|
||||||
|
|
||||||
|
this.created_at = src.parseString("createdAt")
|
||||||
|
this.time_created_at = TootStatus.parseTime(this.created_at)
|
||||||
|
|
||||||
|
this.avatar = src.parseString("avatarUrl")
|
||||||
|
this.avatar_static = src.parseString("avatarUrl")
|
||||||
|
this.header =src.parseString("bannerUrl")
|
||||||
|
this.header_static = src.parseString("bannerUrl")
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// 絵文字データは先に読んでおく
|
||||||
|
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"))
|
||||||
|
this.profile_emojis =
|
||||||
|
parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"))
|
||||||
|
|
||||||
|
// 疑似アカウントにacctとusernameだけ
|
||||||
|
this.url = src.parseString("url")
|
||||||
|
this.username = src.notEmptyOrThrow("username")
|
||||||
|
|
||||||
|
//
|
||||||
|
sv = src.parseString("display_name")
|
||||||
|
this.display_name = if(sv?.isNotEmpty() == true) sv.sanitizeBDI() else username
|
||||||
|
|
||||||
|
//
|
||||||
|
this.note = src.parseString("note")
|
||||||
|
|
||||||
|
this.source = parseSource(src.optJSONObject("source"))
|
||||||
|
this.movedRef = TootAccountRef.mayNull(
|
||||||
|
parser,
|
||||||
|
src.optJSONObject("moved")?.let {
|
||||||
|
TootAccount(parser, it)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
this.locked = src.optBoolean("locked")
|
||||||
|
|
||||||
|
this.fields = parseFields(src.optJSONArray("fields"))
|
||||||
|
|
||||||
|
this.bot = src.optBoolean("bot", false)
|
||||||
|
|
||||||
|
// this.user_hides_network = src.optBoolean("user_hides_network")
|
||||||
|
|
||||||
|
when(parser.serviceType) {
|
||||||
|
ServiceType.MASTODON -> {
|
||||||
|
|
||||||
|
val hostAccess = parser.linkHelper.host
|
||||||
|
|
||||||
|
this.id = src.parseLong("id") ?: INVALID_ID
|
||||||
|
|
||||||
|
this.acct = src.notEmptyOrThrow("acct")
|
||||||
|
this.host = findHostFromUrl(acct, hostAccess, url)
|
||||||
|
?: throw RuntimeException("can't get host from acct or url")
|
||||||
|
|
||||||
|
this.followers_count = src.parseLong("followers_count")
|
||||||
|
this.following_count = src.parseLong("following_count")
|
||||||
|
this.statuses_count = src.parseLong("statuses_count")
|
||||||
|
|
||||||
|
this.created_at = src.parseString("created_at")
|
||||||
|
this.time_created_at = TootStatus.parseTime(this.created_at)
|
||||||
|
|
||||||
|
this.avatar = src.parseString("avatar")
|
||||||
|
this.avatar_static = src.parseString("avatar_static")
|
||||||
|
this.header = src.parseString("header")
|
||||||
|
this.header_static = src.parseString("header_static")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceType.TOOTSEARCH -> {
|
||||||
|
// tootsearch のアカウントのIDはどのタンス上のものか分からないので役に立たない
|
||||||
|
this.id = INVALID_ID // src.parseLong( "id", INVALID_ID)
|
||||||
|
|
||||||
|
sv = src.notEmptyOrThrow("acct")
|
||||||
|
this.host = findHostFromUrl(sv, null, url)
|
||||||
|
?: throw RuntimeException("can't get host from acct or url")
|
||||||
|
this.acct = this.username + "@" + this.host
|
||||||
|
|
||||||
|
this.followers_count = src.parseLong("followers_count")
|
||||||
|
this.following_count = src.parseLong("following_count")
|
||||||
|
this.statuses_count = src.parseLong("statuses_count")
|
||||||
|
|
||||||
|
this.created_at = src.parseString("created_at")
|
||||||
|
this.time_created_at = TootStatus.parseTime(this.created_at)
|
||||||
|
|
||||||
|
this.avatar = src.parseString("avatar")
|
||||||
|
this.avatar_static = src.parseString("avatar_static")
|
||||||
|
this.header = src.parseString("header")
|
||||||
|
this.header_static = src.parseString("header_static")
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceType.MSP -> {
|
||||||
|
this.id = src.parseLong("id") ?: INVALID_ID
|
||||||
|
|
||||||
|
// MSPはLTLの情報しか持ってないのでacctは常にホスト名部分を持たない
|
||||||
|
this.host = findHostFromUrl(null, null, url)
|
||||||
|
?: throw RuntimeException("can't get host from url")
|
||||||
|
this.acct = this.username + "@" + host
|
||||||
|
|
||||||
|
this.followers_count = null
|
||||||
|
this.following_count = null
|
||||||
|
this.statuses_count = null
|
||||||
|
|
||||||
|
this.created_at = null
|
||||||
|
this.time_created_at = 0L
|
||||||
|
|
||||||
|
val avatar = src.parseString("avatar")
|
||||||
|
this.avatar = avatar
|
||||||
|
this.avatar_static = avatar
|
||||||
|
this.header = null
|
||||||
|
this.header_static = null
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> error("will not happen")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,4 +13,9 @@ class TootApplication(
|
||||||
name = src.parseString("name"),
|
name = src.parseString("name"),
|
||||||
website = src.parseString("website")
|
website = src.parseString("website")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
constructor(src:String?):this(
|
||||||
|
name = src,
|
||||||
|
website = null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,8 +18,10 @@ import jp.juggler.subwaytooter.api.TootParser
|
||||||
import jp.juggler.subwaytooter.table.HighlightWord
|
import jp.juggler.subwaytooter.table.HighlightWord
|
||||||
import jp.juggler.subwaytooter.table.SavedAccount
|
import jp.juggler.subwaytooter.table.SavedAccount
|
||||||
import jp.juggler.subwaytooter.util.*
|
import jp.juggler.subwaytooter.util.*
|
||||||
|
import org.json.JSONArray
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanPrivate")
|
@Suppress("MemberVisibilityCanPrivate")
|
||||||
class TootStatus(parser : TootParser, src : JSONObject) :
|
class TootStatus(parser : TootParser, src : JSONObject) :
|
||||||
|
@ -155,133 +157,271 @@ class TootStatus(parser : TootParser, src : JSONObject) :
|
||||||
init {
|
init {
|
||||||
this.json = src
|
this.json = src
|
||||||
|
|
||||||
this.uri = src.parseString("uri") // MSPだとuriは提供されない
|
if( parser.serviceType == ServiceType.MISSKEY) {
|
||||||
this.url = src.parseString("url") // 頻繁にnullになる
|
val instance = parser.linkHelper.host
|
||||||
this.created_at = src.parseString("created_at")
|
val misskeyId = src.parseString("id")
|
||||||
|
this.host_access = parser.linkHelper.host
|
||||||
// 絵文字マップはすぐ後で使うので、最初の方で読んでおく
|
|
||||||
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"), log)
|
this.uri = "https://$instance/notes/$misskeyId"
|
||||||
this.profile_emojis =
|
this.url = "https://$instance/notes/$misskeyId"
|
||||||
parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"), log)
|
this.created_at = src.parseString("createdAt")
|
||||||
|
this.time_created_at = parseTime(this.created_at)
|
||||||
val who = parser.account(src.optJSONObject("account"))
|
this.id = INVALID_ID
|
||||||
?: throw RuntimeException("missing account")
|
|
||||||
|
// 絵文字マップはすぐ後で使うので、最初の方で読んでおく
|
||||||
this.accountRef = TootAccountRef(parser, who)
|
this.custom_emojis = null
|
||||||
|
this.profile_emojis = null
|
||||||
this.reblogs_count = src.parseLong("reblogs_count")
|
|
||||||
this.favourites_count = src.parseLong("favourites_count")
|
val who = parser.account(src.optJSONObject("user"))
|
||||||
this.replies_count = src.parseLong("replies_count")
|
?: throw RuntimeException("missing account")
|
||||||
|
|
||||||
|
this.accountRef = TootAccountRef(parser, who)
|
||||||
|
|
||||||
|
this.reblogs_count = 0L
|
||||||
|
this.favourites_count = 0L
|
||||||
|
this.replies_count = 0L
|
||||||
|
|
||||||
|
this.reblogged = false
|
||||||
|
this.favourited = false
|
||||||
|
|
||||||
|
this.media_attachments = parseMediaAttachmentMisskey(src.optJSONArray("media"))
|
||||||
|
this.visibility = src.parseString("visibility")
|
||||||
|
this.sensitive = src.optBoolean("sensitive")
|
||||||
|
|
||||||
|
|
||||||
|
this.in_reply_to_id = null
|
||||||
|
this.in_reply_to_account_id = null
|
||||||
|
this.mentions = null
|
||||||
|
this.tags = null
|
||||||
|
this.application = parseItem(::TootApplication, src.optJSONObject("appId"), log)
|
||||||
|
this.pinned = parser.pinned
|
||||||
|
this.muted = false
|
||||||
|
this.language = null
|
||||||
|
|
||||||
|
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
||||||
|
parser.linkHelper,
|
||||||
|
this.mentions,
|
||||||
|
this
|
||||||
|
) ?: EMPTY_SPANNABLE
|
||||||
|
|
||||||
|
// this.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
||||||
|
|
||||||
|
// content
|
||||||
|
this.content = src.parseString("text")
|
||||||
|
|
||||||
|
var options = DecodeOptions(
|
||||||
|
parser.context,
|
||||||
|
parser.linkHelper,
|
||||||
|
short = true,
|
||||||
|
decodeEmoji = true,
|
||||||
|
emojiMapCustom = custom_emojis,
|
||||||
|
emojiMapProfile = profile_emojis,
|
||||||
|
attachmentList = media_attachments,
|
||||||
|
highlightTrie = parser.highlightTrie
|
||||||
|
)
|
||||||
|
|
||||||
|
this.decoded_content = options.decodeHTML(content)
|
||||||
|
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
||||||
|
if(options.highlight_sound != null && this.highlight_sound == null) {
|
||||||
|
this.highlight_sound = options.highlight_sound
|
||||||
|
}
|
||||||
|
|
||||||
|
// spoiler_text
|
||||||
|
this.spoiler_text = reWhitespace
|
||||||
|
.matcher(src.parseString("cw") ?: "")
|
||||||
|
.replaceAll(" ")
|
||||||
|
.sanitizeBDI()
|
||||||
|
|
||||||
|
options = DecodeOptions(
|
||||||
|
parser.context,
|
||||||
|
emojiMapCustom = custom_emojis,
|
||||||
|
emojiMapProfile = profile_emojis,
|
||||||
|
highlightTrie = parser.highlightTrie
|
||||||
|
)
|
||||||
|
|
||||||
|
this.decoded_spoiler_text = options.decodeEmoji(spoiler_text)
|
||||||
|
|
||||||
|
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
||||||
|
if(options.highlight_sound != null && this.highlight_sound == null) {
|
||||||
|
this.highlight_sound = options.highlight_sound
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enquete = null
|
||||||
|
|
||||||
|
this.reblog = parser.status(src.optJSONObject("renote"))
|
||||||
|
|
||||||
when(parser.serviceType) {
|
}else{
|
||||||
ServiceType.MASTODON -> {
|
this.uri = src.parseString("uri") // MSPだとuriは提供されない
|
||||||
this.host_access = parser.linkHelper.host
|
this.url = src.parseString("url") // 頻繁にnullになる
|
||||||
|
this.created_at = src.parseString("created_at")
|
||||||
|
|
||||||
|
// 絵文字マップはすぐ後で使うので、最初の方で読んでおく
|
||||||
|
this.custom_emojis = parseMapOrNull(::CustomEmoji, src.optJSONArray("emojis"), log)
|
||||||
|
this.profile_emojis =
|
||||||
|
parseMapOrNull(::NicoProfileEmoji, src.optJSONArray("profile_emojis"), log)
|
||||||
|
|
||||||
|
val who = parser.account(src.optJSONObject("account"))
|
||||||
|
?: throw RuntimeException("missing account")
|
||||||
|
|
||||||
|
this.accountRef = TootAccountRef(parser, who)
|
||||||
|
|
||||||
|
this.reblogs_count = src.parseLong("reblogs_count")
|
||||||
|
this.favourites_count = src.parseLong("favourites_count")
|
||||||
|
this.replies_count = src.parseLong("replies_count")
|
||||||
|
|
||||||
|
when(parser.serviceType) {
|
||||||
|
ServiceType.MASTODON -> {
|
||||||
|
this.host_access = parser.linkHelper.host
|
||||||
|
|
||||||
|
this.id = src.parseLong("id") ?: INVALID_ID
|
||||||
|
|
||||||
|
this.reblogged = src.optBoolean("reblogged")
|
||||||
|
this.favourited = src.optBoolean("favourited")
|
||||||
|
|
||||||
|
this.time_created_at = parseTime(this.created_at)
|
||||||
|
this.media_attachments =
|
||||||
|
parseListOrNull(::TootAttachment, src.optJSONArray("media_attachments"), log)
|
||||||
|
this.visibility = src.parseString("visibility")
|
||||||
|
this.sensitive = src.optBoolean("sensitive")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
this.id = src.parseLong("id") ?: INVALID_ID
|
ServiceType.TOOTSEARCH -> {
|
||||||
|
this.host_access = null
|
||||||
this.reblogged = src.optBoolean("reblogged")
|
|
||||||
this.favourited = src.optBoolean("favourited")
|
// 投稿元タンスでのIDを調べる。失敗するかもしれない
|
||||||
|
this.id = findStatusIdFromUri(uri, url)
|
||||||
this.time_created_at = parseTime(this.created_at)
|
|
||||||
this.media_attachments =
|
this.time_created_at = TootStatus.parseTime(this.created_at)
|
||||||
parseListOrNull(::TootAttachment, src.optJSONArray("media_attachments"), log)
|
this.media_attachments =
|
||||||
this.visibility = src.parseString("visibility")
|
parseListOrNull(::TootAttachment, src.optJSONArray("media_attachments"), log)
|
||||||
this.sensitive = src.optBoolean("sensitive")
|
this.visibility = VISIBILITY_PUBLIC
|
||||||
|
this.sensitive = src.optBoolean("sensitive")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
ServiceType.MSP -> {
|
||||||
|
this.host_access = null
|
||||||
|
|
||||||
|
// MSPのデータはLTLから呼んだものなので、常に投稿元タンスでのidが得られる
|
||||||
|
this.id = src.parseLong("id") ?: INVALID_ID
|
||||||
|
|
||||||
|
this.time_created_at = parseTimeMSP(created_at)
|
||||||
|
this.media_attachments =
|
||||||
|
TootAttachmentMSP.parseList(src.optJSONArray("media_attachments"))
|
||||||
|
this.visibility = VISIBILITY_PUBLIC
|
||||||
|
this.sensitive = src.optInt("sensitive", 0) != 0
|
||||||
|
}
|
||||||
|
else-> error("will not happen")
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceType.TOOTSEARCH -> {
|
this.in_reply_to_id = src.parseString("in_reply_to_id")
|
||||||
this.host_access = null
|
this.in_reply_to_account_id = src.parseString("in_reply_to_account_id")
|
||||||
|
this.mentions = parseListOrNull(::TootMention, src.optJSONArray("mentions"), log)
|
||||||
// 投稿元タンスでのIDを調べる。失敗するかもしれない
|
this.tags = parseListOrNull(::TootTag, src.optJSONArray("tags"))
|
||||||
this.id = findStatusIdFromUri(uri, url)
|
this.application = parseItem(::TootApplication, src.optJSONObject("application"), log)
|
||||||
|
this.pinned = parser.pinned || src.optBoolean("pinned")
|
||||||
this.time_created_at = TootStatus.parseTime(this.created_at)
|
this.muted = src.optBoolean("muted")
|
||||||
this.media_attachments =
|
this.language = src.parseString("language")
|
||||||
parseListOrNull(::TootAttachment, src.optJSONArray("media_attachments"), log)
|
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
||||||
this.visibility = VISIBILITY_PUBLIC
|
parser.linkHelper,
|
||||||
this.sensitive = src.optBoolean("sensitive")
|
this.mentions,
|
||||||
|
this
|
||||||
|
) ?: EMPTY_SPANNABLE
|
||||||
|
// this.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
||||||
|
|
||||||
|
// content
|
||||||
|
this.content = src.parseString("content")
|
||||||
|
|
||||||
|
var options = DecodeOptions(
|
||||||
|
parser.context,
|
||||||
|
parser.linkHelper,
|
||||||
|
short = true,
|
||||||
|
decodeEmoji = true,
|
||||||
|
emojiMapCustom = custom_emojis,
|
||||||
|
emojiMapProfile = profile_emojis,
|
||||||
|
attachmentList = media_attachments,
|
||||||
|
highlightTrie = parser.highlightTrie
|
||||||
|
)
|
||||||
|
|
||||||
|
this.decoded_content = options.decodeHTML(content)
|
||||||
|
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
||||||
|
if(options.highlight_sound != null && this.highlight_sound == null) {
|
||||||
|
this.highlight_sound = options.highlight_sound
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceType.MSP -> {
|
// spoiler_text
|
||||||
this.host_access = null
|
this.spoiler_text = reWhitespace
|
||||||
|
.matcher(src.parseString("spoiler_text") ?: "")
|
||||||
// MSPのデータはLTLから呼んだものなので、常に投稿元タンスでのidが得られる
|
.replaceAll(" ")
|
||||||
this.id = src.parseLong("id") ?: INVALID_ID
|
.sanitizeBDI()
|
||||||
|
|
||||||
this.time_created_at = parseTimeMSP(created_at)
|
options = DecodeOptions(
|
||||||
this.media_attachments =
|
parser.context,
|
||||||
TootAttachmentMSP.parseList(src.optJSONArray("media_attachments"))
|
emojiMapCustom = custom_emojis,
|
||||||
this.visibility = VISIBILITY_PUBLIC
|
emojiMapProfile = profile_emojis,
|
||||||
this.sensitive = src.optInt("sensitive", 0) != 0
|
highlightTrie = parser.highlightTrie
|
||||||
|
)
|
||||||
|
|
||||||
|
this.decoded_spoiler_text = options.decodeEmoji(spoiler_text)
|
||||||
|
|
||||||
|
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
||||||
|
if(options.highlight_sound != null && this.highlight_sound == null) {
|
||||||
|
this.highlight_sound = options.highlight_sound
|
||||||
|
}
|
||||||
|
|
||||||
|
this.enquete = NicoEnquete.parse(
|
||||||
|
parser,
|
||||||
|
this,
|
||||||
|
media_attachments,
|
||||||
|
src.parseString("enquete")
|
||||||
|
)
|
||||||
|
|
||||||
|
// Pinned TL を取得した時にreblogが登場することはないので、reblogについてpinned 状態を気にする必要はない
|
||||||
|
this.reblog = parser.status(src.optJSONObject("reblog"))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseMediaAttachmentMisskey2(src : JSONObject?) : TootAttachment? {
|
||||||
|
src?: return null
|
||||||
|
|
||||||
|
val mimeType = src.parseString("type")
|
||||||
|
val url = src.parseString("url")
|
||||||
|
val thumbnailUrl = src.parseString("thumbnailUrl")
|
||||||
|
val dst = JSONObject()
|
||||||
|
dst.put("id",-1L)
|
||||||
|
dst.put("type", when{
|
||||||
|
mimeType?.startsWith("image/") ==true -> TootAttachmentLike.TYPE_IMAGE
|
||||||
|
mimeType?.startsWith("video/") ==true -> TootAttachmentLike.TYPE_VIDEO
|
||||||
|
else-> TootAttachmentLike.TYPE_UNKNOWN
|
||||||
|
})
|
||||||
|
dst.put("url",url)
|
||||||
|
dst.put("remote_url",url)
|
||||||
|
dst.put("text_url",url)
|
||||||
|
dst.put("preview_url",thumbnailUrl)
|
||||||
|
dst.put("description",src.parseString("comment"))
|
||||||
|
|
||||||
|
return parseItem(::TootAttachment,dst)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseMediaAttachmentMisskey(src : JSONArray?) : ArrayList<TootAttachmentLike>? {
|
||||||
|
var rv :ArrayList<TootAttachmentLike>? = null
|
||||||
|
if(src!=null){
|
||||||
|
for(i in 0 until src.length() ){
|
||||||
|
val item = try{
|
||||||
|
parseMediaAttachmentMisskey2(src.optJSONObject(i))
|
||||||
|
}catch(ex:Throwable){
|
||||||
|
log.e(ex,"parseMediaAttachmentMisskey")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if( item != null ){
|
||||||
|
if(rv==null) rv = ArrayList()
|
||||||
|
rv.add(item)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return rv
|
||||||
this.in_reply_to_id = src.parseString("in_reply_to_id")
|
|
||||||
this.in_reply_to_account_id = src.parseString("in_reply_to_account_id")
|
|
||||||
this.mentions = parseListOrNull(::TootMention, src.optJSONArray("mentions"), log)
|
|
||||||
this.tags = parseListOrNull(::TootTag, src.optJSONArray("tags"))
|
|
||||||
this.application = parseItem(::TootApplication, src.optJSONObject("application"), log)
|
|
||||||
this.pinned = parser.pinned || src.optBoolean("pinned")
|
|
||||||
this.muted = src.optBoolean("muted")
|
|
||||||
this.language = src.parseString("language")
|
|
||||||
this.decoded_mentions = HTMLDecoder.decodeMentions(
|
|
||||||
parser.linkHelper,
|
|
||||||
this.mentions,
|
|
||||||
this
|
|
||||||
) ?: EMPTY_SPANNABLE
|
|
||||||
// this.decoded_tags = HTMLDecoder.decodeTags( account,status.tags );
|
|
||||||
|
|
||||||
// content
|
|
||||||
this.content = src.parseString("content")
|
|
||||||
|
|
||||||
var options = DecodeOptions(
|
|
||||||
parser.context,
|
|
||||||
parser.linkHelper,
|
|
||||||
short = true,
|
|
||||||
decodeEmoji = true,
|
|
||||||
emojiMapCustom = custom_emojis,
|
|
||||||
emojiMapProfile = profile_emojis,
|
|
||||||
attachmentList = media_attachments,
|
|
||||||
highlightTrie = parser.highlightTrie
|
|
||||||
)
|
|
||||||
|
|
||||||
this.decoded_content = options.decodeHTML(content)
|
|
||||||
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
|
||||||
if(options.highlight_sound != null && this.highlight_sound == null) {
|
|
||||||
this.highlight_sound = options.highlight_sound
|
|
||||||
}
|
|
||||||
|
|
||||||
// spoiler_text
|
|
||||||
this.spoiler_text = reWhitespace
|
|
||||||
.matcher(src.parseString("spoiler_text") ?: "")
|
|
||||||
.replaceAll(" ")
|
|
||||||
.sanitizeBDI()
|
|
||||||
|
|
||||||
options = DecodeOptions(
|
|
||||||
parser.context,
|
|
||||||
emojiMapCustom = custom_emojis,
|
|
||||||
emojiMapProfile = profile_emojis,
|
|
||||||
highlightTrie = parser.highlightTrie
|
|
||||||
)
|
|
||||||
|
|
||||||
this.decoded_spoiler_text = options.decodeEmoji(spoiler_text)
|
|
||||||
|
|
||||||
this.hasHighlight = this.hasHighlight || options.hasHighlight
|
|
||||||
if(options.highlight_sound != null && this.highlight_sound == null) {
|
|
||||||
this.highlight_sound = options.highlight_sound
|
|
||||||
}
|
|
||||||
|
|
||||||
this.enquete = NicoEnquete.parse(
|
|
||||||
parser,
|
|
||||||
this,
|
|
||||||
media_attachments,
|
|
||||||
src.parseString("enquete")
|
|
||||||
)
|
|
||||||
|
|
||||||
// Pinned TL を取得した時にreblogが登場することはないので、reblogについてpinned 状態を気にする必要はない
|
|
||||||
this.reblog = parser.status(src.optJSONObject("reblog"))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////
|
///////////////////////////////////////////////////
|
||||||
|
|
|
@ -28,7 +28,8 @@ class SavedAccount(
|
||||||
val acct : String,
|
val acct : String,
|
||||||
hostArg : String? = null,
|
hostArg : String? = null,
|
||||||
var token_info : JSONObject? = null,
|
var token_info : JSONObject? = null,
|
||||||
var loginAccount : TootAccount? = null // 疑似アカウントではnull
|
var loginAccount : TootAccount? = null, // 疑似アカウントではnull
|
||||||
|
var isMisskey :Boolean = false // 疑似アカウントでのみtrue
|
||||||
) : LinkHelper {
|
) : LinkHelper {
|
||||||
|
|
||||||
val username : String
|
val username : String
|
||||||
|
@ -156,6 +157,8 @@ class SavedAccount(
|
||||||
this.sound_uri = cursor.getString(cursor.getColumnIndex(COL_SOUND_URI))
|
this.sound_uri = cursor.getString(cursor.getColumnIndex(COL_SOUND_URI))
|
||||||
|
|
||||||
this.default_text = cursor.getString(cursor.getColumnIndex(COL_DEFAULT_TEXT)) ?: ""
|
this.default_text = cursor.getString(cursor.getColumnIndex(COL_DEFAULT_TEXT)) ?: ""
|
||||||
|
|
||||||
|
this.isMisskey = cursor.getInt(cursor.getColumnIndex(COL_IS_MISSKEY)).i2b()
|
||||||
}
|
}
|
||||||
|
|
||||||
val isNA : Boolean
|
val isNA : Boolean
|
||||||
|
@ -405,6 +408,9 @@ class SavedAccount(
|
||||||
// スキーマ27から
|
// スキーマ27から
|
||||||
private const val COL_DEFAULT_TEXT = "default_text"
|
private const val COL_DEFAULT_TEXT = "default_text"
|
||||||
|
|
||||||
|
// スキーマ28から
|
||||||
|
private const val COL_IS_MISSKEY = "is_misskey"
|
||||||
|
|
||||||
/////////////////////////////////
|
/////////////////////////////////
|
||||||
// login information
|
// login information
|
||||||
const val INVALID_DB_ID = - 1L
|
const val INVALID_DB_ID = - 1L
|
||||||
|
@ -466,6 +472,8 @@ class SavedAccount(
|
||||||
// 以下はDBスキーマ27で更新
|
// 以下はDBスキーマ27で更新
|
||||||
+ ",$COL_DEFAULT_TEXT text default ''"
|
+ ",$COL_DEFAULT_TEXT text default ''"
|
||||||
|
|
||||||
|
// 以下はDBスキーマ28で更新
|
||||||
|
+ ",$COL_IS_MISSKEY integer default 0"
|
||||||
+ ")"
|
+ ")"
|
||||||
)
|
)
|
||||||
db.execSQL("create index if not exists ${table}_user on ${table}(u)")
|
db.execSQL("create index if not exists ${table}_user on ${table}(u)")
|
||||||
|
@ -592,7 +600,14 @@ class SavedAccount(
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if(oldVersion < 28 && newVersion >= 28) {
|
||||||
|
try {
|
||||||
|
db.execSQL("alter table $table add column $COL_IS_MISSKEY integer default 0")
|
||||||
|
} catch(ex : Throwable) {
|
||||||
|
log.trace(ex)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 横断検索用の、何とも紐ついていないアカウント
|
// 横断検索用の、何とも紐ついていないアカウント
|
||||||
|
@ -621,7 +636,8 @@ class SavedAccount(
|
||||||
host : String,
|
host : String,
|
||||||
acct : String,
|
acct : String,
|
||||||
account : JSONObject,
|
account : JSONObject,
|
||||||
token : JSONObject
|
token : JSONObject,
|
||||||
|
isMisskey : Boolean = false
|
||||||
) : Long {
|
) : Long {
|
||||||
try {
|
try {
|
||||||
val cv = ContentValues()
|
val cv = ContentValues()
|
||||||
|
@ -629,6 +645,7 @@ class SavedAccount(
|
||||||
cv.put(COL_USER, acct)
|
cv.put(COL_USER, acct)
|
||||||
cv.put(COL_ACCOUNT, account.toString())
|
cv.put(COL_ACCOUNT, account.toString())
|
||||||
cv.put(COL_TOKEN, token.toString())
|
cv.put(COL_TOKEN, token.toString())
|
||||||
|
cv.put(COL_IS_MISSKEY, isMisskey.b2i() )
|
||||||
return App1.database.insert(table, null, cv)
|
return App1.database.insert(table, null, cv)
|
||||||
} catch(ex : Throwable) {
|
} catch(ex : Throwable) {
|
||||||
log.trace(ex)
|
log.trace(ex)
|
||||||
|
|
|
@ -20,7 +20,10 @@ import android.view.ViewGroup
|
||||||
import android.view.inputmethod.InputMethodManager
|
import android.view.inputmethod.InputMethodManager
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
|
import jp.juggler.subwaytooter.api.TootApiClient
|
||||||
import me.drakeet.support.toast.ToastCompat
|
import me.drakeet.support.toast.ToastCompat
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.RequestBody
|
||||||
import org.apache.commons.io.IOUtils
|
import org.apache.commons.io.IOUtils
|
||||||
import org.json.JSONArray
|
import org.json.JSONArray
|
||||||
import org.json.JSONObject
|
import org.json.JSONObject
|
||||||
|
@ -651,6 +654,9 @@ fun JSONObject.parseInt(key : String) : Int? {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun JSONObject.toPostRequestBuilder()=
|
||||||
|
Request.Builder().post(RequestBody.create(TootApiClient.MEDIA_TYPE_JSON,this.toString()))
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////
|
||||||
// Bundle
|
// Bundle
|
||||||
|
|
||||||
|
|
|
@ -836,6 +836,8 @@ mimumedon.com
|
||||||
mindful.masto.host
|
mindful.masto.host
|
||||||
minidon.bacardi55.org
|
minidon.bacardi55.org
|
||||||
misanthropy.wang
|
misanthropy.wang
|
||||||
|
misskey.xyz
|
||||||
|
misskey.jp
|
||||||
mist.so
|
mist.so
|
||||||
mistermi.me
|
mistermi.me
|
||||||
mn.kitetu.com
|
mn.kitetu.com
|
||||||
|
|
Loading…
Reference in New Issue