mmrelay 1.0.5__py3-none-any.whl → 1.0.7__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/cli.py CHANGED
@@ -3,6 +3,7 @@ Command-line interface handling for the Meshtastic Matrix Relay.
3
3
  """
4
4
 
5
5
  import argparse
6
+ import importlib.resources
6
7
  import os
7
8
  import sys
8
9
 
@@ -11,6 +12,7 @@ from yaml.loader import SafeLoader
11
12
 
12
13
  # Import version from package
13
14
  from mmrelay import __version__
15
+ from mmrelay.tools import get_sample_config_path
14
16
 
15
17
 
16
18
  def parse_arguments():
@@ -363,29 +365,65 @@ def generate_sample_config():
363
365
  # Ensure the directory exists
364
366
  os.makedirs(os.path.dirname(target_path), exist_ok=True)
365
367
 
366
- # Try to find the sample config file
367
- # First, check in the package directory
368
- package_dir = os.path.dirname(__file__)
369
- sample_config_path = os.path.join(
370
- os.path.dirname(os.path.dirname(package_dir)), "sample_config.yaml"
371
- )
368
+ # Use the helper function to get the sample config path
369
+ sample_config_path = get_sample_config_path()
372
370
 
373
- # If not found, try the repository root
374
- if not os.path.exists(sample_config_path):
375
- repo_root = os.path.dirname(os.path.dirname(__file__))
376
- sample_config_path = os.path.join(repo_root, "sample_config.yaml")
371
+ if os.path.exists(sample_config_path):
372
+ # Copy the sample config file to the target path
373
+ import shutil
377
374
 
378
- # If still not found, try the current directory
379
- if not os.path.exists(sample_config_path):
380
- sample_config_path = os.path.join(os.getcwd(), "sample_config.yaml")
375
+ shutil.copy2(sample_config_path, target_path)
376
+ print(f"Generated sample config file at: {target_path}")
377
+ print(
378
+ "\nEdit this file with your Matrix and Meshtastic settings before running mmrelay."
379
+ )
380
+ return True
381
+
382
+ # If the helper function failed, try using importlib.resources directly
383
+ try:
384
+ # Try to get the sample config from the package resources
385
+ sample_config_content = (
386
+ importlib.resources.files("mmrelay.tools")
387
+ .joinpath("sample_config.yaml")
388
+ .read_text()
389
+ )
390
+
391
+ # Write the sample config to the target path
392
+ with open(target_path, "w") as f:
393
+ f.write(sample_config_content)
381
394
 
382
- if os.path.exists(sample_config_path):
383
- shutil.copy(sample_config_path, target_path)
384
395
  print(f"Generated sample config file at: {target_path}")
385
396
  print(
386
397
  "\nEdit this file with your Matrix and Meshtastic settings before running mmrelay."
387
398
  )
388
399
  return True
389
- else:
400
+ except (FileNotFoundError, ImportError, OSError) as e:
401
+ print(f"Error accessing sample_config.yaml: {e}")
402
+
403
+ # Fallback to traditional file paths if importlib.resources fails
404
+ # First, check in the package directory
405
+ package_dir = os.path.dirname(__file__)
406
+ sample_config_paths = [
407
+ # Check in the tools subdirectory of the package
408
+ os.path.join(package_dir, "tools", "sample_config.yaml"),
409
+ # Check in the package directory
410
+ os.path.join(package_dir, "sample_config.yaml"),
411
+ # Check in the repository root
412
+ os.path.join(
413
+ os.path.dirname(os.path.dirname(package_dir)), "sample_config.yaml"
414
+ ),
415
+ # Check in the current directory
416
+ os.path.join(os.getcwd(), "sample_config.yaml"),
417
+ ]
418
+
419
+ for path in sample_config_paths:
420
+ if os.path.exists(path):
421
+ shutil.copy(path, target_path)
422
+ print(f"Generated sample config file at: {target_path}")
423
+ print(
424
+ "\nEdit this file with your Matrix and Meshtastic settings before running mmrelay."
425
+ )
426
+ return True
427
+
390
428
  print("Error: Could not find sample_config.yaml")
391
429
  return False
mmrelay/setup_utils.py CHANGED
@@ -5,6 +5,8 @@ This module provides simple functions for managing the systemd user service
5
5
  and generating configuration files.
6
6
  """
7
7
 
8
+ import importlib.resources
9
+
8
10
  # Import version from package
9
11
  import os
10
12
  import shutil
@@ -12,6 +14,8 @@ import subprocess
12
14
  import sys
13
15
  from pathlib import Path
14
16
 
17
+ from mmrelay.tools import get_service_template_path
18
+
15
19
 
16
20
  def get_executable_path():
17
21
  """Get the full path to the mmrelay executable.
@@ -91,42 +95,121 @@ def get_template_service_path():
91
95
  str: The path to the template service file, or None if not found.
92
96
  """
93
97
  # Try to find the service template file
94
- # First, check in the package directory (where it should be after installation)
95
98
  package_dir = os.path.dirname(__file__)
96
- template_path = os.path.join(
97
- os.path.dirname(os.path.dirname(package_dir)), "tools", "mmrelay.service"
98
- )
99
-
100
- # If not found, try the repository root (for development)
101
- if not os.path.exists(template_path):
102
- repo_root = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
103
- template_path = os.path.join(repo_root, "tools", "mmrelay.service")
104
99
 
105
- # If still not found, try the current directory (fallback)
106
- if not os.path.exists(template_path):
107
- template_path = os.path.join(os.getcwd(), "tools", "mmrelay.service")
108
-
109
- if not os.path.exists(template_path):
110
- return None
111
-
112
- return template_path
100
+ # Try to find the service template file in various locations
101
+ template_paths = [
102
+ # Check in the package directory (where it should be after installation)
103
+ os.path.join(package_dir, "mmrelay.service"),
104
+ # Check in a tools subdirectory of the package
105
+ os.path.join(package_dir, "tools", "mmrelay.service"),
106
+ # Check in the data files location (where it should be after installation)
107
+ os.path.join(sys.prefix, "share", "mmrelay", "mmrelay.service"),
108
+ os.path.join(sys.prefix, "share", "mmrelay", "tools", "mmrelay.service"),
109
+ # Check in the user site-packages location
110
+ os.path.join(
111
+ os.path.expanduser("~"), ".local", "share", "mmrelay", "mmrelay.service"
112
+ ),
113
+ os.path.join(
114
+ os.path.expanduser("~"),
115
+ ".local",
116
+ "share",
117
+ "mmrelay",
118
+ "tools",
119
+ "mmrelay.service",
120
+ ),
121
+ # Check one level up from the package directory
122
+ os.path.join(os.path.dirname(package_dir), "tools", "mmrelay.service"),
123
+ # Check two levels up from the package directory (for development)
124
+ os.path.join(
125
+ os.path.dirname(os.path.dirname(package_dir)), "tools", "mmrelay.service"
126
+ ),
127
+ # Check in the repository root (for development)
128
+ os.path.join(
129
+ os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
130
+ "tools",
131
+ "mmrelay.service",
132
+ ),
133
+ # Check in the current directory (fallback)
134
+ os.path.join(os.getcwd(), "tools", "mmrelay.service"),
135
+ ]
136
+
137
+ # Try each path until we find one that exists
138
+ for path in template_paths:
139
+ if os.path.exists(path):
140
+ return path
141
+
142
+ # If we get here, we couldn't find the template
143
+ # Debug output to help diagnose issues
144
+ print("Debug: Could not find mmrelay.service in any of these locations:")
145
+ for path in template_paths:
146
+ print(f" - {path}")
147
+
148
+ # If we get here, we couldn't find the template
149
+ return None
113
150
 
114
151
 
115
152
  def get_template_service_content():
116
153
  """Get the content of the template service file.
117
154
 
118
155
  Returns:
119
- str: The content of the template service file, or None if not found.
156
+ str: The content of the template service file, or a default template if not found.
120
157
  """
121
- template_path = get_template_service_path()
122
- if not template_path:
123
- return None
124
-
125
- # Read the template
126
- with open(template_path, "r") as f:
127
- service_template = f.read()
128
-
129
- return service_template
158
+ # Use the helper function to get the service template path
159
+ template_path = get_service_template_path()
160
+
161
+ if template_path and os.path.exists(template_path):
162
+ # Read the template from file
163
+ try:
164
+ with open(template_path, "r") as f:
165
+ service_template = f.read()
166
+ return service_template
167
+ except Exception as e:
168
+ print(f"Error reading service template file: {e}")
169
+
170
+ # If the helper function failed, try using importlib.resources directly
171
+ try:
172
+ service_template = (
173
+ importlib.resources.files("mmrelay.tools")
174
+ .joinpath("mmrelay.service")
175
+ .read_text()
176
+ )
177
+ return service_template
178
+ except (FileNotFoundError, ImportError, OSError) as e:
179
+ print(f"Error accessing mmrelay.service via importlib.resources: {e}")
180
+
181
+ # Fall back to the file path method
182
+ template_path = get_template_service_path()
183
+ if template_path:
184
+ # Read the template from file
185
+ try:
186
+ with open(template_path, "r") as f:
187
+ service_template = f.read()
188
+ return service_template
189
+ except Exception as e:
190
+ print(f"Error reading service template file: {e}")
191
+
192
+ # If we couldn't find or read the template file, use a default template
193
+ print("Using default service template")
194
+ return """[Unit]
195
+ Description=A Meshtastic <=> Matrix Relay
196
+ After=network-online.target
197
+ Wants=network-online.target
198
+
199
+ [Service]
200
+ Type=simple
201
+ # The mmrelay binary can be installed via pipx or pip
202
+ ExecStart=%h/.local/bin/mmrelay --config %h/.mmrelay/config.yaml --logfile %h/.mmrelay/logs/mmrelay.log
203
+ WorkingDirectory=%h/.mmrelay
204
+ Restart=on-failure
205
+ RestartSec=10
206
+ Environment=PYTHONUNBUFFERED=1
207
+ # Ensure both pipx and pip environments are properly loaded
208
+ Environment=PATH=%h/.local/bin:%h/.local/pipx/venvs/mmrelay/bin:/usr/local/bin:/usr/bin:/bin
209
+
210
+ [Install]
211
+ WantedBy=default.target
212
+ """
130
213
 
131
214
 
132
215
  def is_service_enabled():
@@ -270,6 +353,69 @@ def service_needs_update():
270
353
  return False, "Service file is up to date"
271
354
 
272
355
 
356
+ def check_loginctl_available():
357
+ """Check if loginctl is available on the system.
358
+
359
+ Returns:
360
+ bool: True if loginctl is available, False otherwise.
361
+ """
362
+ try:
363
+ result = subprocess.run(
364
+ ["which", "loginctl"],
365
+ check=False,
366
+ capture_output=True,
367
+ text=True,
368
+ )
369
+ return result.returncode == 0
370
+ except Exception:
371
+ return False
372
+
373
+
374
+ def check_lingering_enabled():
375
+ """Check if user lingering is enabled.
376
+
377
+ Returns:
378
+ bool: True if lingering is enabled, False otherwise.
379
+ """
380
+ try:
381
+ username = os.environ.get("USER", os.environ.get("USERNAME"))
382
+ result = subprocess.run(
383
+ ["loginctl", "show-user", username, "--property=Linger"],
384
+ check=False,
385
+ capture_output=True,
386
+ text=True,
387
+ )
388
+ return result.returncode == 0 and "Linger=yes" in result.stdout
389
+ except Exception:
390
+ return False
391
+
392
+
393
+ def enable_lingering():
394
+ """Enable user lingering using sudo.
395
+
396
+ Returns:
397
+ bool: True if lingering was enabled successfully, False otherwise.
398
+ """
399
+ try:
400
+ username = os.environ.get("USER", os.environ.get("USERNAME"))
401
+ print(f"Enabling lingering for user {username}...")
402
+ result = subprocess.run(
403
+ ["sudo", "loginctl", "enable-linger", username],
404
+ check=False,
405
+ capture_output=True,
406
+ text=True,
407
+ )
408
+ if result.returncode == 0:
409
+ print("Lingering enabled successfully")
410
+ return True
411
+ else:
412
+ print(f"Error enabling lingering: {result.stderr}")
413
+ return False
414
+ except Exception as e:
415
+ print(f"Error enabling lingering: {e}")
416
+ return False
417
+
418
+
273
419
  def install_service():
274
420
  """Install or update the MMRelay user service."""
275
421
  # Check if service already exists
@@ -315,6 +461,27 @@ def install_service():
315
461
 
316
462
  # We don't need to validate the config here as it will be validated when the service starts
317
463
 
464
+ # Check if loginctl is available
465
+ loginctl_available = check_loginctl_available()
466
+ if loginctl_available:
467
+ # Check if user lingering is enabled
468
+ lingering_enabled = check_lingering_enabled()
469
+ if not lingering_enabled:
470
+ print(
471
+ "\nUser lingering is not enabled. This is required for the service to start automatically at boot."
472
+ )
473
+ print(
474
+ "Lingering allows user services to run even when you're not logged in."
475
+ )
476
+ if (
477
+ input(
478
+ "Do you want to enable lingering for your user? (requires sudo) (y/n): "
479
+ )
480
+ .lower()
481
+ .startswith("y")
482
+ ):
483
+ enable_lingering()
484
+
318
485
  # Check if the service is already enabled
319
486
  service_enabled = is_service_enabled()
320
487
  if service_enabled:
@@ -377,6 +544,8 @@ def install_service():
377
544
  print("\nService Status Summary:")
378
545
  print(f" Service File: {service_path}")
379
546
  print(f" Enabled at Boot: {'Yes' if service_enabled else 'No'}")
547
+ if loginctl_available:
548
+ print(f" User Lingering: {'Yes' if check_lingering_enabled() else 'No'}")
380
549
  print(f" Currently Running: {'Yes' if is_service_active() else 'No'}")
381
550
  print("\nService Management Commands:")
382
551
  print_service_commands()
@@ -0,0 +1,28 @@
1
+ """Tools and resources for MMRelay."""
2
+
3
+ import importlib.resources
4
+ import pathlib
5
+
6
+
7
+ def get_sample_config_path():
8
+ """Get the path to the sample config file."""
9
+ try:
10
+ # For Python 3.9+
11
+ return str(
12
+ importlib.resources.files("mmrelay.tools").joinpath("sample_config.yaml")
13
+ )
14
+ except AttributeError:
15
+ # Fallback for older Python versions
16
+ return str(pathlib.Path(__file__).parent / "sample_config.yaml")
17
+
18
+
19
+ def get_service_template_path():
20
+ """Get the path to the service template file."""
21
+ try:
22
+ # For Python 3.9+
23
+ return str(
24
+ importlib.resources.files("mmrelay.tools").joinpath("mmrelay.service")
25
+ )
26
+ except AttributeError:
27
+ # Fallback for older Python versions
28
+ return str(pathlib.Path(__file__).parent / "mmrelay.service")
@@ -0,0 +1,18 @@
1
+ [Unit]
2
+ Description=A Meshtastic <=> Matrix Relay
3
+ After=network-online.target
4
+ Wants=network-online.target
5
+
6
+ [Service]
7
+ Type=simple
8
+ # The mmrelay binary can be installed via pipx or pip
9
+ ExecStart=%h/.local/bin/mmrelay --config %h/.mmrelay/config.yaml --logfile %h/.mmrelay/logs/mmrelay.log
10
+ WorkingDirectory=%h/.mmrelay
11
+ Restart=on-failure
12
+ RestartSec=10
13
+ Environment=PYTHONUNBUFFERED=1
14
+ # Ensure both pipx and pip environments are properly loaded
15
+ Environment=PATH=%h/.local/bin:%h/.local/pipx/venvs/mmrelay/bin:/usr/local/bin:/usr/bin:/bin
16
+
17
+ [Install]
18
+ WantedBy=default.target
@@ -0,0 +1,64 @@
1
+ matrix:
2
+ homeserver: https://example.matrix.org
3
+ access_token: reaalllllyloooooongsecretttttcodeeeeeeforrrrbot # See: https://t2bot.io/docs/access_tokens/
4
+ bot_user_id: "@botuser:example.matrix.org"
5
+
6
+ matrix_rooms: # Needs at least 1 room & channel, but supports all Meshtastic channels
7
+ - id: "#someroomalias:example.matrix.org" # Matrix room aliases & IDs supported
8
+ meshtastic_channel: 0
9
+ - id: "!someroomid:example.matrix.org"
10
+ meshtastic_channel: 2
11
+
12
+ meshtastic:
13
+ connection_type: serial # Choose either "tcp", "serial", or "ble"
14
+ serial_port: /dev/ttyUSB0 # Only used when connection is "serial"
15
+ host: meshtastic.local # Only used when connection is "tcp"
16
+ ble_address: AA:BB:CC:DD:EE:FF # Only used when connection is "ble" - Uses either an address or name from a `meshtastic --ble-scan`
17
+ meshnet_name: Your Meshnet Name # This is displayed in full on Matrix, but is truncated when sent to a Meshnet
18
+ broadcast_enabled: true # Must be set to true to enable Matrix to Meshtastic messages
19
+ detection_sensor: true # Must be set to true to forward messages of Meshtastic's detection sensor module
20
+ plugin_response_delay: 3 # Default response delay in seconds for plugins that respond on the mesh;
21
+ relay_reactions: true # Defaults to false, set to true to enable relay reactions between platforms
22
+
23
+ logging:
24
+ level: info
25
+ #log_to_file: true # Set to true to enable file logging
26
+ #filename: ~/.mmrelay/logs/mmrelay.log # Default location if log_to_file is true
27
+ #max_log_size: 10485760 # 10 MB default if omitted
28
+ #backup_count: 1 # Keeps 1 backup as the default if omitted
29
+ #color_enabled: true # Set to false to disable colored console output
30
+
31
+ #database:
32
+ # path: ~/.mmrelay/data/meshtastic.sqlite # Default location
33
+ # msg_map: # The message map is necessary for the relay_reactions functionality. If `relay_reactions` is set to false, nothing will be saved to the message map.
34
+ # msgs_to_keep: 500 # If set to 0, it will not delete any messages; Defaults to 500
35
+ # wipe_on_restart: true # Clears out the message map when the relay is restarted; Defaults to False
36
+
37
+ # These are core Plugins - Note: Some plugins are experimental and some need maintenance.
38
+ plugins:
39
+ ping:
40
+ active: true
41
+ #channels: [2,3,5] # List of channels the plugin will respond to; DMs are always processed if the plugin is active
42
+ weather:
43
+ active: true
44
+ units: imperial # Options: metric, imperial - Default is metric
45
+ #channels: [] # Empty list, will only respond to DMs
46
+ nodes:
47
+ active: true
48
+ # Does not need to specify channels, as it's a Matrix-only plugin
49
+
50
+ #community-plugins:
51
+ # sample_plugin:
52
+ # active: true
53
+ # repository: https://github.com/username/sample_plugin.git
54
+ # tag: master
55
+ # advanced_plugin:
56
+ # active: false
57
+ # repository: https://github.com/username/advanced_plugin.git
58
+ # tag: v1.2.0
59
+
60
+ #custom-plugins:
61
+ # my_custom_plugin:
62
+ # active: true
63
+ # another_custom_plugin:
64
+ # active: false
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mmrelay
3
- Version: 1.0.5
3
+ Version: 1.0.7
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
@@ -25,6 +25,7 @@ Requires-Dist: schedule==1.2.2
25
25
  Requires-Dist: platformdirs==4.3.7
26
26
  Requires-Dist: py-staticmaps>=0.4.0
27
27
  Requires-Dist: rich==14.0.0
28
+ Requires-Dist: setuptools==80.3.1
28
29
  Dynamic: license-file
29
30
 
30
31
  # M<>M Relay
@@ -67,7 +68,7 @@ For pipx installation instructions, see: [pipx installation guide](https://pipx.
67
68
 
68
69
  - **New Users**: See [INSTRUCTIONS.md](INSTRUCTIONS.md) for setup and configuration
69
70
  - **Existing Users**: See [UPGRADE_TO_V1.md](UPGRADE_TO_V1.md) for migration guidance
70
- - **Configuration**: Review [sample_config.yaml](sample_config.yaml) for examples
71
+ - **Configuration**: Review [sample_config.yaml](src/mmrelay/tools/sample_config.yaml) for examples
71
72
 
72
73
  ### Command-Line Options
73
74
 
@@ -1,5 +1,5 @@
1
1
  mmrelay/__init__.py,sha256=8fghAZAeSUb8uIaiit0FGNUWI0ZsBR__QbXNwqNbGtw,588
2
- mmrelay/cli.py,sha256=yBYOkCwGYDJ2gRKPoPltxB_PydX1CPNUerVJHcNuHTo,12355
2
+ mmrelay/cli.py,sha256=hdPTlcGsXTJC9GEUiScG7b3IFp02B3lwhqgwFpU3NsM,13835
3
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
@@ -8,7 +8,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
10
  mmrelay/plugin_loader.py,sha256=Gg8E_TKqndMQHiVJwtmlIC-jCgcty-5EsX_5JJ6Onvo,36590
11
- mmrelay/setup_utils.py,sha256=GHttNLoqPwOpjSly0osaCnotPxCq0hfyopsZ2qq313A,14091
11
+ mmrelay/setup_utils.py,sha256=N6qdScHKHEMFKDmT1l7dcLDPNTusZXPkyxrLXjFLhRI,19910
12
12
  mmrelay/plugins/__init__.py,sha256=KVMQIXRhe0wlGj4O3IZ0vOIQRKFkfPYejHXhJL17qrc,51
13
13
  mmrelay/plugins/base_plugin.py,sha256=hv21tSEYG-AB36aLAFdW9DDKm0NOTRNPpGIO5F3i1ts,8633
14
14
  mmrelay/plugins/debug_plugin.py,sha256=Jziht9Nj_bRO6Rmy7TjfBXaYo5eM3XsenbWFxPpyUs4,443
@@ -21,9 +21,12 @@ 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.5.dist-info/licenses/LICENSE,sha256=yceWauM1c0-FHxVplsD7W1-AbSeRaUNlmqT4UO1msBU,1073
25
- mmrelay-1.0.5.dist-info/METADATA,sha256=IrC7LB07B_2BqV3oTs-Epo3veb7XYlXE8H1aeD1WMQw,6953
26
- mmrelay-1.0.5.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
27
- mmrelay-1.0.5.dist-info/entry_points.txt,sha256=SJZwGUOEpQ-qx4H8UL4xKFnKeInGUaZNW1I0ddjK7Ws,45
28
- mmrelay-1.0.5.dist-info/top_level.txt,sha256=B_ZLCRm7NYAmI3PipRUyHGymP-C-q16LSeMGzmqJfo4,8
29
- mmrelay-1.0.5.dist-info/RECORD,,
24
+ mmrelay/tools/__init__.py,sha256=WFjDQjdevgg19_zT6iEoL29rvb1JPqYSd8708Jn5D7A,838
25
+ mmrelay/tools/mmrelay.service,sha256=3vqK1VbfXvVftkTrTEOan77aTHeOT36hIAL7HqJsmTg,567
26
+ mmrelay/tools/sample_config.yaml,sha256=iGOoVxELUEJwfmpFxyeWXXS0RWNsErnf8-6LXyIwH2k,3052
27
+ mmrelay-1.0.7.dist-info/licenses/LICENSE,sha256=yceWauM1c0-FHxVplsD7W1-AbSeRaUNlmqT4UO1msBU,1073
28
+ mmrelay-1.0.7.dist-info/METADATA,sha256=zhlJoZilGueyloBZ-n7t7bg2QaMi_xSwjEQXb7SKGZM,7005
29
+ mmrelay-1.0.7.dist-info/WHEEL,sha256=0CuiUZ_p9E4cD6NyLD6UG80LBXYyiSYZOKDm5lp32xk,91
30
+ mmrelay-1.0.7.dist-info/entry_points.txt,sha256=SJZwGUOEpQ-qx4H8UL4xKFnKeInGUaZNW1I0ddjK7Ws,45
31
+ mmrelay-1.0.7.dist-info/top_level.txt,sha256=B_ZLCRm7NYAmI3PipRUyHGymP-C-q16LSeMGzmqJfo4,8
32
+ mmrelay-1.0.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (79.0.1)
2
+ Generator: setuptools (80.3.1)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5