Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions app/src/main/java/io/heckel/ntfy/backup/Backuper.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.heckel.ntfy.db.Repository
import io.heckel.ntfy.firebase.FirebaseMessenger
import io.heckel.ntfy.msg.NotificationService
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.topicHash
import io.heckel.ntfy.util.topicUrl
import java.io.InputStreamReader

Expand Down Expand Up @@ -115,9 +116,9 @@ class Backuper(val context: Context) {
repository.addSubscription(subscription)

// Subscribe to Firebase topics
if (s.baseUrl == appBaseUrl) {
messenger.subscribe(s.topic)
}
val firebaseTopic = if (s.baseUrl == appBaseUrl) s.topic else topicHash(s.baseUrl, s.topic)
Log.d(TAG, "Subscribing to Firebase topic $firebaseTopic")
messenger.subscribe(firebaseTopic)

// Create dedicated channels
if (s.dedicatedChannels) {
Expand Down
5 changes: 4 additions & 1 deletion app/src/main/java/io/heckel/ntfy/db/Database.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.room.migration.Migration
import androidx.sqlite.db.SupportSQLiteDatabase
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import io.heckel.ntfy.util.topicHash
import kotlinx.coroutines.flow.Flow
import java.lang.reflect.Type

Expand Down Expand Up @@ -90,7 +91,9 @@ data class SubscriptionWithMetadata(
val totalCount: Int,
val newCount: Int,
val lastActive: Long
)
) {
fun urlHash() = topicHash(baseUrl, topic)
}

@Entity(primaryKeys = ["id", "subscriptionId"])
data class Notification(
Expand Down
10 changes: 10 additions & 0 deletions app/src/main/java/io/heckel/ntfy/db/Repository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ import androidx.appcompat.app.AppCompatDelegate
import androidx.lifecycle.*
import io.heckel.ntfy.util.Log
import io.heckel.ntfy.util.validUrl
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicLong

Expand Down Expand Up @@ -44,6 +47,13 @@ class Repository(private val sharedPrefs: SharedPreferences, private val databas
.map { list -> list.map { Pair(it.id, it.instant) }.toSet() }
}

suspend fun getSubscriptionByHash(topicHash: String): Subscription? {
return toSubscription(
subscriptionDao.listFlow().map { subs -> subs.first { topicHash == it.urlHash() } }
.first()
)
}

suspend fun getSubscriptions(): List<Subscription> {
return toSubscriptionList(subscriptionDao.list())
}
Expand Down
16 changes: 8 additions & 8 deletions app/src/main/java/io/heckel/ntfy/ui/DetailActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
)
repository.addSubscription(subscription)

// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
if (baseUrl == appBaseUrl) {
Log.d(TAG, "Subscribing to Firebase topic $topic")
messenger.subscribe(topic)
}
// Subscribe to Firebase topic (even if instant, just to be sure!)
val firebaseTopic = if (baseUrl == appBaseUrl) topic else topicHash(baseUrl, topic)
Log.d(TAG, "Subscribing to Firebase topic $topic")
messenger.subscribe(firebaseTopic)

// Fetch cached messages
try {
Expand Down Expand Up @@ -608,9 +607,10 @@ class DetailActivity : AppCompatActivity(), ActionMode.Callback, NotificationFra
GlobalScope.launch(Dispatchers.IO) {
repository.removeAllNotifications(subscriptionId)
repository.removeSubscription(subscriptionId)
if (subscriptionBaseUrl == appBaseUrl) {
messenger.unsubscribe(subscriptionTopic)
}

val firebaseTopic = if (subscriptionBaseUrl == appBaseUrl) subscriptionTopic else topicHash(subscriptionBaseUrl, subscriptionTopic)
Log.d(TAG, "Unsubscribing from Firebase topic $firebaseTopic")
messenger.unsubscribe(firebaseTopic)
}
finish()
}
Expand Down
9 changes: 4 additions & 5 deletions app/src/main/java/io/heckel/ntfy/ui/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -466,11 +466,10 @@ class MainActivity : AppCompatActivity(), ActionMode.Callback, AddFragment.Subsc
)
viewModel.add(subscription)

// Subscribe to Firebase topic if ntfy.sh (even if instant, just to be sure!)
if (baseUrl == appBaseUrl) {
Log.d(TAG, "Subscribing to Firebase topic $topic")
messenger.subscribe(topic)
}
// Subscribe to Firebase topic (even if instant, just to be sure!)
val firebaseTopic = if (baseUrl == appBaseUrl) topic else topicHash(baseUrl, topic)
Log.d(TAG, "Subscribing to Firebase topic $firebaseTopic")
messenger.subscribe(firebaseTopic)

// Fetch cached messages
lifecycleScope.launch(Dispatchers.IO) {
Expand Down
1 change: 1 addition & 0 deletions app/src/main/java/io/heckel/ntfy/util/Util.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ fun topicUrlWs(baseUrl: String, topic: String, since: String) = "${topicUrl(base
fun topicUrlAuth(baseUrl: String, topic: String) = "${topicUrl(baseUrl, topic)}/auth"
fun topicUrlJsonPoll(baseUrl: String, topic: String, since: String) = "${topicUrl(baseUrl, topic)}/json?poll=1&since=$since"
fun topicShortUrl(baseUrl: String, topic: String) = shortUrl(topicUrl(baseUrl, topic))
fun topicHash(baseUrl: String, topic: String) = topicUrl(baseUrl, topic).sha256()

fun subscriptionTopicShortUrl(subscription: Subscription) : String {
return topicShortUrl(subscription.baseUrl, subscription.topic)
Expand Down
39 changes: 22 additions & 17 deletions app/src/play/java/io/heckel/ntfy/firebase/FirebaseService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -61,23 +61,28 @@ class FirebaseService : FirebaseMessagingService() {
}

private fun handlePollRequest(remoteMessage: RemoteMessage) {
val baseUrl = getString(R.string.app_base_url) // Everything from Firebase comes from main service URL!
val topic = remoteMessage.data["topic"] ?: return
val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val workName = "${PollWorker.WORK_NAME_ONCE_SINGE_PREFIX}_${baseUrl}_${topic}"
val workManager = WorkManager.getInstance(this)
val workRequest = OneTimeWorkRequest.Builder(PollWorker::class.java)
.setInputData(workDataOf(
PollWorker.INPUT_DATA_BASE_URL to baseUrl,
PollWorker.INPUT_DATA_TOPIC to topic
))
.setConstraints(constraints)
.build()
Log.d(TAG, "Poll request for ${topicShortUrl(baseUrl, topic)} received, scheduling unique poll worker with name $workName")

workManager.enqueueUniqueWork(workName, ExistingWorkPolicy.REPLACE, workRequest)
CoroutineScope(job).launch {
val pollTopic = remoteMessage.data["topic"] ?: return@launch
val subscription = repository.getSubscriptionByHash(pollTopic)
val baseUrl = subscription?.baseUrl ?: getString(R.string.app_base_url)
val topic = subscription?.topic ?: pollTopic

val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build()
val workName = "${PollWorker.WORK_NAME_ONCE_SINGE_PREFIX}_${baseUrl}_${topic}"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo? "SINGE" -> "SINGLE"?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that could be changed in another commit. It was an existing spelling mistake.

val workManager = WorkManager.getInstance(this@FirebaseService)
val workRequest = OneTimeWorkRequest.Builder(PollWorker::class.java)
.setInputData(workDataOf(
PollWorker.INPUT_DATA_BASE_URL to baseUrl,
PollWorker.INPUT_DATA_TOPIC to topic
))
.setConstraints(constraints)
.build()
Log.d(TAG, "Poll request for ${topicShortUrl(baseUrl, topic)} received, scheduling unique poll worker with name $workName")

workManager.enqueueUniqueWork(workName, ExistingWorkPolicy.REPLACE, workRequest)
}
}

private fun handleMessage(remoteMessage: RemoteMessage) {
Expand Down