Skip to content

Commit 5c59f8f

Browse files
committed
[localserver] inbox direct access
1 parent 4d6169b commit 5c59f8f

9 files changed

Lines changed: 466 additions & 1 deletion

File tree

app/src/main/assets/api/swagger.json

Lines changed: 273 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -878,6 +878,52 @@
878878
],
879879
"type": "object"
880880
},
881+
"smsgateway.IncomingMessage": {
882+
"properties": {
883+
"contentPreview": {
884+
"description": "Message body preview or metadata",
885+
"type": "string"
886+
},
887+
"createdAt": {
888+
"description": "Message received timestamp",
889+
"format": "date-time",
890+
"type": "string"
891+
},
892+
"id": {
893+
"description": "Incoming message ID",
894+
"type": "string"
895+
},
896+
"recipient": {
897+
"description": "Recipient phone number on the device",
898+
"nullable": true,
899+
"type": "string"
900+
},
901+
"sender": {
902+
"description": "Incoming sender phone number",
903+
"type": "string"
904+
},
905+
"simNumber": {
906+
"description": "SIM slot number",
907+
"nullable": true,
908+
"type": "integer"
909+
},
910+
"subscriptionId": {
911+
"description": "Android subscription ID",
912+
"nullable": true,
913+
"type": "integer"
914+
},
915+
"type": {
916+
"enum": [
917+
"SMS",
918+
"DATA_SMS",
919+
"MMS",
920+
"MMS_DOWNLOADED"
921+
],
922+
"type": "string"
923+
}
924+
},
925+
"type": "object"
926+
},
881927
"smsgateway.TokenRequest": {
882928
"properties": {
883929
"scopes": {
@@ -1954,6 +2000,233 @@
19542000
]
19552001
}
19562002
},
2003+
"/messages/inbox": {
2004+
"get": {
2005+
"description": "Retrieves incoming messages with filtering and pagination.",
2006+
"parameters": [
2007+
{
2008+
"description": "Filter incoming messages by type",
2009+
"in": "query",
2010+
"name": "type",
2011+
"schema": {
2012+
"enum": [
2013+
"SMS",
2014+
"DATA_SMS",
2015+
"MMS",
2016+
"MMS_DOWNLOADED"
2017+
],
2018+
"type": "string"
2019+
}
2020+
},
2021+
{
2022+
"description": "Maximum number of messages to return",
2023+
"in": "query",
2024+
"name": "limit",
2025+
"schema": {
2026+
"default": 50,
2027+
"maximum": 500,
2028+
"minimum": 1,
2029+
"type": "integer"
2030+
}
2031+
},
2032+
{
2033+
"description": "Number of messages to skip",
2034+
"in": "query",
2035+
"name": "offset",
2036+
"schema": {
2037+
"default": 0,
2038+
"minimum": 0,
2039+
"type": "integer"
2040+
}
2041+
},
2042+
{
2043+
"description": "Start of date range (ISO 8601)",
2044+
"in": "query",
2045+
"name": "from",
2046+
"schema": {
2047+
"format": "date-time",
2048+
"type": "string"
2049+
}
2050+
},
2051+
{
2052+
"description": "End of date range (ISO 8601)",
2053+
"in": "query",
2054+
"name": "to",
2055+
"schema": {
2056+
"format": "date-time",
2057+
"type": "string"
2058+
}
2059+
},
2060+
{
2061+
"description": "Device ID",
2062+
"in": "query",
2063+
"name": "deviceId",
2064+
"schema": {
2065+
"type": "string"
2066+
}
2067+
}
2068+
],
2069+
"responses": {
2070+
"200": {
2071+
"content": {
2072+
"application/json": {
2073+
"schema": {
2074+
"items": {
2075+
"$ref": "#/components/schemas/smsgateway.IncomingMessage"
2076+
},
2077+
"type": "array"
2078+
}
2079+
}
2080+
},
2081+
"description": "A list of incoming messages"
2082+
},
2083+
"400": {
2084+
"content": {
2085+
"application/json": {
2086+
"schema": {
2087+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2088+
}
2089+
}
2090+
},
2091+
"description": "Invalid request"
2092+
},
2093+
"401": {
2094+
"content": {
2095+
"application/json": {
2096+
"schema": {
2097+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2098+
}
2099+
}
2100+
},
2101+
"description": "Unauthorized"
2102+
},
2103+
"403": {
2104+
"content": {
2105+
"application/json": {
2106+
"schema": {
2107+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2108+
}
2109+
}
2110+
},
2111+
"description": "Forbidden"
2112+
},
2113+
"500": {
2114+
"content": {
2115+
"application/json": {
2116+
"schema": {
2117+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2118+
}
2119+
}
2120+
},
2121+
"description": "Internal server error"
2122+
}
2123+
},
2124+
"security": [
2125+
{
2126+
"ApiAuth": []
2127+
},
2128+
{
2129+
"JWTAuth": []
2130+
}
2131+
],
2132+
"summary": "Get incoming messages",
2133+
"tags": [
2134+
"User",
2135+
"Messages"
2136+
]
2137+
}
2138+
},
2139+
"/messages/inbox/{id}": {
2140+
"get": {
2141+
"description": "Retrieves a single incoming message by id.",
2142+
"parameters": [
2143+
{
2144+
"description": "Incoming message ID",
2145+
"in": "path",
2146+
"name": "id",
2147+
"required": true,
2148+
"schema": {
2149+
"type": "string"
2150+
}
2151+
}
2152+
],
2153+
"responses": {
2154+
"200": {
2155+
"content": {
2156+
"application/json": {
2157+
"schema": {
2158+
"$ref": "#/components/schemas/smsgateway.IncomingMessage"
2159+
}
2160+
}
2161+
},
2162+
"description": "Incoming message"
2163+
},
2164+
"400": {
2165+
"content": {
2166+
"application/json": {
2167+
"schema": {
2168+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2169+
}
2170+
}
2171+
},
2172+
"description": "Invalid request"
2173+
},
2174+
"401": {
2175+
"content": {
2176+
"application/json": {
2177+
"schema": {
2178+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2179+
}
2180+
}
2181+
},
2182+
"description": "Unauthorized"
2183+
},
2184+
"403": {
2185+
"content": {
2186+
"application/json": {
2187+
"schema": {
2188+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2189+
}
2190+
}
2191+
},
2192+
"description": "Forbidden"
2193+
},
2194+
"404": {
2195+
"content": {
2196+
"application/json": {
2197+
"schema": {
2198+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2199+
}
2200+
}
2201+
},
2202+
"description": "Not found"
2203+
},
2204+
"500": {
2205+
"content": {
2206+
"application/json": {
2207+
"schema": {
2208+
"$ref": "#/components/schemas/smsgateway.ErrorResponse"
2209+
}
2210+
}
2211+
},
2212+
"description": "Internal server error"
2213+
}
2214+
},
2215+
"security": [
2216+
{
2217+
"ApiAuth": []
2218+
},
2219+
{
2220+
"JWTAuth": []
2221+
}
2222+
],
2223+
"summary": "Get incoming message",
2224+
"tags": [
2225+
"User",
2226+
"Messages"
2227+
]
2228+
}
2229+
},
19572230
"/messages/inbox/export": {
19582231
"post": {
19592232
"description": "Initiates process of inbox messages export via webhooks. For each message the `sms:received` webhook will be triggered. The webhooks will be triggered without specific order.",

app/src/main/java/me/capcom/smsgateway/modules/incoming/IncomingMessagesService.kt

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,24 @@ class IncomingMessagesService(
3131
)
3232
}
3333

34+
fun count(type: IncomingMessageType?, from: Long, to: Long): Int {
35+
return repository.count(type, from, to)
36+
}
37+
38+
fun select(
39+
type: IncomingMessageType?,
40+
from: Long,
41+
to: Long,
42+
limit: Int,
43+
offset: Int
44+
): List<IncomingMessage> {
45+
return repository.select(type, from, to, limit, offset)
46+
}
47+
48+
fun getById(id: String): IncomingMessage? {
49+
return repository.selectById(id)
50+
}
51+
3452
private fun buildId(message: InboxMessage): String {
3553
val base = when (message) {
3654
is InboxMessage.MmsHeaders -> message.messageId ?: message.transactionId

app/src/main/java/me/capcom/smsgateway/modules/incoming/db/IncomingMessagesDao.kt

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,37 @@ interface IncomingMessagesDao {
1414
@Query("SELECT * FROM incoming_messages ORDER BY createdAt DESC, id DESC LIMIT :limit")
1515
fun selectLast(limit: Int): LiveData<List<IncomingMessage>>
1616

17+
@Query(
18+
"""
19+
SELECT COUNT(*)
20+
FROM incoming_messages
21+
WHERE (:type IS NULL OR type = :type)
22+
AND createdAt BETWEEN :from AND :to
23+
"""
24+
)
25+
fun count(type: IncomingMessageType?, from: Long, to: Long): Int
26+
27+
@Query(
28+
"""
29+
SELECT *
30+
FROM incoming_messages
31+
WHERE (:type IS NULL OR type = :type)
32+
AND createdAt BETWEEN :from AND :to
33+
ORDER BY createdAt DESC, id DESC
34+
LIMIT :limit OFFSET :offset
35+
"""
36+
)
37+
fun select(
38+
type: IncomingMessageType?,
39+
from: Long,
40+
to: Long,
41+
limit: Int,
42+
offset: Int
43+
): List<IncomingMessage>
44+
45+
@Query("SELECT * FROM incoming_messages WHERE id = :id LIMIT 1")
46+
fun selectById(id: String): IncomingMessage?
47+
1748
@Query(
1849
"""
1950
SELECT

app/src/main/java/me/capcom/smsgateway/modules/incoming/repositories/IncomingMessagesRepository.kt

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,27 @@ import androidx.lifecycle.LiveData
44
import androidx.lifecycle.distinctUntilChanged
55
import me.capcom.smsgateway.modules.incoming.db.IncomingMessage
66
import me.capcom.smsgateway.modules.incoming.db.IncomingMessageTotals
7+
import me.capcom.smsgateway.modules.incoming.db.IncomingMessageType
78
import me.capcom.smsgateway.modules.incoming.db.IncomingMessagesDao
89

910
class IncomingMessagesRepository(private val dao: IncomingMessagesDao) {
1011
fun selectLast(limit: Int): LiveData<List<IncomingMessage>> =
1112
dao.selectLast(limit).distinctUntilChanged()
1213

14+
fun count(type: IncomingMessageType?, from: Long, to: Long): Int =
15+
dao.count(type, from, to)
16+
17+
fun select(
18+
type: IncomingMessageType?,
19+
from: Long,
20+
to: Long,
21+
limit: Int,
22+
offset: Int
23+
): List<IncomingMessage> =
24+
dao.select(type, from, to, limit, offset)
25+
26+
fun selectById(id: String): IncomingMessage? = dao.selectById(id)
27+
1328
val totals: LiveData<IncomingMessageTotals> = dao.getStats().distinctUntilChanged()
1429

1530
fun insert(message: IncomingMessage) = dao.insert(message)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ class WebService : Service() {
169169
call.respond(listOf(device))
170170
}
171171
}
172-
MessagesRoutes(applicationContext, get(), get(), get()).let {
172+
MessagesRoutes(applicationContext, get(), get(), get(), get()).let {
173173
route("/message") {
174174
it.register(this)
175175
}

app/src/main/java/me/capcom/smsgateway/modules/localserver/auth/AuthScopes.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ enum class AuthScopes(val value: String) {
55

66
MessagesSend("messages:send"),
77
MessagesRead("messages:read"),
8+
MessagesReadInbox("messages:read-inbox"),
89
MessagesExport("messages:export"),
910

1011
DevicesList("devices:list"),
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package me.capcom.smsgateway.modules.localserver.domain
2+
3+
typealias GetIncomingMessagesResponse = List<IncomingMessageResponse>

0 commit comments

Comments
 (0)