mmrelay 1.1.3__py3-none-any.whl → 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of mmrelay might be problematic. Click here for more details.
- mmrelay/__init__.py +1 -1
- mmrelay/cli.py +1097 -110
- mmrelay/cli_utils.py +696 -0
- mmrelay/config.py +632 -44
- mmrelay/constants/__init__.py +54 -0
- mmrelay/constants/app.py +29 -0
- mmrelay/constants/config.py +78 -0
- mmrelay/constants/database.py +22 -0
- mmrelay/constants/formats.py +20 -0
- mmrelay/constants/messages.py +45 -0
- mmrelay/constants/network.py +42 -0
- mmrelay/constants/queue.py +17 -0
- mmrelay/db_utils.py +281 -132
- mmrelay/e2ee_utils.py +392 -0
- mmrelay/log_utils.py +77 -19
- mmrelay/main.py +101 -30
- mmrelay/matrix_utils.py +1083 -118
- mmrelay/meshtastic_utils.py +374 -118
- mmrelay/message_queue.py +17 -17
- mmrelay/plugin_loader.py +126 -91
- mmrelay/plugins/base_plugin.py +74 -15
- mmrelay/plugins/drop_plugin.py +13 -5
- mmrelay/plugins/mesh_relay_plugin.py +7 -10
- mmrelay/plugins/weather_plugin.py +118 -12
- mmrelay/setup_utils.py +67 -30
- mmrelay/tools/sample-docker-compose-prebuilt.yaml +80 -0
- mmrelay/tools/sample-docker-compose.yaml +34 -8
- mmrelay/tools/sample_config.yaml +29 -4
- {mmrelay-1.1.3.dist-info → mmrelay-1.2.0.dist-info}/METADATA +21 -50
- mmrelay-1.2.0.dist-info/RECORD +45 -0
- mmrelay/config_checker.py +0 -133
- mmrelay-1.1.3.dist-info/RECORD +0 -35
- {mmrelay-1.1.3.dist-info → mmrelay-1.2.0.dist-info}/WHEEL +0 -0
- {mmrelay-1.1.3.dist-info → mmrelay-1.2.0.dist-info}/entry_points.txt +0 -0
- {mmrelay-1.1.3.dist-info → mmrelay-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {mmrelay-1.1.3.dist-info → mmrelay-1.2.0.dist-info}/top_level.txt +0 -0
mmrelay/db_utils.py
CHANGED
|
@@ -31,12 +31,9 @@ def clear_db_path_cache():
|
|
|
31
31
|
# Get the database path
|
|
32
32
|
def get_db_path():
|
|
33
33
|
"""
|
|
34
|
-
|
|
34
|
+
Resolves and returns the file path to the SQLite database, using configuration overrides if provided.
|
|
35
35
|
|
|
36
|
-
|
|
37
|
-
If a custom path is specified in the configuration under `database.path` (preferred) or `db.path` (legacy),
|
|
38
|
-
that path is used instead. The resolved path is cached for subsequent calls, and the directory is created
|
|
39
|
-
if it does not exist. Cache is automatically invalidated if the relevant configuration changes.
|
|
36
|
+
Prefers the path specified in `config["database"]["path"]`, falls back to `config["db"]["path"]` (legacy), and defaults to `meshtastic.sqlite` in the standard data directory if neither is set. The resolved path is cached and the cache is invalidated if relevant configuration changes. Attempts to create the directory for the database path if it does not exist.
|
|
40
37
|
"""
|
|
41
38
|
global config, _cached_db_path, _db_path_logged, _cached_config_hash
|
|
42
39
|
|
|
@@ -69,7 +66,13 @@ def get_db_path():
|
|
|
69
66
|
# Ensure the directory exists
|
|
70
67
|
db_dir = os.path.dirname(custom_path)
|
|
71
68
|
if db_dir:
|
|
72
|
-
|
|
69
|
+
try:
|
|
70
|
+
os.makedirs(db_dir, exist_ok=True)
|
|
71
|
+
except (OSError, PermissionError) as e:
|
|
72
|
+
logger.warning(
|
|
73
|
+
f"Could not create database directory {db_dir}: {e}"
|
|
74
|
+
)
|
|
75
|
+
# Continue anyway - the database connection will fail later if needed
|
|
73
76
|
|
|
74
77
|
# Cache the path and log only once
|
|
75
78
|
_cached_db_path = custom_path
|
|
@@ -104,76 +107,128 @@ def get_db_path():
|
|
|
104
107
|
|
|
105
108
|
# Initialize SQLite database
|
|
106
109
|
def initialize_database():
|
|
110
|
+
"""
|
|
111
|
+
Initializes the SQLite database schema for the relay application.
|
|
112
|
+
|
|
113
|
+
Creates required tables (`longnames`, `shortnames`, `plugin_data`, and `message_map`) if they do not exist, and ensures the `meshtastic_meshnet` column is present in `message_map`. Raises an exception if database initialization fails.
|
|
114
|
+
"""
|
|
107
115
|
db_path = get_db_path()
|
|
108
116
|
# Check if database exists
|
|
109
117
|
if os.path.exists(db_path):
|
|
110
118
|
logger.info(f"Loading database from: {db_path}")
|
|
111
119
|
else:
|
|
112
120
|
logger.info(f"Creating new database at: {db_path}")
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
# Attempt to add meshtastic_meshnet column if it's missing (for upgrades)
|
|
133
|
-
# This is a no-op if the column already exists.
|
|
134
|
-
# If user runs fresh, it will already be there from CREATE TABLE IF NOT EXISTS.
|
|
135
|
-
try:
|
|
136
|
-
cursor.execute("ALTER TABLE message_map ADD COLUMN meshtastic_meshnet TEXT")
|
|
137
|
-
except sqlite3.OperationalError:
|
|
138
|
-
# Column already exists, or table just created with it
|
|
139
|
-
pass
|
|
121
|
+
try:
|
|
122
|
+
with sqlite3.connect(db_path) as conn:
|
|
123
|
+
cursor = conn.cursor()
|
|
124
|
+
# Updated table schema: matrix_event_id is now PRIMARY KEY, meshtastic_id is not necessarily unique
|
|
125
|
+
cursor.execute(
|
|
126
|
+
"CREATE TABLE IF NOT EXISTS longnames (meshtastic_id TEXT PRIMARY KEY, longname TEXT)"
|
|
127
|
+
)
|
|
128
|
+
cursor.execute(
|
|
129
|
+
"CREATE TABLE IF NOT EXISTS shortnames (meshtastic_id TEXT PRIMARY KEY, shortname TEXT)"
|
|
130
|
+
)
|
|
131
|
+
cursor.execute(
|
|
132
|
+
"CREATE TABLE IF NOT EXISTS plugin_data (plugin_name TEXT, meshtastic_id TEXT, data TEXT, PRIMARY KEY (plugin_name, meshtastic_id))"
|
|
133
|
+
)
|
|
134
|
+
# Changed the schema for message_map: matrix_event_id is now primary key
|
|
135
|
+
# Added a new column 'meshtastic_meshnet' to store the meshnet origin of the message.
|
|
136
|
+
# If table already exists, we try adding the column if it doesn't exist.
|
|
137
|
+
cursor.execute(
|
|
138
|
+
"CREATE TABLE IF NOT EXISTS message_map (meshtastic_id INTEGER, matrix_event_id TEXT PRIMARY KEY, matrix_room_id TEXT, meshtastic_text TEXT, meshtastic_meshnet TEXT)"
|
|
139
|
+
)
|
|
140
140
|
|
|
141
|
-
|
|
141
|
+
# Attempt to add meshtastic_meshnet column if it's missing (for upgrades)
|
|
142
|
+
# This is a no-op if the column already exists.
|
|
143
|
+
# If user runs fresh, it will already be there from CREATE TABLE IF NOT EXISTS.
|
|
144
|
+
try:
|
|
145
|
+
cursor.execute(
|
|
146
|
+
"ALTER TABLE message_map ADD COLUMN meshtastic_meshnet TEXT"
|
|
147
|
+
)
|
|
148
|
+
except sqlite3.OperationalError:
|
|
149
|
+
# Column already exists, or table just created with it
|
|
150
|
+
pass
|
|
151
|
+
except sqlite3.Error as e:
|
|
152
|
+
logger.error(f"Database initialization failed: {e}")
|
|
153
|
+
raise
|
|
142
154
|
|
|
143
155
|
|
|
144
156
|
def store_plugin_data(plugin_name, meshtastic_id, data):
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
157
|
+
"""
|
|
158
|
+
Store or update JSON-serialized plugin data for a specific plugin and Meshtastic ID in the database.
|
|
159
|
+
|
|
160
|
+
Parameters:
|
|
161
|
+
plugin_name (str): The name of the plugin.
|
|
162
|
+
meshtastic_id (str): The Meshtastic node identifier.
|
|
163
|
+
data (Any): The plugin data to be serialized and stored.
|
|
164
|
+
"""
|
|
165
|
+
try:
|
|
166
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
167
|
+
cursor = conn.cursor()
|
|
168
|
+
cursor.execute(
|
|
169
|
+
"INSERT OR REPLACE INTO plugin_data (plugin_name, meshtastic_id, data) VALUES (?, ?, ?) ON CONFLICT (plugin_name, meshtastic_id) DO UPDATE SET data = ?",
|
|
170
|
+
(plugin_name, meshtastic_id, json.dumps(data), json.dumps(data)),
|
|
171
|
+
)
|
|
172
|
+
conn.commit()
|
|
173
|
+
except sqlite3.Error as e:
|
|
174
|
+
logger.error(
|
|
175
|
+
f"Database error storing plugin data for {plugin_name}, {meshtastic_id}: {e}"
|
|
150
176
|
)
|
|
151
|
-
conn.commit()
|
|
152
177
|
|
|
153
178
|
|
|
154
179
|
def delete_plugin_data(plugin_name, meshtastic_id):
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
180
|
+
"""
|
|
181
|
+
Deletes the plugin data entry for the specified plugin and Meshtastic ID from the database.
|
|
182
|
+
|
|
183
|
+
Parameters:
|
|
184
|
+
plugin_name (str): The name of the plugin whose data should be deleted.
|
|
185
|
+
meshtastic_id (str): The Meshtastic node ID associated with the plugin data.
|
|
186
|
+
"""
|
|
187
|
+
try:
|
|
188
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
189
|
+
cursor = conn.cursor()
|
|
190
|
+
cursor.execute(
|
|
191
|
+
"DELETE FROM plugin_data WHERE plugin_name=? AND meshtastic_id=?",
|
|
192
|
+
(plugin_name, meshtastic_id),
|
|
193
|
+
)
|
|
194
|
+
conn.commit()
|
|
195
|
+
except sqlite3.Error as e:
|
|
196
|
+
logger.error(
|
|
197
|
+
f"Database error deleting plugin data for {plugin_name}, {meshtastic_id}: {e}"
|
|
160
198
|
)
|
|
161
|
-
conn.commit()
|
|
162
199
|
|
|
163
200
|
|
|
164
201
|
# Get the data for a given plugin and Meshtastic ID
|
|
165
202
|
def get_plugin_data_for_node(plugin_name, meshtastic_id):
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
203
|
+
"""
|
|
204
|
+
Retrieve and decode plugin data for a specific plugin and Meshtastic node.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
list: The deserialized plugin data as a list, or an empty list if no data is found or on error.
|
|
208
|
+
"""
|
|
209
|
+
try:
|
|
210
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
211
|
+
cursor = conn.cursor()
|
|
212
|
+
cursor.execute(
|
|
213
|
+
"SELECT data FROM plugin_data WHERE plugin_name=? AND meshtastic_id=?",
|
|
214
|
+
(
|
|
215
|
+
plugin_name,
|
|
216
|
+
meshtastic_id,
|
|
217
|
+
),
|
|
218
|
+
)
|
|
219
|
+
result = cursor.fetchone()
|
|
220
|
+
try:
|
|
221
|
+
return json.loads(result[0] if result else "[]")
|
|
222
|
+
except (json.JSONDecodeError, TypeError) as e:
|
|
223
|
+
logger.error(
|
|
224
|
+
f"Failed to decode JSON data for plugin {plugin_name}, node {meshtastic_id}: {e}"
|
|
225
|
+
)
|
|
226
|
+
return []
|
|
227
|
+
except (MemoryError, sqlite3.Error) as e:
|
|
228
|
+
logger.error(
|
|
229
|
+
f"Database error retrieving plugin data for {plugin_name}, node {meshtastic_id}: {e}"
|
|
174
230
|
)
|
|
175
|
-
|
|
176
|
-
return json.loads(result[0] if result else "[]")
|
|
231
|
+
return []
|
|
177
232
|
|
|
178
233
|
|
|
179
234
|
# Get the data for a given plugin
|
|
@@ -189,26 +244,53 @@ def get_plugin_data(plugin_name):
|
|
|
189
244
|
|
|
190
245
|
# Get the longname for a given Meshtastic ID
|
|
191
246
|
def get_longname(meshtastic_id):
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
|
|
247
|
+
"""
|
|
248
|
+
Retrieve the long name associated with a given Meshtastic ID.
|
|
249
|
+
|
|
250
|
+
Parameters:
|
|
251
|
+
meshtastic_id (str): The Meshtastic node identifier.
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
str or None: The long name if found, otherwise None.
|
|
255
|
+
"""
|
|
256
|
+
try:
|
|
257
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
258
|
+
cursor = conn.cursor()
|
|
259
|
+
cursor.execute(
|
|
260
|
+
"SELECT longname FROM longnames WHERE meshtastic_id=?", (meshtastic_id,)
|
|
261
|
+
)
|
|
262
|
+
result = cursor.fetchone()
|
|
263
|
+
return result[0] if result else None
|
|
264
|
+
except sqlite3.Error as e:
|
|
265
|
+
logger.error(f"Database error retrieving longname for {meshtastic_id}: {e}")
|
|
266
|
+
return None
|
|
199
267
|
|
|
200
268
|
|
|
201
269
|
def save_longname(meshtastic_id, longname):
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
270
|
+
"""
|
|
271
|
+
Insert or update the long name for a given Meshtastic ID in the database.
|
|
272
|
+
|
|
273
|
+
If an entry for the Meshtastic ID already exists, its long name is updated; otherwise, a new entry is created.
|
|
274
|
+
"""
|
|
275
|
+
try:
|
|
276
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
277
|
+
cursor = conn.cursor()
|
|
278
|
+
cursor.execute(
|
|
279
|
+
"INSERT OR REPLACE INTO longnames (meshtastic_id, longname) VALUES (?, ?)",
|
|
280
|
+
(meshtastic_id, longname),
|
|
281
|
+
)
|
|
282
|
+
conn.commit()
|
|
283
|
+
except sqlite3.Error as e:
|
|
284
|
+
logger.error(f"Database error saving longname for {meshtastic_id}: {e}")
|
|
209
285
|
|
|
210
286
|
|
|
211
287
|
def update_longnames(nodes):
|
|
288
|
+
"""
|
|
289
|
+
Updates the long names for all users in the provided nodes dictionary.
|
|
290
|
+
|
|
291
|
+
Parameters:
|
|
292
|
+
nodes (dict): A dictionary of nodes, each containing user information with Meshtastic IDs and long names.
|
|
293
|
+
"""
|
|
212
294
|
if nodes:
|
|
213
295
|
for node in nodes.values():
|
|
214
296
|
user = node.get("user")
|
|
@@ -219,26 +301,54 @@ def update_longnames(nodes):
|
|
|
219
301
|
|
|
220
302
|
|
|
221
303
|
def get_shortname(meshtastic_id):
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
)
|
|
227
|
-
|
|
228
|
-
|
|
304
|
+
"""
|
|
305
|
+
Retrieve the short name associated with a given Meshtastic ID.
|
|
306
|
+
|
|
307
|
+
Parameters:
|
|
308
|
+
meshtastic_id (str): The Meshtastic node ID to look up.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
str or None: The short name if found, or None if not found or on database error.
|
|
312
|
+
"""
|
|
313
|
+
try:
|
|
314
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
315
|
+
cursor = conn.cursor()
|
|
316
|
+
cursor.execute(
|
|
317
|
+
"SELECT shortname FROM shortnames WHERE meshtastic_id=?",
|
|
318
|
+
(meshtastic_id,),
|
|
319
|
+
)
|
|
320
|
+
result = cursor.fetchone()
|
|
321
|
+
return result[0] if result else None
|
|
322
|
+
except sqlite3.Error as e:
|
|
323
|
+
logger.error(f"Database error retrieving shortname for {meshtastic_id}: {e}")
|
|
324
|
+
return None
|
|
229
325
|
|
|
230
326
|
|
|
231
327
|
def save_shortname(meshtastic_id, shortname):
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
328
|
+
"""
|
|
329
|
+
Insert or update the short name for a given Meshtastic ID in the database.
|
|
330
|
+
|
|
331
|
+
If an entry for the Meshtastic ID already exists, its short name is updated; otherwise, a new entry is created.
|
|
332
|
+
"""
|
|
333
|
+
try:
|
|
334
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
335
|
+
cursor = conn.cursor()
|
|
336
|
+
cursor.execute(
|
|
337
|
+
"INSERT OR REPLACE INTO shortnames (meshtastic_id, shortname) VALUES (?, ?)",
|
|
338
|
+
(meshtastic_id, shortname),
|
|
339
|
+
)
|
|
340
|
+
conn.commit()
|
|
341
|
+
except sqlite3.Error as e:
|
|
342
|
+
logger.error(f"Database error saving shortname for {meshtastic_id}: {e}")
|
|
239
343
|
|
|
240
344
|
|
|
241
345
|
def update_shortnames(nodes):
|
|
346
|
+
"""
|
|
347
|
+
Updates the short names for all users in the provided nodes dictionary.
|
|
348
|
+
|
|
349
|
+
Parameters:
|
|
350
|
+
nodes (dict): A dictionary of nodes, each containing user information with Meshtastic IDs and short names.
|
|
351
|
+
"""
|
|
242
352
|
if nodes:
|
|
243
353
|
for node in nodes.values():
|
|
244
354
|
user = node.get("user")
|
|
@@ -256,64 +366,103 @@ def store_message_map(
|
|
|
256
366
|
meshtastic_meshnet=None,
|
|
257
367
|
):
|
|
258
368
|
"""
|
|
259
|
-
Stores a message
|
|
260
|
-
|
|
261
|
-
:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
369
|
+
Stores or updates a mapping between a Meshtastic message and its corresponding Matrix event in the database.
|
|
370
|
+
|
|
371
|
+
Parameters:
|
|
372
|
+
meshtastic_id: The Meshtastic message ID.
|
|
373
|
+
matrix_event_id: The Matrix event ID (primary key).
|
|
374
|
+
matrix_room_id: The Matrix room ID.
|
|
375
|
+
meshtastic_text: The text content of the Meshtastic message.
|
|
376
|
+
meshtastic_meshnet: Optional name of the meshnet where the message originated, used to distinguish remote from local mesh origins.
|
|
267
377
|
"""
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
378
|
+
try:
|
|
379
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
380
|
+
cursor = conn.cursor()
|
|
381
|
+
logger.debug(
|
|
382
|
+
f"Storing message map: meshtastic_id={meshtastic_id}, matrix_event_id={matrix_event_id}, matrix_room_id={matrix_room_id}, meshtastic_text={meshtastic_text}, meshtastic_meshnet={meshtastic_meshnet}"
|
|
383
|
+
)
|
|
384
|
+
cursor.execute(
|
|
385
|
+
"INSERT OR REPLACE INTO message_map (meshtastic_id, matrix_event_id, matrix_room_id, meshtastic_text, meshtastic_meshnet) VALUES (?, ?, ?, ?, ?)",
|
|
386
|
+
(
|
|
387
|
+
meshtastic_id,
|
|
388
|
+
matrix_event_id,
|
|
389
|
+
matrix_room_id,
|
|
390
|
+
meshtastic_text,
|
|
391
|
+
meshtastic_meshnet,
|
|
392
|
+
),
|
|
393
|
+
)
|
|
394
|
+
conn.commit()
|
|
395
|
+
except sqlite3.Error as e:
|
|
396
|
+
logger.error(f"Database error storing message map for {matrix_event_id}: {e}")
|
|
284
397
|
|
|
285
398
|
|
|
286
399
|
def get_message_map_by_meshtastic_id(meshtastic_id):
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
400
|
+
"""
|
|
401
|
+
Retrieve the message mapping entry for a given Meshtastic ID.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
tuple or None: A tuple (matrix_event_id, matrix_room_id, meshtastic_text, meshtastic_meshnet) if found and valid, or None if not found, on malformed data, or if a database error occurs.
|
|
405
|
+
"""
|
|
406
|
+
try:
|
|
407
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
408
|
+
cursor = conn.cursor()
|
|
409
|
+
cursor.execute(
|
|
410
|
+
"SELECT matrix_event_id, matrix_room_id, meshtastic_text, meshtastic_meshnet FROM message_map WHERE meshtastic_id=?",
|
|
411
|
+
(meshtastic_id,),
|
|
412
|
+
)
|
|
413
|
+
result = cursor.fetchone()
|
|
414
|
+
logger.debug(
|
|
415
|
+
f"Retrieved message map by meshtastic_id={meshtastic_id}: {result}"
|
|
416
|
+
)
|
|
417
|
+
if result:
|
|
418
|
+
try:
|
|
419
|
+
# result = (matrix_event_id, matrix_room_id, meshtastic_text, meshtastic_meshnet)
|
|
420
|
+
return result[0], result[1], result[2], result[3]
|
|
421
|
+
except (IndexError, TypeError) as e:
|
|
422
|
+
logger.error(
|
|
423
|
+
f"Malformed data in message_map for meshtastic_id {meshtastic_id}: {e}"
|
|
424
|
+
)
|
|
425
|
+
return None
|
|
426
|
+
return None
|
|
427
|
+
except sqlite3.Error as e:
|
|
428
|
+
logger.error(
|
|
429
|
+
f"Database error retrieving message map for meshtastic_id {meshtastic_id}: {e}"
|
|
296
430
|
)
|
|
297
|
-
if result:
|
|
298
|
-
# result = (matrix_event_id, matrix_room_id, meshtastic_text, meshtastic_meshnet)
|
|
299
|
-
return result[0], result[1], result[2], result[3]
|
|
300
431
|
return None
|
|
301
432
|
|
|
302
433
|
|
|
303
434
|
def get_message_map_by_matrix_event_id(matrix_event_id):
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
435
|
+
"""
|
|
436
|
+
Retrieve the message mapping entry for a given Matrix event ID.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
tuple or None: A tuple (meshtastic_id, matrix_room_id, meshtastic_text, meshtastic_meshnet) if found, or None if not found or on error.
|
|
440
|
+
"""
|
|
441
|
+
try:
|
|
442
|
+
with sqlite3.connect(get_db_path()) as conn:
|
|
443
|
+
cursor = conn.cursor()
|
|
444
|
+
cursor.execute(
|
|
445
|
+
"SELECT meshtastic_id, matrix_room_id, meshtastic_text, meshtastic_meshnet FROM message_map WHERE matrix_event_id=?",
|
|
446
|
+
(matrix_event_id,),
|
|
447
|
+
)
|
|
448
|
+
result = cursor.fetchone()
|
|
449
|
+
logger.debug(
|
|
450
|
+
f"Retrieved message map by matrix_event_id={matrix_event_id}: {result}"
|
|
451
|
+
)
|
|
452
|
+
if result:
|
|
453
|
+
try:
|
|
454
|
+
# result = (meshtastic_id, matrix_room_id, meshtastic_text, meshtastic_meshnet)
|
|
455
|
+
return result[0], result[1], result[2], result[3]
|
|
456
|
+
except (IndexError, TypeError) as e:
|
|
457
|
+
logger.error(
|
|
458
|
+
f"Malformed data in message_map for matrix_event_id {matrix_event_id}: {e}"
|
|
459
|
+
)
|
|
460
|
+
return None
|
|
461
|
+
return None
|
|
462
|
+
except (UnicodeDecodeError, sqlite3.Error) as e:
|
|
463
|
+
logger.error(
|
|
464
|
+
f"Database error retrieving message map for matrix_event_id {matrix_event_id}: {e}"
|
|
313
465
|
)
|
|
314
|
-
if result:
|
|
315
|
-
# result = (meshtastic_id, matrix_room_id, meshtastic_text, meshtastic_meshnet)
|
|
316
|
-
return result[0], result[1], result[2], result[3]
|
|
317
466
|
return None
|
|
318
467
|
|
|
319
468
|
|