バージョン比較時にrcを正しく取り扱う。2.4.0rc2以降のタンスでプッシュ購読更新の挙動を最適化。
This commit is contained in:
parent
9133f18650
commit
f3f25557f7
|
@ -241,8 +241,7 @@ class Column(
|
|||
}
|
||||
}
|
||||
|
||||
internal val version_1_6 = VersionString("1.6")
|
||||
|
||||
|
||||
@Suppress("HasPlatformType")
|
||||
val reMaxId = Pattern.compile("[&?]max_id=(\\d+)") // より古いデータの取得に使う
|
||||
|
||||
|
@ -1711,7 +1710,7 @@ class Column(
|
|||
if(with_attachment && ! with_highlight) path += "&only_media=1"
|
||||
|
||||
if(instance != null
|
||||
&& instance.versionGE(version_1_6)
|
||||
&& instance.versionGE(TootInstance.VERSION_1_6)
|
||||
// 将来的に正しく判定できる見込みがないので、Pleroma条件でのフィルタは行わない
|
||||
// && instance.instanceType != TootInstance.InstanceType.Pleroma
|
||||
) {
|
||||
|
|
|
@ -180,7 +180,7 @@ class TootApiClient(
|
|||
}
|
||||
|
||||
fun getScopeString(ti : TootInstance) = when {
|
||||
ti.versionGE(TootInstance.VERSION_2_4_0) -> "read+write+follow+push"
|
||||
ti.versionGE(TootInstance.VERSION_2_4_0_rc1) -> "read+write+follow+push"
|
||||
else -> "read+write+follow"
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,9 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
|||
companion object {
|
||||
private val rePleroma = Pattern.compile("\\bpleroma\\b", Pattern.CASE_INSENSITIVE)
|
||||
|
||||
val VERSION_2_4_0 = VersionString("2.4.0")
|
||||
val VERSION_2_4_1 = VersionString("2.4.1")
|
||||
val VERSION_1_6 = VersionString("1.6")
|
||||
val VERSION_2_4_0_rc1 = VersionString("2.4.0rc1")
|
||||
val VERSION_2_4_0_rc2 = VersionString("2.4.0rc2")
|
||||
|
||||
}
|
||||
|
||||
|
@ -106,10 +107,5 @@ class TootInstance(parser : TootParser, src : JSONObject) {
|
|||
val i = VersionString.compare(decoded_version, check)
|
||||
return i >= 0
|
||||
}
|
||||
|
||||
fun versionEquals(check : VersionString) : Boolean {
|
||||
if(decoded_version.isEmpty || check.isEmpty) return false
|
||||
val i = VersionString.compare(decoded_version, check)
|
||||
return i == 0
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -59,7 +59,7 @@ class PostHelper(
|
|||
private val reCharsNotTag = Pattern.compile("[・\\s\\-+.,:;/]")
|
||||
private val reCharsNotEmoji = Pattern.compile("[^0-9A-Za-z_-]")
|
||||
|
||||
private val version_1_6 = VersionString("1.6")
|
||||
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -205,7 +205,7 @@ class PostHelper(
|
|||
instance = instance_tmp ?: return r2
|
||||
account.instance = instance
|
||||
}
|
||||
visibility_checked = if(instance.versionGE(version_1_6)) {
|
||||
visibility_checked = if(instance.versionGE(TootInstance.VERSION_1_6)) {
|
||||
null
|
||||
} else {
|
||||
val r2 = getCredential(client)
|
||||
|
|
|
@ -2,8 +2,9 @@ package jp.juggler.subwaytooter.util
|
|||
|
||||
import java.math.BigInteger
|
||||
import java.util.ArrayList
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class VersionString(src : String?) {
|
||||
class VersionString(src : String?) : Comparable<VersionString> {
|
||||
|
||||
private val src : String
|
||||
|
||||
|
@ -16,97 +17,143 @@ class VersionString(src : String?) {
|
|||
return src
|
||||
}
|
||||
|
||||
private class RC(val x : Int) : Comparable<RC> {
|
||||
override fun compareTo(other : RC) : Int {
|
||||
val i = x - other.x
|
||||
return if(i > 0) 1 else if(i < 0) - 1 else 0
|
||||
}
|
||||
|
||||
override fun toString() : String {
|
||||
return "RC($x)"
|
||||
}
|
||||
}
|
||||
|
||||
override fun compareTo(other : VersionString) : Int {
|
||||
return compare(this, other)
|
||||
}
|
||||
|
||||
init {
|
||||
this.src = src ?: ""
|
||||
if( src != null && src.isNotEmpty() ){
|
||||
if(src != null && src.isNotEmpty()) {
|
||||
val end = src.length
|
||||
var next = 0
|
||||
while(next < end) {
|
||||
var c = src[next]
|
||||
|
||||
if(isDelimiter(c)) {
|
||||
// 先頭の区切り文字を無視する
|
||||
++ next
|
||||
} else if(Character.isDigit(c)) {
|
||||
// 数字列のノード
|
||||
val start = next ++
|
||||
while(next < end && Character.isDigit(src[next])) ++ next
|
||||
val value = BigInteger(src.substring(start, next))
|
||||
node_list.add(value)
|
||||
} else {
|
||||
// 区切り文字と数字以外の文字が並ぶノード
|
||||
val start = next ++
|
||||
while(next < end) {
|
||||
c = src[next]
|
||||
if(isDelimiter(c)) break
|
||||
if(Character.isDigit(c)) break
|
||||
when {
|
||||
isDelimiter(c) -> {
|
||||
// 先頭の区切り文字を無視する
|
||||
++ next
|
||||
}
|
||||
val value = src.substring(start, next)
|
||||
node_list.add(value)
|
||||
|
||||
Character.isDigit(c) -> {
|
||||
// 数字列のノード
|
||||
val start = next ++
|
||||
while(next < end && Character.isDigit(src[next])) ++ next
|
||||
val value = BigInteger(src.substring(start, next))
|
||||
node_list.add(value)
|
||||
}
|
||||
|
||||
else -> {
|
||||
val m = reRcX.matcher(src)
|
||||
|
||||
if(DUMP) {
|
||||
if(m.find(next)) {
|
||||
println("next=$next, matct_start=${m.start()}")
|
||||
} else {
|
||||
println("next=$next, not match.")
|
||||
}
|
||||
}
|
||||
|
||||
if(m.find(next) && m.start() == next) {
|
||||
// RCノード
|
||||
next = m.end()
|
||||
val numStr = m.group(1)
|
||||
val num = if(numStr?.isNotEmpty() == true) {
|
||||
numStr.toInt()
|
||||
} else {
|
||||
0
|
||||
}
|
||||
node_list.add(RC(num))
|
||||
} else {
|
||||
// 区切り文字と数字以外の文字が並ぶノード
|
||||
val start = next ++
|
||||
while(next < end) {
|
||||
c = src[next]
|
||||
if(isDelimiter(c)) break
|
||||
if(Character.isDigit(c)) break
|
||||
++ next
|
||||
}
|
||||
val value = src.substring(start, next)
|
||||
node_list.add(value)
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
// private val warning = new LogCategory( "VersionString" )
|
||||
companion object : Comparator<VersionString> {
|
||||
|
||||
private const val DUMP = false
|
||||
|
||||
private fun isDelimiter(c : Char) : Boolean {
|
||||
return c == '.' || c == ' '
|
||||
}
|
||||
|
||||
private val reRcX = Pattern.compile("rc(\\d*)")
|
||||
|
||||
private fun checkTail(b : Any) : Int {
|
||||
// 1.0 < 1.0.n => -1
|
||||
// 1.0 < 1.0xxx => -1
|
||||
// 1.0 > 1.0rc1 => 1
|
||||
return if(b is RC) 1 else - 1
|
||||
}
|
||||
|
||||
private fun checkBigInteger(a : BigInteger, b : Any) : Int {
|
||||
if(b is BigInteger) return a.compareTo(b)
|
||||
// 数字 > 数字以外
|
||||
// 1.5.n > 1.5xxx
|
||||
// 1.5.n > 1.5rc1
|
||||
return 1
|
||||
}
|
||||
|
||||
private fun checkRc(a : RC, b : Any) : Int {
|
||||
if(b is RC) return a.compareTo(b)
|
||||
// RC < string
|
||||
// 1.5rc < 1.5xxx
|
||||
return - 1
|
||||
}
|
||||
|
||||
// return -1 if a<b , return 1 if a>b , return 0 if a==b
|
||||
fun compare(a : VersionString, b : VersionString) : Int {
|
||||
|
||||
override fun compare(a : VersionString, b : VersionString) : Int {
|
||||
var idx = 0
|
||||
while(true) {
|
||||
loop@ while(true) {
|
||||
val ao = if(idx >= a.node_list.size) null else a.node_list[idx]
|
||||
val bo = if(idx >= b.node_list.size) null else b.node_list[idx]
|
||||
if(ao == null) {
|
||||
// 1.0 < 1.0.n
|
||||
// 1.0 < 1.0 xxx
|
||||
return if(bo == null) 0 else - 1
|
||||
} else if(bo == null) {
|
||||
// 1.0.n > 1.0
|
||||
// 1.0 xxx > 1.0
|
||||
return 1
|
||||
}
|
||||
if(DUMP) println("a=$ao,b=$bo")
|
||||
|
||||
return if(ao is BigInteger) {
|
||||
if(bo is BigInteger) {
|
||||
// 数字同士の場合
|
||||
val i = ao.compareTo(bo)
|
||||
if(i == 0) {
|
||||
++ idx
|
||||
continue
|
||||
}else {
|
||||
i
|
||||
}
|
||||
} else {
|
||||
// 数字 > 数字以外
|
||||
// 1.5.n > 1.5 xxx
|
||||
1
|
||||
val i = when {
|
||||
ao == null -> {
|
||||
if(bo == null) return 0
|
||||
checkTail(bo)
|
||||
}
|
||||
} else if(bo is BigInteger) {
|
||||
// 数字以外 < 数字
|
||||
// 1.5 xxx < 1.5.n
|
||||
- 1
|
||||
} else if( ao is String && bo is String ){
|
||||
// 文字列どうしは辞書順で比較
|
||||
val i =ao.compareTo(bo )
|
||||
if(i == 0) {
|
||||
++ idx
|
||||
continue
|
||||
}
|
||||
i
|
||||
}else{
|
||||
throw RuntimeException("node is not string")
|
||||
|
||||
bo == null -> - checkTail(ao)
|
||||
ao is BigInteger -> checkBigInteger(ao, bo)
|
||||
bo is BigInteger -> - checkBigInteger(bo, ao)
|
||||
ao is RC -> checkRc(ao, bo)
|
||||
bo is RC -> - checkRc(bo, ao)
|
||||
else -> a.toString().compareTo(b.toString())
|
||||
}
|
||||
if(i == 0) {
|
||||
++ idx
|
||||
continue@loop
|
||||
}
|
||||
return i
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -81,8 +81,8 @@ class WebPushSubscription(
|
|||
r = client.getInstanceInformation2()
|
||||
val ti = r?.data as? TootInstance ?: return r
|
||||
|
||||
if(! ti.versionGE(TootInstance.VERSION_2_4_0)) {
|
||||
// 2.3.x 以下にはプッシュ購読APIはない
|
||||
if( ! ti.versionGE(TootInstance.VERSION_2_4_0_rc1)) {
|
||||
// 2.4.0rc1 未満にはプッシュ購読APIはない
|
||||
return TootApiResult(
|
||||
error = context.getString(
|
||||
R.string.instance_does_not_support_push_api,
|
||||
|
@ -92,15 +92,13 @@ class WebPushSubscription(
|
|||
}
|
||||
|
||||
if(subscription404 && flags == 0) {
|
||||
if(ti.versionGE(TootInstance.VERSION_2_4_1)
|
||||
|| ti.versionEquals(TootInstance.VERSION_2_4_0)
|
||||
) {
|
||||
if(ti.versionGE(TootInstance.VERSION_2_4_0_rc2) ) {
|
||||
// 購読が不要で現在の状況が404だった場合
|
||||
// 2.4.0正式版と2.4.1以降では購読が存在しないので何もしなくてよい
|
||||
// 2.4.0rc2以降では「購読が存在しない」を示すので何もしなくてよい
|
||||
if(verbose) addLog(context.getString(R.string.push_subscription_not_exists))
|
||||
return TootApiResult()
|
||||
} else {
|
||||
// コミット単位でバージョン比較する方法はないので、2.4.0正式ではない2.4.0xxxでは存在確認はできない
|
||||
// 2.4.0rc1では「APIが存在しない」と「購読が存在しない」を判別できない
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
@file:Suppress(
|
||||
"USELESS_CAST", "unused", "DEPRECATED_IDENTITY_EQUALS", "UNUSED_VARIABLE",
|
||||
"UNUSED_VALUE", "ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "VARIABLE_WITH_REDUNDANT_INITIALIZER",
|
||||
"ReplaceCallWithComparison"
|
||||
)
|
||||
|
||||
package jp.juggler.subwaytooter
|
||||
|
||||
import jp.juggler.subwaytooter.util.VersionString
|
||||
import org.junit.Test
|
||||
|
||||
import org.junit.Assert.*
|
||||
|
||||
class TestVersionString {
|
||||
@Test
|
||||
fun test1() {
|
||||
val v233 = VersionString("2.3.3")
|
||||
val v240rc0 = VersionString("2.4.0rc")
|
||||
val v240rc1 = VersionString("2.4.0rc1")
|
||||
val v240rc2 = VersionString("2.4.0rc2")
|
||||
val v240 = VersionString("2.4.0")
|
||||
val v240xxx = VersionString("2.4.0xxx")
|
||||
val v241 = VersionString("2.4.1")
|
||||
|
||||
assertTrue(v233 < v240rc0)
|
||||
assertTrue(v240rc0 < v240rc1)
|
||||
assertTrue(v240rc1 < v240rc2)
|
||||
assertTrue(v240rc2 < v240)
|
||||
assertTrue(v240 < v240xxx)
|
||||
assertTrue(v240xxx < v241)
|
||||
|
||||
assertTrue(v240rc0 > v233)
|
||||
assertTrue(v240rc1 > v240rc0)
|
||||
assertTrue(v240rc2 > v240rc1)
|
||||
assertTrue(v240 > v240rc2)
|
||||
assertTrue(v240xxx > v240)
|
||||
assertTrue(v241 > v240xxx)
|
||||
|
||||
assertTrue(0 == v233.compareTo(v233))
|
||||
assertTrue(0 == v240rc0.compareTo(v240rc0))
|
||||
assertTrue(0 == v240rc1.compareTo(v240rc1))
|
||||
assertTrue(0 == v240rc2.compareTo(v240rc2))
|
||||
assertTrue(0 == v240.compareTo(v240))
|
||||
assertTrue(0 == v240xxx.compareTo(v240xxx))
|
||||
assertTrue(0 == v241.compareTo(v241))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test2() {
|
||||
val v240 = VersionString("2.4.0")
|
||||
val v240xxx = VersionString("2.4.0xxx")
|
||||
assertTrue(v240 < v240xxx)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue