Skip to content

Commit a9a00cc

Browse files
committed
[gateway] add settings sync with the server
1 parent 1c87842 commit a9a00cc

File tree

7 files changed

+184
-74
lines changed

7 files changed

+184
-74
lines changed

app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayApi.kt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,13 @@ class GatewayApi(
116116
}
117117
}
118118

119+
suspend fun getSettings(token: String): Map<String, *> {
120+
return client.get("$baseUrl/settings") {
121+
bearerAuth(token)
122+
}.body()
123+
}
124+
125+
///////////////////////////////////////////////////////////////////////////
119126
private fun HttpRequestBuilder.bearerAuth(token: String) {
120127
header(HttpHeaders.Authorization, "Bearer $token")
121128
}
@@ -124,6 +131,7 @@ class GatewayApi(
124131
header(HttpHeaders.Authorization, "Basic ${"$username:$password".encodeBase64()}")
125132
}
126133

134+
///////////////////////////////////////////////////////////////////////////
127135
data class DeviceGetResponse(
128136
val externalIp: String,
129137
)

app/src/main/java/me/capcom/smsgateway/modules/gateway/GatewayService.kt

Lines changed: 97 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import me.capcom.smsgateway.modules.events.EventBus
1010
import me.capcom.smsgateway.modules.gateway.events.DeviceRegisteredEvent
1111
import me.capcom.smsgateway.modules.gateway.workers.PullMessagesWorker
1212
import me.capcom.smsgateway.modules.gateway.workers.SendStateWorker
13+
import me.capcom.smsgateway.modules.gateway.workers.SettingsUpdateWorker
1314
import me.capcom.smsgateway.modules.gateway.workers.WebhooksUpdateWorker
1415
import me.capcom.smsgateway.modules.messages.MessagesService
1516
import me.capcom.smsgateway.modules.messages.data.SendParams
@@ -32,33 +33,32 @@ class GatewayService(
3233
settings.privateToken
3334
).also { _api = it }
3435

35-
suspend fun getPublicIP(): String {
36-
return GatewayApi(
37-
settings.serverUrl,
38-
settings.privateToken
39-
)
40-
.getDevice(settings.registrationInfo?.token)
41-
.externalIp
42-
}
43-
36+
//region Start, stop, etc...
4437
fun start(context: Context) {
4538
if (!settings.enabled) return
4639

4740
PushService.register(context)
4841
PullMessagesWorker.start(context)
4942
WebhooksUpdateWorker.start(context)
43+
SettingsUpdateWorker.start(context)
44+
5045
eventsReceiver.start()
5146
}
5247

53-
fun isActiveLiveData(context: Context) = PullMessagesWorker.getStateLiveData(context)
54-
5548
fun stop(context: Context) {
5649
eventsReceiver.stop()
50+
51+
SettingsUpdateWorker.stop(context)
5752
WebhooksUpdateWorker.stop(context)
5853
PullMessagesWorker.stop(context)
54+
5955
this._api = null
6056
}
6157

58+
fun isActiveLiveData(context: Context) = PullMessagesWorker.getStateLiveData(context)
59+
//endregion
60+
61+
//region Account
6262
suspend fun getLoginCode(): GatewayApi.GetUserCodeResponse {
6363
val username = settings.username
6464
?: throw IllegalStateException("Username is not set")
@@ -87,64 +87,9 @@ class GatewayService(
8787
)
8888
)
8989
}
90+
//endregion
9091

91-
///////////////////////////////////////////////////////////////////////////
92-
internal suspend fun getWebHooks(): List<GatewayApi.WebHook> {
93-
val settings = settings.registrationInfo
94-
return if (settings != null) {
95-
api.getWebHooks(settings.token)
96-
} else {
97-
emptyList()
98-
}
99-
}
100-
101-
internal suspend fun sendState(
102-
message: MessageWithRecipients
103-
) {
104-
val settings = settings.registrationInfo ?: return
105-
106-
api.patchMessages(
107-
settings.token,
108-
listOf(
109-
GatewayApi.MessagePatchRequest(
110-
message.message.id,
111-
message.message.state,
112-
message.recipients.map {
113-
GatewayApi.RecipientState(
114-
it.phoneNumber,
115-
it.state,
116-
it.error
117-
)
118-
},
119-
message.states.associate { it.state to Date(it.updatedAt) }
120-
)
121-
)
122-
)
123-
}
124-
125-
internal suspend fun updateDevice(pushToken: String) {
126-
if (!settings.enabled) return
127-
128-
val settings = settings.registrationInfo ?: return
129-
val accessToken = settings.token
130-
131-
api.devicePatch(
132-
accessToken,
133-
GatewayApi.DevicePatchRequest(
134-
settings.id,
135-
pushToken
136-
)
137-
)
138-
139-
events.emit(
140-
DeviceRegisteredEvent.Success(
141-
api.hostname,
142-
settings.login,
143-
settings.password,
144-
)
145-
)
146-
}
147-
92+
//region Device
14893
internal suspend fun registerDevice(
14994
pushToken: String?,
15095
registerMode: RegistrationMode
@@ -204,6 +149,37 @@ class GatewayService(
204149
}
205150
}
206151

152+
internal suspend fun updateDevice(pushToken: String) {
153+
if (!settings.enabled) return
154+
155+
val settings = settings.registrationInfo ?: return
156+
val accessToken = settings.token
157+
158+
api.devicePatch(
159+
accessToken,
160+
GatewayApi.DevicePatchRequest(
161+
settings.id,
162+
pushToken
163+
)
164+
)
165+
166+
events.emit(
167+
DeviceRegisteredEvent.Success(
168+
api.hostname,
169+
settings.login,
170+
settings.password,
171+
)
172+
)
173+
}
174+
175+
sealed class RegistrationMode {
176+
object Anonymous : RegistrationMode()
177+
class WithCredentials(val login: String, val password: String) : RegistrationMode()
178+
class WithCode(val code: String) : RegistrationMode()
179+
}
180+
//endregion
181+
182+
//region Messages
207183
internal suspend fun getNewMessages(context: Context) {
208184
if (!settings.enabled) return
209185
val settings = settings.registrationInfo ?: return
@@ -244,9 +220,58 @@ class GatewayService(
244220
messagesService.enqueueMessage(request)
245221
}
246222

247-
sealed class RegistrationMode {
248-
object Anonymous : RegistrationMode()
249-
class WithCredentials(val login: String, val password: String) : RegistrationMode()
250-
class WithCode(val code: String) : RegistrationMode()
223+
internal suspend fun sendState(
224+
message: MessageWithRecipients
225+
) {
226+
val settings = settings.registrationInfo ?: return
227+
228+
api.patchMessages(
229+
settings.token,
230+
listOf(
231+
GatewayApi.MessagePatchRequest(
232+
message.message.id,
233+
message.message.state,
234+
message.recipients.map {
235+
GatewayApi.RecipientState(
236+
it.phoneNumber,
237+
it.state,
238+
it.error
239+
)
240+
},
241+
message.states.associate { it.state to Date(it.updatedAt) }
242+
)
243+
)
244+
)
245+
}
246+
//endregion
247+
248+
//region Webhooks
249+
internal suspend fun getWebHooks(): List<GatewayApi.WebHook> {
250+
val settings = settings.registrationInfo
251+
return if (settings != null) {
252+
api.getWebHooks(settings.token)
253+
} else {
254+
emptyList()
255+
}
256+
}
257+
//endregion
258+
259+
//region Settings
260+
internal suspend fun getSettings(): Map<String, *>? {
261+
val settings = settings.registrationInfo ?: return null
262+
263+
return api.getSettings(settings.token)
264+
}
265+
//endregion
266+
267+
//region Utility
268+
suspend fun getPublicIP(): String {
269+
return GatewayApi(
270+
settings.serverUrl,
271+
settings.privateToken
272+
)
273+
.getDevice(settings.registrationInfo?.token)
274+
.externalIp
251275
}
276+
//endregion
252277
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package me.capcom.smsgateway.modules.gateway.workers
2+
3+
import android.content.Context
4+
import androidx.work.BackoffPolicy
5+
import androidx.work.Constraints
6+
import androidx.work.CoroutineWorker
7+
import androidx.work.ExistingPeriodicWorkPolicy
8+
import androidx.work.NetworkType
9+
import androidx.work.PeriodicWorkRequestBuilder
10+
import androidx.work.WorkManager
11+
import androidx.work.WorkRequest
12+
import androidx.work.WorkerParameters
13+
import me.capcom.smsgateway.modules.gateway.GatewayService
14+
import me.capcom.smsgateway.modules.settings.SettingsService
15+
import org.koin.core.component.KoinComponent
16+
import org.koin.core.component.get
17+
import java.util.concurrent.TimeUnit
18+
19+
class SettingsUpdateWorker(appContext: Context, params: WorkerParameters) :
20+
CoroutineWorker(appContext, params), KoinComponent {
21+
override suspend fun doWork(): Result {
22+
val gatewaySvc: GatewayService = get()
23+
val settingsSvc: SettingsService = get()
24+
25+
return try {
26+
val settings = gatewaySvc.getSettings()
27+
28+
settings?.let {
29+
settingsSvc.update(settings)
30+
}
31+
32+
Result.success()
33+
} catch (th: Throwable) {
34+
th.printStackTrace()
35+
Result.retry()
36+
}
37+
}
38+
39+
companion object {
40+
private const val NAME = "SettingsUpdateWorker"
41+
42+
fun start(context: Context) {
43+
val work = PeriodicWorkRequestBuilder<SettingsUpdateWorker>(
44+
24,
45+
TimeUnit.HOURS
46+
)
47+
.setBackoffCriteria(
48+
BackoffPolicy.EXPONENTIAL,
49+
WorkRequest.MIN_BACKOFF_MILLIS,
50+
TimeUnit.MILLISECONDS
51+
)
52+
.setConstraints(
53+
Constraints.Builder()
54+
.setRequiredNetworkType(NetworkType.CONNECTED)
55+
.build()
56+
)
57+
.build()
58+
WorkManager.getInstance(context)
59+
.enqueueUniquePeriodicWork(
60+
NAME,
61+
ExistingPeriodicWorkPolicy.REPLACE,
62+
work
63+
)
64+
}
65+
66+
fun stop(context: Context) {
67+
WorkManager.getInstance(context)
68+
.cancelUniqueWork(NAME)
69+
}
70+
}
71+
}

app/src/main/java/me/capcom/smsgateway/modules/localserver/routes/SettingsRoutes.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ class SettingsRoutes(
3535
try {
3636
val settings = call.receive<Map<String, *>>()
3737

38-
settingsService.apply(settings)
38+
settingsService.update(settings)
3939

4040
call.respond(
4141
HttpStatusCode.OK,

app/src/main/java/me/capcom/smsgateway/modules/push/Event.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,7 @@ enum class Event {
1111

1212
@SerializedName("MessagesExportRequested")
1313
MessagesExportRequested,
14+
15+
@SerializedName("SettingsUpdated")
16+
SettingsUpdated,
1417
}

app/src/main/java/me/capcom/smsgateway/modules/settings/SettingsService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class SettingsService(
3232
return settings.mapValues { (it.value as? Exporter)?.export() }
3333
}
3434

35-
fun apply(data: Map<String, *>) {
35+
fun update(data: Map<String, *>) {
3636
data.forEach { (key, value) ->
3737
try {
3838
settings[key]?.let {

app/src/main/java/me/capcom/smsgateway/services/PushService.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import kotlinx.coroutines.launch
1414
import me.capcom.smsgateway.helpers.SettingsHelper
1515
import me.capcom.smsgateway.modules.events.EventBus
1616
import me.capcom.smsgateway.modules.gateway.workers.RegistrationWorker
17+
import me.capcom.smsgateway.modules.gateway.workers.SettingsUpdateWorker
1718
import me.capcom.smsgateway.modules.gateway.workers.WebhooksUpdateWorker
1819
import me.capcom.smsgateway.modules.logs.LogsService
1920
import me.capcom.smsgateway.modules.logs.db.LogEntry
@@ -58,6 +59,8 @@ class PushService : FirebaseMessagingService(), KoinComponent {
5859
payload.since to payload.until
5960
)
6061
}
62+
63+
Event.SettingsUpdated -> SettingsUpdateWorker.start(this)
6164
}
6265
} catch (e: Throwable) {
6366
e.printStackTrace()

0 commit comments

Comments
 (0)