古いプッシュ購読のURL中の識別子を見て自動移行を行う。アプリデータのインポート時に、使わなくなったカラムのデータを無視する。
This commit is contained in:
parent
2d7fceb238
commit
7e7f726e6a
|
@ -15,8 +15,10 @@ sub cmd($){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cmd "./gradlew --stop";
|
||||||
cmd "./gradlew clean";
|
cmd "./gradlew clean";
|
||||||
cmd "./gradlew assembleNoFcmRelease";
|
cmd "./gradlew assembleNoFcmRelease";
|
||||||
cmd "./gradlew assembleFcmRelease";
|
cmd "./gradlew assembleFcmRelease";
|
||||||
|
cmd "./gradlew --stop";
|
||||||
cmd "mv app/build/outputs/apk/SubwayTooter*.apk app/";
|
cmd "mv app/build/outputs/apk/SubwayTooter*.apk app/";
|
||||||
cmd " ls -1t app/SubwayTooter*.apk |head -n 5";
|
cmd " ls -1t app/SubwayTooter*.apk |head -n 5";
|
||||||
|
|
|
@ -182,6 +182,7 @@ object AppDataExporter {
|
||||||
cv.clear()
|
cv.clear()
|
||||||
|
|
||||||
reader.beginObject()
|
reader.beginObject()
|
||||||
|
val keys = ArrayList<String>()
|
||||||
while (reader.hasNext()) {
|
while (reader.hasNext()) {
|
||||||
val name = reader.nextName()
|
val name = reader.nextName()
|
||||||
if (name == null) {
|
if (name == null) {
|
||||||
|
@ -205,6 +206,7 @@ object AppDataExporter {
|
||||||
"last_notification_error",
|
"last_notification_error",
|
||||||
"last_subscription_error",
|
"last_subscription_error",
|
||||||
"last_push_endpoint",
|
"last_push_endpoint",
|
||||||
|
"sound_uri",
|
||||||
-> {
|
-> {
|
||||||
reader.skipValue()
|
reader.skipValue()
|
||||||
continue
|
continue
|
||||||
|
@ -217,20 +219,35 @@ object AppDataExporter {
|
||||||
JsonToken.NULL -> {
|
JsonToken.NULL -> {
|
||||||
reader.skipValue()
|
reader.skipValue()
|
||||||
cv.putNull(name)
|
cv.putNull(name)
|
||||||
|
keys.add(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonToken.BOOLEAN -> cv.put(name, if (reader.nextBoolean()) 1 else 0)
|
JsonToken.BOOLEAN -> {
|
||||||
|
cv.put(name, if (reader.nextBoolean()) 1 else 0)
|
||||||
|
keys.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
JsonToken.NUMBER -> cv.put(name, reader.nextLong())
|
JsonToken.NUMBER -> {
|
||||||
|
cv.put(name, reader.nextLong())
|
||||||
|
keys.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
JsonToken.STRING -> cv.put(name, reader.nextString())
|
JsonToken.STRING -> {
|
||||||
|
cv.put(name, reader.nextString())
|
||||||
|
keys.add(name)
|
||||||
|
}
|
||||||
|
|
||||||
else -> reader.skipValue()
|
else -> {
|
||||||
|
reader.skipValue()
|
||||||
|
log.w("skip $table.$name")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
reader.endObject()
|
reader.endObject()
|
||||||
val new_id = db.replace(table, null, cv)
|
val new_id = db.replace(table, null, cv)
|
||||||
if (new_id == -1L) error("importTable: invalid row_id")
|
if (new_id == -1L) {
|
||||||
|
error("importTable: replace failed. table=$table, names=${keys.joinToString(",")}")
|
||||||
|
}
|
||||||
idMap?.put(old_id, new_id)
|
idMap?.put(old_id, new_id)
|
||||||
}
|
}
|
||||||
reader.endArray()
|
reader.endArray()
|
||||||
|
|
|
@ -18,6 +18,7 @@ import jp.juggler.util.data.*
|
||||||
import jp.juggler.util.log.LogCategory
|
import jp.juggler.util.log.LogCategory
|
||||||
import jp.juggler.util.time.parseTimeIso8601
|
import jp.juggler.util.time.parseTimeIso8601
|
||||||
import kotlinx.coroutines.isActive
|
import kotlinx.coroutines.isActive
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import java.security.Provider
|
import java.security.Provider
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.security.interfaces.ECPublicKey
|
import java.security.interfaces.ECPublicKey
|
||||||
|
@ -88,11 +89,16 @@ class PushMastodon(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params["dh"] != deviceHash) {
|
if (params["dh"] != deviceHash && !isOldSubscription(account, oldEndpointUrl)) {
|
||||||
|
|
||||||
// この端末で作成した購読ではない。
|
// この端末で作成した購読ではない。
|
||||||
// TODO: 古い形式のURLを移行できないか?
|
// TODO: 古い形式のURLを移行できないか?
|
||||||
log.w("deviceHash not match. keep it for other devices. ${account.acct} $oldEndpointUrl")
|
log.w("deviceHash not match. keep it for other devices. ${account.acct} $oldEndpointUrl")
|
||||||
subLog.e(R.string.push_subscription_exists_but_not_created_by_this_device)
|
subLog.e(R.string.push_subscription_exists_but_not_created_by_this_device)
|
||||||
|
daoAccountNotificationStatus.updateSubscriptionError(
|
||||||
|
account.acct,
|
||||||
|
context.getString(R.string.push_subscription_exists_but_not_created_by_this_device)
|
||||||
|
)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -175,6 +181,22 @@ class PushMastodon(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isOldSubscription(account: SavedAccount, url: String): Boolean {
|
||||||
|
// https://mastodon-msg.juggler.jp
|
||||||
|
// /webpushcallback
|
||||||
|
// /{ deviceId(FCM token) }
|
||||||
|
// /{ acct }
|
||||||
|
// /{flags }
|
||||||
|
// /{ client identifier}
|
||||||
|
|
||||||
|
val clientIdentifierOld = url.toHttpUrlOrNull()?.pathSegments?.elementAtOrNull(4)
|
||||||
|
?: return false
|
||||||
|
val installId = prefDevice.installIdV1?.notEmpty() ?: return false
|
||||||
|
val accessToken = account.bearerAccessToken?.notEmpty() ?: return false
|
||||||
|
val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
||||||
|
return clientIdentifier == clientIdentifierOld
|
||||||
|
}
|
||||||
|
|
||||||
private suspend fun isSameAlerts(
|
private suspend fun isSameAlerts(
|
||||||
subLog: SubscriptionLogger,
|
subLog: SubscriptionLogger,
|
||||||
account: SavedAccount,
|
account: SavedAccount,
|
||||||
|
@ -362,7 +384,7 @@ class PushMastodon(
|
||||||
// - notification.user のfull acct がないのでふぁぼ魔ミュートは行えない
|
// - notification.user のfull acct がないのでふぁぼ魔ミュートは行えない
|
||||||
// - テキスト本文のミュートは…部分的には可能
|
// - テキスト本文のミュートは…部分的には可能
|
||||||
|
|
||||||
if(pm.textExpand?.let{TootStatus.muted_word?.matchShort(it)}==true){
|
if (pm.textExpand?.let { TootStatus.muted_word?.matchShort(it) } == true) {
|
||||||
error("muted by text word.")
|
error("muted by text word.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ import jp.juggler.subwaytooter.pref.prefDevice
|
||||||
import jp.juggler.subwaytooter.table.*
|
import jp.juggler.subwaytooter.table.*
|
||||||
import jp.juggler.util.data.*
|
import jp.juggler.util.data.*
|
||||||
import jp.juggler.util.log.LogCategory
|
import jp.juggler.util.log.LogCategory
|
||||||
|
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
|
||||||
import java.security.Provider
|
import java.security.Provider
|
||||||
import java.security.SecureRandom
|
import java.security.SecureRandom
|
||||||
import java.security.interfaces.ECPublicKey
|
import java.security.interfaces.ECPublicKey
|
||||||
|
@ -99,6 +100,10 @@ class PushMisskey(
|
||||||
subLog.i(R.string.push_subscription_app_server_hash_missing_but_ok)
|
subLog.i(R.string.push_subscription_app_server_hash_missing_but_ok)
|
||||||
} else {
|
} else {
|
||||||
subLog.e(R.string.push_subscription_app_server_hash_missing_error)
|
subLog.e(R.string.push_subscription_app_server_hash_missing_error)
|
||||||
|
daoAccountNotificationStatus.updateSubscriptionError(
|
||||||
|
account.acct,
|
||||||
|
context.getString(R.string.push_subscription_app_server_hash_missing_error)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
} else if (willRemoveSubscription) {
|
} else if (willRemoveSubscription) {
|
||||||
|
@ -160,6 +165,22 @@ class PushMisskey(
|
||||||
subLog.i(R.string.push_subscription_completed)
|
subLog.i(R.string.push_subscription_completed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isOldSubscription(account: SavedAccount, url: String): Boolean {
|
||||||
|
// https://mastodon-msg.juggler.jp
|
||||||
|
// /webpushcallback
|
||||||
|
// /{ deviceId(FCM token) }
|
||||||
|
// /{ acct }
|
||||||
|
// /{flags }
|
||||||
|
// /{ client identifier}
|
||||||
|
|
||||||
|
val clientIdentifierOld = url.toHttpUrlOrNull()?.pathSegments?.elementAtOrNull(4)
|
||||||
|
?: return false
|
||||||
|
val installId = prefDevice.installIdV1?.notEmpty() ?: return false
|
||||||
|
val accessToken = account.misskeyApiToken?.notEmpty() ?: return false
|
||||||
|
val clientIdentifier = "$accessToken$installId".digestSHA256Base64Url()
|
||||||
|
return clientIdentifier == clientIdentifierOld
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
https://github.com/syuilo/misskey/blob/master/src/services/create-notification.ts#L46
|
https://github.com/syuilo/misskey/blob/master/src/services/create-notification.ts#L46
|
||||||
Misskeyは通知に既読の概念があり、イベント発生後2秒たっても未読の時だけプッシュ通知が発生する。
|
Misskeyは通知に既読の概念があり、イベント発生後2秒たっても未読の時だけプッシュ通知が発生する。
|
||||||
|
|
|
@ -357,6 +357,10 @@ class PushRepo(
|
||||||
)
|
)
|
||||||
} catch (ex: Throwable) {
|
} catch (ex: Throwable) {
|
||||||
subLog.e(ex, "updateSubscription failed.")
|
subLog.e(ex, "updateSubscription failed.")
|
||||||
|
daoAccountNotificationStatus.updateSubscriptionError(
|
||||||
|
account.acct,
|
||||||
|
ex.withCaption()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
prefDevice.timeLastEndpointRegister = System.currentTimeMillis()
|
prefDevice.timeLastEndpointRegister = System.currentTimeMillis()
|
||||||
|
|
Loading…
Reference in New Issue