Skip to content

Commit

Permalink
Show relay stats in the notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
greenart7c3 committed Jan 15, 2025
1 parent 02588a3 commit 5e9bd9d
Show file tree
Hide file tree
Showing 3 changed files with 147 additions and 37 deletions.
125 changes: 125 additions & 0 deletions app/src/main/java/com/greenart7c3/nostrsigner/relays/AmberRelayStat.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package com.greenart7c3.nostrsigner.relays

import android.Manifest
import android.app.Notification
import android.app.NotificationManager
import android.content.pm.PackageManager
import android.util.Log
import androidx.core.app.ActivityCompat
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationChannelGroupCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.R
import com.vitorpamplona.ammolite.relays.RelayStats
import kotlinx.coroutines.launch

object AmberRelayStats {
var connected = 0
var available = 0
init {
NostrSigner.getInstance().applicationIOScope.launch {
NostrSigner.getInstance().client.relayStatusFlow().collect {
connected = it.connected
available = it.available
}
}
}
private val innerCache = mutableMapOf<String, AmberRelayStat>()

fun createNotification(): Notification {
val channelId = "ServiceChannel"
val group = NotificationChannelGroupCompat.Builder("ServiceGroup")
.setName(NostrSigner.getInstance().getString(R.string.service))
.setDescription(NostrSigner.getInstance().getString(R.string.service_description))
.build()
val channel = NotificationChannelCompat.Builder(channelId, NotificationManager.IMPORTANCE_DEFAULT)
.setName(NostrSigner.getInstance().getString(R.string.service))
.setDescription(NostrSigner.getInstance().getString(R.string.amber_is_running_in_background))
.setSound(null, null)
.setGroup(group.id)
.build()

val notificationManager = NotificationManagerCompat.from(NostrSigner.getInstance())
notificationManager.createNotificationChannelGroup(group)
notificationManager.createNotificationChannel(channel)

val message = NostrSigner.getInstance().client.getAll().joinToString("\n") {
"${it.url} ${if (it.isConnected()) "connected" else "disconnected"}\n" +
"Ping: ${RelayStats.get(it.url).pingInMs}ms" +
if (get(it.url).sent > 0) {
" Sent: ${get(it.url).sent}"
} else {
"" +
if (get(it.url).received > 0) {
" Received: ${get(it.url).received}"
} else {
"" +
if (get(it.url).failed > 0) {
" Rejected by relay: ${get(it.url).failed}"
} else {
"" +
if (RelayStats.get(it.url).errorCounter > 0) " Error: ${RelayStats.get(it.url).errorCounter}" else ""
}
}
}
}

val notificationBuilder =
NotificationCompat.Builder(NostrSigner.getInstance(), channelId)
.setGroup(group.id)
.setContentTitle("$connected of $available connected relays")
.setStyle(
NotificationCompat.BigTextStyle()
.bigText(message),
)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSmallIcon(R.drawable.ic_notification)

return notificationBuilder.build()
}

fun updateNotification() {
Log.d("ConnectivityService", "updateNotification")
val notificationManager = NotificationManagerCompat.from(NostrSigner.getInstance())
if (ActivityCompat.checkSelfPermission(NostrSigner.getInstance(), Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notificationManager.notify(1, createNotification())
}
}

fun get(url: String): AmberRelayStat = innerCache.getOrPut(url) { AmberRelayStat() }

fun addSent(url: String) {
get(url).addSent()
updateNotification()
}

fun addReceived(url: String) {
get(url).addReceived()
updateNotification()
}

fun addFailed(url: String) {
get(url).addFailed()
updateNotification()
}
}

class AmberRelayStat(
var sent: Long = 0L,
var received: Long = 0L,
var failed: Long = 0L,
) {
fun addSent() {
sent++
}

fun addReceived() {
received++
}

fun addFailed() {
failed++
}
}
Original file line number Diff line number Diff line change
@@ -1,21 +1,15 @@
package com.greenart7c3.nostrsigner.service

import android.app.Notification
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.net.ConnectivityManager
import android.net.Network
import android.net.NetworkCapabilities
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationChannelCompat
import androidx.core.app.NotificationChannelGroupCompat
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import com.greenart7c3.nostrsigner.BuildConfig
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.R
import com.greenart7c3.nostrsigner.relays.AmberRelayStats
import java.util.Timer
import java.util.TimerTask
import kotlinx.coroutines.CoroutineScope
Expand Down Expand Up @@ -93,40 +87,13 @@ class ConnectivityService : Service() {
return null!!
}

private fun createNotification(): Notification {
val channelId = "ServiceChannel"
val group = NotificationChannelGroupCompat.Builder("ServiceGroup")
.setName(getString(R.string.service))
.setDescription(getString(R.string.service_description))
.build()
val channel = NotificationChannelCompat.Builder(channelId, NotificationManager.IMPORTANCE_DEFAULT)
.setName(getString(R.string.service))
.setDescription(getString(R.string.amber_is_running_in_background))
.setSound(null, null)
.setGroup(group.id)
.build()

val notificationManager = NotificationManagerCompat.from(this)
notificationManager.createNotificationChannelGroup(group)
notificationManager.createNotificationChannel(channel)

val notificationBuilder =
NotificationCompat.Builder(this, channelId)
.setGroup(group.id)
.setContentTitle(getString(R.string.amber_is_running_in_background))
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setSmallIcon(R.drawable.ic_notification)

return notificationBuilder.build()
}

override fun onCreate() {
if (isStarted) return

Log.d("ConnectivityService", "onCreate")

isStarted = true
startForeground(1, createNotification())
startForeground(1, AmberRelayStats.createNotification())

@Suppress("KotlinConstantConditions")
if (BuildConfig.FLAVOR != "offline") {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@
*/
package com.greenart7c3.nostrsigner.service

import android.util.Log
import com.greenart7c3.nostrsigner.LocalPreferences
import com.greenart7c3.nostrsigner.NostrSigner
import com.greenart7c3.nostrsigner.checkNotInMainThread
import com.greenart7c3.nostrsigner.database.LogEntity
import com.greenart7c3.nostrsigner.relays.AmberRelayStats
import com.vitorpamplona.ammolite.relays.COMMON_FEED_TYPES
import com.vitorpamplona.ammolite.relays.NostrClient
import com.vitorpamplona.ammolite.relays.NostrDataSource
Expand Down Expand Up @@ -71,6 +73,8 @@ object NotificationDataSource : NostrDataSource(NostrSigner.getInstance().client
relay: Relay,
subscriptionId: String?,
) {
Log.d("NotificationDataSource", "onRelayStateChange: $type")
AmberRelayStats.updateNotification()
scope.launch {
LocalPreferences.currentAccount(NostrSigner.getInstance())?.let { account ->
NostrSigner.getInstance().getDatabase(account).applicationDao().insertLog(
Expand Down Expand Up @@ -125,6 +129,15 @@ object NotificationDataSource : NostrDataSource(NostrSigner.getInstance().client
}
notify(relay, description)
}

override fun onSendResponse(eventId: String, success: Boolean, message: String, relay: Relay) {
if (success) {
AmberRelayStats.addSent(relay.url)
} else {
AmberRelayStats.addFailed(relay.url)
}
super.onSendResponse(eventId, success, message, relay)
}
}

init {
Expand All @@ -149,12 +162,16 @@ object NotificationDataSource : NostrDataSource(NostrSigner.getInstance().client
private fun createNotificationsFilter(): TypedFilter {
var since = TimeUtils.now()
val accounts = LocalPreferences.allSavedAccounts(NostrSigner.getInstance())
var localLatest = 0L
accounts.forEach {
val latest = NostrSigner.getInstance().getDatabase(it.npub).applicationDao().getLatestNotification()
if (latest != null) {
since = latest
if (latest != null && latest > localLatest) {
localLatest = latest + 1
}
}
if (localLatest > 0) {
since = localLatest
}

val pubKeys =
accounts.mapNotNull {
Expand Down Expand Up @@ -183,6 +200,7 @@ object NotificationDataSource : NostrDataSource(NostrSigner.getInstance().client
) {
checkNotInMainThread()
NotificationUtils.getOrCreateDMChannel(NostrSigner.getInstance().applicationContext)
AmberRelayStats.addReceived(relay.url)
eventNotificationConsumer.consume(event)
}

Expand Down

0 comments on commit 5e9bd9d

Please sign in to comment.