mmrelay 1.0.3__py3-none-any.whl → 1.0.4__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/config.py CHANGED
@@ -103,6 +103,32 @@ def get_data_dir():
103
103
  return data_dir
104
104
 
105
105
 
106
+ def get_plugin_data_dir(plugin_name=None):
107
+ """
108
+ Returns the directory for storing plugin-specific data files.
109
+ If plugin_name is provided, returns a plugin-specific subdirectory.
110
+ Creates the directory if it doesn't exist.
111
+
112
+ Example:
113
+ - get_plugin_data_dir() returns ~/.mmrelay/data/plugins/
114
+ - get_plugin_data_dir("my_plugin") returns ~/.mmrelay/data/plugins/my_plugin/
115
+ """
116
+ # Get the base data directory
117
+ base_data_dir = get_data_dir()
118
+
119
+ # Create the plugins directory
120
+ plugins_data_dir = os.path.join(base_data_dir, "plugins")
121
+ os.makedirs(plugins_data_dir, exist_ok=True)
122
+
123
+ # If a plugin name is provided, create and return a plugin-specific directory
124
+ if plugin_name:
125
+ plugin_data_dir = os.path.join(plugins_data_dir, plugin_name)
126
+ os.makedirs(plugin_data_dir, exist_ok=True)
127
+ return plugin_data_dir
128
+
129
+ return plugins_data_dir
130
+
131
+
106
132
  def get_log_dir():
107
133
  """
108
134
  Returns the directory for storing log files.
mmrelay/plugin_loader.py CHANGED
@@ -60,31 +60,332 @@ def clone_or_update_repo(repo_url, tag, plugins_dir):
60
60
  # Extract the repository name from the URL
61
61
  repo_name = os.path.splitext(os.path.basename(repo_url.rstrip("/")))[0]
62
62
  repo_path = os.path.join(plugins_dir, repo_name)
63
+
64
+ # Default branch names to try if tag is not specified
65
+ default_branches = ["main", "master"]
66
+
67
+ # If tag is one of the default branches, we'll handle it as a branch
68
+ is_default_branch = tag in default_branches
69
+
63
70
  if os.path.isdir(repo_path):
64
71
  try:
65
- subprocess.check_call(["git", "-C", repo_path, "fetch"])
66
- subprocess.check_call(["git", "-C", repo_path, "checkout", tag])
67
- subprocess.check_call(["git", "-C", repo_path, "pull", "origin", tag])
68
- logger.info(f"Updated repository {repo_name} to {tag}")
72
+ # Fetch all branches but don't fetch tags to avoid conflicts
73
+ try:
74
+ subprocess.check_call(["git", "-C", repo_path, "fetch", "origin"])
75
+ except subprocess.CalledProcessError as e:
76
+ logger.warning(f"Error fetching from remote: {e}")
77
+ # Continue anyway, we'll try to use what we have
78
+
79
+ # If it's a default branch, handle it differently
80
+ if is_default_branch:
81
+ try:
82
+ # Check if we're already on the right branch
83
+ current_branch = subprocess.check_output(
84
+ ["git", "-C", repo_path, "rev-parse", "--abbrev-ref", "HEAD"],
85
+ universal_newlines=True,
86
+ ).strip()
87
+
88
+ if current_branch == tag:
89
+ # We're on the right branch, just pull
90
+ try:
91
+ subprocess.check_call(
92
+ ["git", "-C", repo_path, "pull", "origin", tag]
93
+ )
94
+ logger.info(f"Updated repository {repo_name} branch {tag}")
95
+ return True
96
+ except subprocess.CalledProcessError as e:
97
+ logger.warning(f"Error pulling branch {tag}: {e}")
98
+ # Continue anyway, we'll use what we have
99
+ return True
100
+ else:
101
+ # Switch to the right branch
102
+ subprocess.check_call(["git", "-C", repo_path, "checkout", tag])
103
+ subprocess.check_call(
104
+ ["git", "-C", repo_path, "pull", "origin", tag]
105
+ )
106
+ logger.info(f"Switched to and updated branch {tag}")
107
+ return True
108
+ except subprocess.CalledProcessError:
109
+ # If we can't checkout the specified branch, try the other default branch
110
+ other_default = "main" if tag == "master" else "master"
111
+ try:
112
+ logger.warning(
113
+ f"Branch {tag} not found, trying {other_default}"
114
+ )
115
+ subprocess.check_call(
116
+ ["git", "-C", repo_path, "checkout", other_default]
117
+ )
118
+ subprocess.check_call(
119
+ ["git", "-C", repo_path, "pull", "origin", other_default]
120
+ )
121
+ logger.info(f"Using {other_default} branch instead of {tag}")
122
+ return True
123
+ except subprocess.CalledProcessError:
124
+ # If that fails too, just use whatever branch we're on
125
+ logger.warning(
126
+ "Could not checkout any default branch, using current branch"
127
+ )
128
+ return True
129
+ else:
130
+ # Handle tag checkout
131
+ # Check if we're already on the correct tag/commit
132
+ try:
133
+ # Get the current commit hash
134
+ current_commit = subprocess.check_output(
135
+ ["git", "-C", repo_path, "rev-parse", "HEAD"],
136
+ universal_newlines=True,
137
+ ).strip()
138
+
139
+ # Get the commit hash for the tag
140
+ tag_commit = None
141
+ try:
142
+ tag_commit = subprocess.check_output(
143
+ ["git", "-C", repo_path, "rev-parse", tag],
144
+ universal_newlines=True,
145
+ ).strip()
146
+ except subprocess.CalledProcessError:
147
+ # Tag doesn't exist locally, we'll need to fetch it
148
+ pass
149
+
150
+ # If we're already at the tag's commit, we're done
151
+ if tag_commit and current_commit == tag_commit:
152
+ logger.info(f"Repository {repo_name} is already at tag {tag}")
153
+ return True
154
+
155
+ # Otherwise, try to checkout the tag
156
+ subprocess.check_call(["git", "-C", repo_path, "checkout", tag])
157
+ logger.info(f"Updated repository {repo_name} to tag {tag}")
158
+ return True
159
+ except subprocess.CalledProcessError:
160
+ # If tag checkout fails, try to fetch it specifically
161
+ logger.warning(
162
+ f"Tag {tag} not found locally, trying to fetch it specifically"
163
+ )
164
+ try:
165
+ # Try to fetch the specific tag, but first remove any existing tag with the same name
166
+ try:
167
+ # Delete the local tag if it exists to avoid conflicts
168
+ subprocess.check_call(
169
+ ["git", "-C", repo_path, "tag", "-d", tag]
170
+ )
171
+ except subprocess.CalledProcessError:
172
+ # Tag doesn't exist locally, which is fine
173
+ pass
174
+
175
+ # Now fetch the tag from remote
176
+ try:
177
+ # Try to fetch the tag
178
+ subprocess.check_call(
179
+ [
180
+ "git",
181
+ "-C",
182
+ repo_path,
183
+ "fetch",
184
+ "origin",
185
+ f"refs/tags/{tag}",
186
+ ]
187
+ )
188
+ except subprocess.CalledProcessError:
189
+ # If that fails, try to fetch the tag without the refs/tags/ prefix
190
+ subprocess.check_call(
191
+ [
192
+ "git",
193
+ "-C",
194
+ repo_path,
195
+ "fetch",
196
+ "origin",
197
+ f"refs/tags/{tag}:refs/tags/{tag}",
198
+ ]
199
+ )
200
+
201
+ subprocess.check_call(["git", "-C", repo_path, "checkout", tag])
202
+ logger.info(f"Successfully fetched and checked out tag {tag}")
203
+ return True
204
+ except subprocess.CalledProcessError:
205
+ # If that fails too, try as a branch
206
+ logger.warning(f"Could not fetch tag {tag}, trying as a branch")
207
+ try:
208
+ subprocess.check_call(
209
+ ["git", "-C", repo_path, "fetch", "origin", tag]
210
+ )
211
+ subprocess.check_call(
212
+ ["git", "-C", repo_path, "checkout", tag]
213
+ )
214
+ subprocess.check_call(
215
+ ["git", "-C", repo_path, "pull", "origin", tag]
216
+ )
217
+ logger.info(
218
+ f"Updated repository {repo_name} to branch {tag}"
219
+ )
220
+ return True
221
+ except subprocess.CalledProcessError:
222
+ # If all else fails, just use a default branch
223
+ logger.warning(
224
+ f"Could not checkout {tag} as tag or branch, trying default branches"
225
+ )
226
+ for default_branch in default_branches:
227
+ try:
228
+ subprocess.check_call(
229
+ [
230
+ "git",
231
+ "-C",
232
+ repo_path,
233
+ "checkout",
234
+ default_branch,
235
+ ]
236
+ )
237
+ subprocess.check_call(
238
+ [
239
+ "git",
240
+ "-C",
241
+ repo_path,
242
+ "pull",
243
+ "origin",
244
+ default_branch,
245
+ ]
246
+ )
247
+ logger.info(
248
+ f"Using {default_branch} instead of {tag}"
249
+ )
250
+ return True
251
+ except subprocess.CalledProcessError:
252
+ continue
253
+
254
+ # If we get here, we couldn't checkout any branch
255
+ logger.warning(
256
+ "Could not checkout any branch, using current state"
257
+ )
258
+ return True
69
259
  except subprocess.CalledProcessError as e:
70
260
  logger.error(f"Error updating repository {repo_name}: {e}")
71
261
  logger.error(
72
262
  f"Please manually git clone the repository {repo_url} into {repo_path}"
73
263
  )
74
- sys.exit(1)
264
+ return False
75
265
  else:
266
+ # Repository doesn't exist yet, clone it
76
267
  try:
77
268
  os.makedirs(plugins_dir, exist_ok=True)
78
- subprocess.check_call(
79
- ["git", "clone", "--branch", tag, repo_url], cwd=plugins_dir
80
- )
81
- logger.info(f"Cloned repository {repo_name} from {repo_url} at {tag}")
269
+
270
+ # If it's a default branch, just clone it directly
271
+ if is_default_branch:
272
+ try:
273
+ # Try to clone with the specified branch
274
+ subprocess.check_call(
275
+ ["git", "clone", "--branch", tag, repo_url], cwd=plugins_dir
276
+ )
277
+ logger.info(
278
+ f"Cloned repository {repo_name} from {repo_url} at branch {tag}"
279
+ )
280
+ return True
281
+ except subprocess.CalledProcessError:
282
+ # If that fails, try the other default branch
283
+ other_default = "main" if tag == "master" else "master"
284
+ try:
285
+ logger.warning(
286
+ f"Could not clone with branch {tag}, trying {other_default}"
287
+ )
288
+ subprocess.check_call(
289
+ ["git", "clone", "--branch", other_default, repo_url],
290
+ cwd=plugins_dir,
291
+ )
292
+ logger.info(
293
+ f"Cloned repository {repo_name} from {repo_url} at branch {other_default}"
294
+ )
295
+ return True
296
+ except subprocess.CalledProcessError:
297
+ # If that fails too, clone without specifying a branch
298
+ logger.warning(
299
+ f"Could not clone with branch {other_default}, cloning default branch"
300
+ )
301
+ subprocess.check_call(
302
+ ["git", "clone", repo_url], cwd=plugins_dir
303
+ )
304
+ logger.info(
305
+ f"Cloned repository {repo_name} from {repo_url} (default branch)"
306
+ )
307
+ return True
308
+ else:
309
+ # It's a tag, try to clone with the tag
310
+ try:
311
+ # Try to clone with the specified tag
312
+ subprocess.check_call(
313
+ ["git", "clone", "--branch", tag, repo_url], cwd=plugins_dir
314
+ )
315
+ logger.info(
316
+ f"Cloned repository {repo_name} from {repo_url} at tag {tag}"
317
+ )
318
+ return True
319
+ except subprocess.CalledProcessError:
320
+ # If that fails, clone without specifying a tag
321
+ logger.warning(
322
+ f"Could not clone with tag {tag}, cloning default branch"
323
+ )
324
+ subprocess.check_call(["git", "clone", repo_url], cwd=plugins_dir)
325
+
326
+ # Then try to fetch and checkout the tag
327
+ try:
328
+ # Try to fetch the tag
329
+ try:
330
+ subprocess.check_call(
331
+ [
332
+ "git",
333
+ "-C",
334
+ repo_path,
335
+ "fetch",
336
+ "origin",
337
+ f"refs/tags/{tag}",
338
+ ]
339
+ )
340
+ except subprocess.CalledProcessError:
341
+ # If that fails, try to fetch the tag without the refs/tags/ prefix
342
+ subprocess.check_call(
343
+ [
344
+ "git",
345
+ "-C",
346
+ repo_path,
347
+ "fetch",
348
+ "origin",
349
+ f"refs/tags/{tag}:refs/tags/{tag}",
350
+ ]
351
+ )
352
+
353
+ # Now checkout the tag
354
+ subprocess.check_call(["git", "-C", repo_path, "checkout", tag])
355
+ logger.info(
356
+ f"Cloned repository {repo_name} and checked out tag {tag}"
357
+ )
358
+ return True
359
+ except subprocess.CalledProcessError:
360
+ # If that fails, try as a branch
361
+ try:
362
+ logger.warning(
363
+ f"Could not checkout {tag} as a tag, trying as a branch"
364
+ )
365
+ subprocess.check_call(
366
+ ["git", "-C", repo_path, "fetch", "origin", tag]
367
+ )
368
+ subprocess.check_call(
369
+ ["git", "-C", repo_path, "checkout", tag]
370
+ )
371
+ logger.info(
372
+ f"Cloned repository {repo_name} and checked out branch {tag}"
373
+ )
374
+ return True
375
+ except subprocess.CalledProcessError:
376
+ logger.warning(
377
+ f"Could not checkout {tag}, using default branch"
378
+ )
379
+ logger.info(
380
+ f"Cloned repository {repo_name} from {repo_url} (default branch)"
381
+ )
382
+ return True
82
383
  except subprocess.CalledProcessError as e:
83
384
  logger.error(f"Error cloning repository {repo_name}: {e}")
84
385
  logger.error(
85
386
  f"Please manually git clone the repository {repo_url} into {repo_path}"
86
387
  )
87
- sys.exit(1)
388
+ return False
88
389
  # Install requirements if requirements.txt exists
89
390
  requirements_path = os.path.join(repo_path, "requirements.txt")
90
391
  if os.path.isfile(requirements_path):
@@ -255,11 +556,16 @@ def load_plugins(passed_config=None):
255
556
  tag = plugin_info.get("tag", "master")
256
557
  if repo_url:
257
558
  # Clone to the user directory by default
258
- clone_or_update_repo(repo_url, tag, community_plugins_dir)
559
+ success = clone_or_update_repo(repo_url, tag, community_plugins_dir)
560
+ if not success:
561
+ logger.warning(
562
+ f"Failed to clone/update plugin {plugin_name}, skipping"
563
+ )
564
+ continue
259
565
  else:
260
566
  logger.error("Repository URL not specified for a community plugin")
261
567
  logger.error("Please specify the repository URL in config.yaml")
262
- sys.exit(1)
568
+ continue
263
569
 
264
570
  # Only load community plugins that are explicitly enabled
265
571
  for plugin_name in active_community_plugins:
@@ -1,3 +1,4 @@
1
+ import os
1
2
  import threading
2
3
  import time
3
4
  from abc import ABC, abstractmethod
@@ -5,6 +6,7 @@ from abc import ABC, abstractmethod
5
6
  import markdown
6
7
  import schedule
7
8
 
9
+ from mmrelay.config import get_plugin_data_dir
8
10
  from mmrelay.db_utils import (
9
11
  delete_plugin_data,
10
12
  get_plugin_data,
@@ -195,6 +197,33 @@ class BasePlugin(ABC):
195
197
  def get_data(self):
196
198
  return get_plugin_data(self.plugin_name)
197
199
 
200
+ def get_plugin_data_dir(self, subdir=None):
201
+ """
202
+ Returns the directory for storing plugin-specific data files.
203
+ Creates the directory if it doesn't exist.
204
+
205
+ Args:
206
+ subdir (str, optional): Optional subdirectory within the plugin's data directory.
207
+ If provided, this subdirectory will be created.
208
+
209
+ Returns:
210
+ str: Path to the plugin's data directory or subdirectory
211
+
212
+ Example:
213
+ self.get_plugin_data_dir() returns ~/.mmrelay/data/plugins/your_plugin_name/
214
+ self.get_plugin_data_dir("data_files") returns ~/.mmrelay/data/plugins/your_plugin_name/data_files/
215
+ """
216
+ # Get the plugin-specific data directory
217
+ plugin_dir = get_plugin_data_dir(self.plugin_name)
218
+
219
+ # If a subdirectory is specified, create and return it
220
+ if subdir:
221
+ subdir_path = os.path.join(plugin_dir, subdir)
222
+ os.makedirs(subdir_path, exist_ok=True)
223
+ return subdir_path
224
+
225
+ return plugin_dir
226
+
198
227
  def matches(self, event):
199
228
  from mmrelay.matrix_utils import bot_command
200
229
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mmrelay
3
- Version: 1.0.3
3
+ Version: 1.0.4
4
4
  Summary: Bridge between Meshtastic mesh networks and Matrix chat rooms
5
5
  Home-page: https://github.com/geoffwhittington/meshtastic-matrix-relay
6
6
  Author: Geoff Whittington, Jeremiah K., and contributors
@@ -1,16 +1,16 @@
1
1
  mmrelay/__init__.py,sha256=8fghAZAeSUb8uIaiit0FGNUWI0ZsBR__QbXNwqNbGtw,588
2
2
  mmrelay/cli.py,sha256=yBYOkCwGYDJ2gRKPoPltxB_PydX1CPNUerVJHcNuHTo,12355
3
- mmrelay/config.py,sha256=OIDxQStuVHyWxsDfnKqt0rr26ETEoZPqHVXReEH3IG8,7006
3
+ mmrelay/config.py,sha256=5VZag8iSc5yLQgvwI76bbpizbtqag74cHnfXCrWHNyA,7910
4
4
  mmrelay/config_checker.py,sha256=UnoHVTXzfdTfFkbmXv9r_Si76v-sxXLb5FOaQSOM45E,4909
5
5
  mmrelay/db_utils.py,sha256=DP2YuKBZtV771wo9X-Z7Ww5txfaIR0inWh1K_oVZ7cA,11430
6
6
  mmrelay/log_utils.py,sha256=FXhaq4WSDHwlqiG3k1BbSxiOl5be4P4Kyr1gsIThOBw,4572
7
7
  mmrelay/main.py,sha256=acgBF-DnL0Rs8MmYAfbNHZ9xjqM3Qc0_oKtATN4iOEE,11085
8
8
  mmrelay/matrix_utils.py,sha256=GkIVj2bbPHtx1emFMwhEhc1SWHcv4UvkuyZYdb-Wnwo,30511
9
9
  mmrelay/meshtastic_utils.py,sha256=Pd0j7mz008ncBDIjRGyHOIb0U3vKq06uXWoJP-csHcQ,23381
10
- mmrelay/plugin_loader.py,sha256=QfSXu4nxxBL_pGttLJGzGki8kRtWbFdtSoD_Qnx2iqU,12758
10
+ mmrelay/plugin_loader.py,sha256=na1fso1jaN_APto3LqtXctTciDEOWMyghzAO6TqH4J8,27839
11
11
  mmrelay/setup_utils.py,sha256=GHttNLoqPwOpjSly0osaCnotPxCq0hfyopsZ2qq313A,14091
12
12
  mmrelay/plugins/__init__.py,sha256=KVMQIXRhe0wlGj4O3IZ0vOIQRKFkfPYejHXhJL17qrc,51
13
- mmrelay/plugins/base_plugin.py,sha256=7tBIARWp9Qc4iAEMcsKiUJh1cbqXHcXAk4dlu1b8SBg,7524
13
+ mmrelay/plugins/base_plugin.py,sha256=hv21tSEYG-AB36aLAFdW9DDKm0NOTRNPpGIO5F3i1ts,8633
14
14
  mmrelay/plugins/debug_plugin.py,sha256=Jziht9Nj_bRO6Rmy7TjfBXaYo5eM3XsenbWFxPpyUs4,443
15
15
  mmrelay/plugins/drop_plugin.py,sha256=ACchX6GfEldqTyvsZVg-5jwbe2-CjENQVVZFnw8SaEM,4618
16
16
  mmrelay/plugins/health_plugin.py,sha256=svV_GfpAVL0QhiVzi3PVZ1mNpsOL1NHSmkRF-Mn_ExE,2250
@@ -21,9 +21,9 @@ mmrelay/plugins/nodes_plugin.py,sha256=RDabzyG5hKG5aYWecsRUcLSjMCCv6Pngmq2Qpld1A
21
21
  mmrelay/plugins/ping_plugin.py,sha256=RTRdgDQUSO33lreDTmWsTlI0L1C3FJrXE0KYqfEWYO0,4017
22
22
  mmrelay/plugins/telemetry_plugin.py,sha256=8SxWv4BLXMUTbiVaD3MjlMMdQyS7S_1OfLlVNAUMSO0,6306
23
23
  mmrelay/plugins/weather_plugin.py,sha256=yoKA_HdFqFEhgYdXqLhvXatLphCyLJFuGUKCR7fILv0,8546
24
- mmrelay-1.0.3.dist-info/licenses/LICENSE,sha256=yceWauM1c0-FHxVplsD7W1-AbSeRaUNlmqT4UO1msBU,1073
25
- mmrelay-1.0.3.dist-info/METADATA,sha256=u2oPLnidTXciajKZyZuk28FaNTYL-Z_JygobFBJwm3I,6953
26
- mmrelay-1.0.3.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
27
- mmrelay-1.0.3.dist-info/entry_points.txt,sha256=SJZwGUOEpQ-qx4H8UL4xKFnKeInGUaZNW1I0ddjK7Ws,45
28
- mmrelay-1.0.3.dist-info/top_level.txt,sha256=B_ZLCRm7NYAmI3PipRUyHGymP-C-q16LSeMGzmqJfo4,8
29
- mmrelay-1.0.3.dist-info/RECORD,,
24
+ mmrelay-1.0.4.dist-info/licenses/LICENSE,sha256=yceWauM1c0-FHxVplsD7W1-AbSeRaUNlmqT4UO1msBU,1073
25
+ mmrelay-1.0.4.dist-info/METADATA,sha256=fZZsYxyfKn-KANTa3l4CIB7aSwkbg7mKAxRB3UL76FA,6953
26
+ mmrelay-1.0.4.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
27
+ mmrelay-1.0.4.dist-info/entry_points.txt,sha256=SJZwGUOEpQ-qx4H8UL4xKFnKeInGUaZNW1I0ddjK7Ws,45
28
+ mmrelay-1.0.4.dist-info/top_level.txt,sha256=B_ZLCRm7NYAmI3PipRUyHGymP-C-q16LSeMGzmqJfo4,8
29
+ mmrelay-1.0.4.dist-info/RECORD,,