|
66 | 66 | from meshtastic.protobuf import admin_pb2, channel_pb2, clientonly_pb2, config_pb2, portnums_pb2, mesh_pb2 |
67 | 67 | from meshtastic.version import get_active_version |
68 | 68 |
|
| 69 | +from meshtastic.message_store import MessageSettings, MessageStore, MessageLog, print_messages |
| 70 | + |
69 | 71 | logger = logging.getLogger(__name__) |
70 | 72 |
|
71 | 73 | # Map dotted preference paths to the protobuf enum that defines their flags. |
@@ -600,6 +602,14 @@ def onConnected(interface): |
600 | 602 | onResponse=interface.getNode(args.dest, False, **getNode_kwargs).onAckNak, |
601 | 603 | portNum=portnums_pb2.PortNum.PRIVATE_APP if args.private else portnums_pb2.PortNum.TEXT_MESSAGE_APP |
602 | 604 | ) |
| 605 | + |
| 606 | + #Save Outbound Messages -- if save enabled |
| 607 | + if mt_config.message_store: |
| 608 | + mt_config.message_store.log_sent( |
| 609 | + args.sendtext, |
| 610 | + destination_id=args.dest, |
| 611 | + channel=channelIndex, |
| 612 | + ) |
603 | 613 | else: |
604 | 614 | meshtastic.util.our_exit( |
605 | 615 | f"Warning: {channelIndex} is not a valid channel. Channel must not be DISABLED." |
@@ -1642,6 +1652,18 @@ def common(): |
1642 | 1652 | mt_config.logfile = logfile |
1643 | 1653 |
|
1644 | 1654 | subscribe() |
| 1655 | + |
| 1656 | + # (after the early arg checks, before any interface is constructed) |
| 1657 | + # Enable? StoreMessages? Call to get bool --> True (Save) |
| 1658 | + message_store = None |
| 1659 | + if handleMessageStoreArgs(args): |
| 1660 | + message_store = MessageStore(MessageLog()) |
| 1661 | + mt_config.message_store = message_store # so onConnected can reach it |
| 1662 | + |
| 1663 | + #Display Messages |
| 1664 | + if handleShowMessagesArgs(args): |
| 1665 | + return |
| 1666 | + |
1645 | 1667 | if args.ble_scan: |
1646 | 1668 | logger.debug("BLE scan starting") |
1647 | 1669 | for x in BLEInterface.scan(): |
@@ -1806,6 +1828,70 @@ def common(): |
1806 | 1828 | # don't call exit, background threads might be running still |
1807 | 1829 | # sys.exit(0) |
1808 | 1830 |
|
| 1831 | +def handleMessageStoreArgs(args) -> bool: |
| 1832 | + """Resolve whether message logging is enabled for this run. |
| 1833 | +
|
| 1834 | + Reads --messages, updates the saved setting for on/off, and returns |
| 1835 | + the effective logging state. Does not attach hooks or exit. |
| 1836 | + """ |
| 1837 | + |
| 1838 | + args = mt_config.args |
| 1839 | + mode = args.messages |
| 1840 | + |
| 1841 | + store = MessageSettings() |
| 1842 | + |
| 1843 | + # No flag: use the saved setting (defaults to off if missing/corrupt) |
| 1844 | + if mode is None: |
| 1845 | + return store.is_enabled() |
| 1846 | + |
| 1847 | + if mode == "on": |
| 1848 | + store.set_enabled(True) # persist |
| 1849 | + return True |
| 1850 | + |
| 1851 | + if mode == "off": |
| 1852 | + store.set_enabled(False) # persist |
| 1853 | + return False |
| 1854 | + |
| 1855 | + if mode == "live": |
| 1856 | + # Log for this run only; saved setting is untouched |
| 1857 | + return True |
| 1858 | + |
| 1859 | + if mode == "status": |
| 1860 | + saved = store.is_enabled() |
| 1861 | + print(f"Message logging is {'ON' if saved else 'OFF'}") |
| 1862 | + return saved |
| 1863 | + |
| 1864 | + return False # unreachable with argparse choices, but safe |
| 1865 | + |
| 1866 | +def handleShowMessagesArgs(args) -> bool: |
| 1867 | + """Handle --show-messages. Returns True if it did, so the caller can stop |
| 1868 | + before any store is created or any connection is attempted.""" |
| 1869 | + |
| 1870 | + args = mt_config.args |
| 1871 | + parser = mt_config.parser |
| 1872 | + |
| 1873 | + mode = getattr(args, "show_messages", None) |
| 1874 | + # |
| 1875 | + if mode is None: |
| 1876 | + return False |
| 1877 | + |
| 1878 | + # Local-only command: refuse anything else that was actually set. |
| 1879 | + # Compare each arg to its parser default so unset flags don't count. |
| 1880 | + allowed = {"show_messages", "dest"} #Exclude dest -- which is set @BRDCST_ADDR |
| 1881 | + others = [ |
| 1882 | + "--" + name.replace("_", "-") |
| 1883 | + for name, value in vars(args).items() |
| 1884 | + if name not in allowed and value != parser.get_default(name) |
| 1885 | + ] |
| 1886 | + if others: |
| 1887 | + meshtastic.util.our_exit( |
| 1888 | + "Error: --show-messages can't be combined with: " + ", ".join(sorted(others)), 1 |
| 1889 | + ) |
| 1890 | + |
| 1891 | + if mode == "all": |
| 1892 | + print_messages() |
| 1893 | + return True |
| 1894 | + |
1809 | 1895 |
|
1810 | 1896 | def addConnectionArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: |
1811 | 1897 | """Add connection specification arguments""" |
@@ -2396,6 +2482,43 @@ def addRemoteAdminArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentPars |
2396 | 2482 |
|
2397 | 2483 | return parser |
2398 | 2484 |
|
| 2485 | + |
| 2486 | +def addMessageArgs(parser: argparse.ArgumentParser) -> argparse.ArgumentParser: |
| 2487 | + """Add message logging / history arguments.""" |
| 2488 | + group = parser.add_argument_group( |
| 2489 | + "Messages", |
| 2490 | + "Persistent text-message logging (client-side JSONL). " |
| 2491 | + ) |
| 2492 | + |
| 2493 | + group.add_argument( |
| 2494 | + "--messages", |
| 2495 | + nargs="?", |
| 2496 | + const="status", |
| 2497 | + default=None, |
| 2498 | + choices=["on", "off", "status", "live"], |
| 2499 | + metavar="on|off|status|live", |
| 2500 | + help=( |
| 2501 | + "on/off: enable or disable message logging (saved) (default off). " |
| 2502 | + "status: show whether logging is on/off. " |
| 2503 | + "live: log messages for this run only, without changing the saved " |
| 2504 | + "setting. Combine with --listen or other commands." |
| 2505 | + ) |
| 2506 | + ) |
| 2507 | + |
| 2508 | + group.add_argument( |
| 2509 | + "--show-messages", |
| 2510 | + nargs="?", |
| 2511 | + const="all", |
| 2512 | + default=None, |
| 2513 | + choices=["all"], |
| 2514 | + help=( |
| 2515 | + "Print stored messages. Currently supports: all." |
| 2516 | + ) |
| 2517 | + ) |
| 2518 | + |
| 2519 | + return parser |
| 2520 | + |
| 2521 | + |
2399 | 2522 | def initParser(): |
2400 | 2523 | """Initialize the command line argument parsing.""" |
2401 | 2524 | parser = mt_config.parser |
@@ -2436,6 +2559,9 @@ def initParser(): |
2436 | 2559 | parser = addRemoteActionArgs(parser) |
2437 | 2560 | parser = addRemoteAdminArgs(parser) |
2438 | 2561 |
|
| 2562 | + #Arguments for Message Parsing |
| 2563 | + parser = addMessageArgs(parser) |
| 2564 | + |
2439 | 2565 | # All the rest of the arguments |
2440 | 2566 | group = parser.add_argument_group("Miscellaneous arguments") |
2441 | 2567 |
|
|
0 commit comments