Add automatic bot functionality

Add basic bot functionality
This commit is contained in:
Jack Kingsman authored and GitHub committed 2026-01-26 21:46:26 -08:00
commit d97fa3703f
22 files changed
+1570 -561

No files matched your search

+248
View File
@@ -0,0 +1,248 @@
"""
Bot execution module for automatic message responses.
This module provides functionality for executing user-defined Python code
in response to incoming messages. The user's code can process message data
and optionally return a response string.
SECURITY WARNING: This executes arbitrary Python code provided by the user.
It should only be enabled on trusted systems where the user understands
the security implications.
"""
import asyncio
import logging
from concurrent.futures import ThreadPoolExecutor
from typing import Any
from fastapi import HTTPException
logger = logging.getLogger(__name__)
# Limit concurrent bot executions to prevent resource exhaustion
_bot_semaphore = asyncio.Semaphore(3)
# Dedicated thread pool for bot execution (separate from default executor)
_bot_executor = ThreadPoolExecutor(max_workers=3, thread_name_prefix="bot_")
# Timeout for bot code execution (seconds)
BOT_EXECUTION_TIMEOUT = 10
def execute_bot_code(
code: str,
sender_name: str | None,
sender_key: str | None,
message_text: str,
is_dm: bool,
channel_key: str | None,
channel_name: str | None,
sender_timestamp: int | None,
path: str | None,
) -> str | None:
"""
Execute user-provided bot code with message context.
The code should define a function:
`bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path)`
that returns either None (no response) or a string (response message).
Args:
code: Python code defining the bot function
sender_name: Display name of the sender (may be None)
sender_key: 64-char hex public key of sender for DMs, None for channel messages
message_text: The message content
is_dm: True for direct messages, False for channel messages
channel_key: 32-char hex channel key for channel messages, None for DMs
channel_name: Channel name (e.g. "#general" with hash), None for DMs
sender_timestamp: Sender's timestamp from the message (may be None)
path: Hex-encoded routing path (may be None)
Returns:
Response string if the bot returns one, None otherwise.
Note: This executes arbitrary code. Only use with trusted input.
"""
if not code or not code.strip():
return None
# Build execution namespace with allowed imports
namespace: dict[str, Any] = {
"__builtins__": __builtins__,
}
try:
# Execute the user's code to define the bot function
exec(code, namespace)
except Exception as e:
logger.warning("Bot code compilation failed: %s", e)
return None
# Check if bot function was defined
if "bot" not in namespace or not callable(namespace["bot"]):
logger.debug("Bot code does not define a callable 'bot' function")
return None
bot_func = namespace["bot"]
try:
# Call the bot function with message context
result = bot_func(
sender_name,
sender_key,
message_text,
is_dm,
channel_key,
channel_name,
sender_timestamp,
path,
)
# Validate result
if result is None:
return None
if isinstance(result, str):
return result if result.strip() else None
logger.debug("Bot function returned non-string: %s", type(result))
return None
except Exception as e:
logger.warning("Bot function execution failed: %s", e)
return None
async def process_bot_response(
response: str,
is_dm: bool,
sender_key: str,
channel_key: str | None,
) -> None:
"""
Send the bot's response message using the existing message sending endpoints.
For DMs, sends a direct message back to the sender.
For channel messages, sends to the same channel.
Args:
response: The response text to send
is_dm: Whether the original message was a DM
sender_key: Public key of the original sender (for DM replies)
channel_key: Channel key for channel message replies
"""
from app.models import SendChannelMessageRequest, SendDirectMessageRequest
from app.routers.messages import send_channel_message, send_direct_message
from app.websocket import broadcast_event
try:
if is_dm:
logger.info("Bot sending DM reply to %s", sender_key[:12])
request = SendDirectMessageRequest(destination=sender_key, text=response)
message = await send_direct_message(request)
# Broadcast to WebSocket (endpoint returns to HTTP caller, bot needs explicit broadcast)
broadcast_event("message", message.model_dump())
elif channel_key:
logger.info("Bot sending channel reply to %s", channel_key[:8])
request = SendChannelMessageRequest(channel_key=channel_key, text=response)
message = await send_channel_message(request)
# Broadcast to WebSocket
broadcast_event("message", message.model_dump())
else:
logger.warning("Cannot send bot response: no destination")
except HTTPException as e:
logger.error("Bot failed to send response: %s", e.detail)
except Exception as e:
logger.error("Bot failed to send response: %s", e)
async def run_bot_for_message(
sender_name: str | None,
sender_key: str | None,
message_text: str,
is_dm: bool,
channel_key: str | None,
channel_name: str | None = None,
sender_timestamp: int | None = None,
path: str | None = None,
is_outgoing: bool = False,
) -> None:
"""
Run the bot for an incoming message if enabled.
This is the main entry point called by message handlers after
a message is successfully decrypted and stored.
Args:
sender_name: Display name of the sender
sender_key: 64-char hex public key of sender (DMs only, None for channels)
message_text: The message content
is_dm: True for direct messages, False for channel messages
channel_key: Channel key for channel messages
channel_name: Channel name (e.g. "#general"), None for DMs
sender_timestamp: Sender's timestamp from the message
path: Hex-encoded routing path
is_outgoing: Whether this is our own outgoing message (skip bot)
"""
# Don't respond to our own outgoing messages
if is_outgoing:
return
# Early check if bot is enabled (will re-check after sleep)
from app.repository import AppSettingsRepository
settings = await AppSettingsRepository.get()
if not settings.bot_enabled or not settings.bot_code:
return
# Try to acquire semaphore (limit concurrent bot executions)
if not _bot_semaphore.locked():
pass # Semaphore available
else:
logger.debug("Bot execution queue full, skipping message")
return
async with _bot_semaphore:
logger.debug(
"Running bot for message from %s (is_dm=%s)",
sender_name or (sender_key[:12] if sender_key else "unknown"),
is_dm,
)
# Wait for the initiating message's retransmissions to propagate through the mesh
await asyncio.sleep(2)
# Re-check settings after sleep (user may have disabled bot)
settings = await AppSettingsRepository.get()
if not settings.bot_enabled or not settings.bot_code:
logger.debug("Bot disabled during wait, skipping")
return
# Execute bot code in a dedicated thread pool with timeout
loop = asyncio.get_event_loop()
try:
response = await asyncio.wait_for(
loop.run_in_executor(
_bot_executor,
execute_bot_code,
settings.bot_code,
sender_name,
sender_key,
message_text,
is_dm,
channel_key,
channel_name,
sender_timestamp,
path,
),
timeout=BOT_EXECUTION_TIMEOUT,
)
except asyncio.TimeoutError:
logger.warning("Bot execution timed out after %ds", BOT_EXECUTION_TIMEOUT)
return
except Exception as e:
logger.warning("Bot execution error: %s", e)
return
# Send response if any
if response:
await process_bot_response(response, is_dm, sender_key or "", channel_key)
+15
View File
@@ -118,6 +118,21 @@ async def on_contact_message(event: "Event") -> None:
if contact:
await ContactRepository.update_last_contacted(contact.public_key, received_at)
# Run bot if enabled (for non-CLI messages)
from app.bot import run_bot_for_message
await run_bot_for_message(
sender_name=contact.name if contact else None,
sender_key=sender_pubkey,
message_text=payload.get("text", ""),
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=payload.get("sender_timestamp"),
path=payload.get("path"),
is_outgoing=False,
)
async def on_rx_log_data(event: "Event") -> None:
"""Store raw RF packet data and process via centralized packet processor.
+35
View File
@@ -114,6 +114,13 @@ async def run_migrations(conn: aiosqlite.Connection) -> int:
await set_version(conn, 11)
applied += 1
# Migration 12: Add bot_enabled and bot_code columns to app_settings
if version < 12:
logger.info("Applying migration 12: add bot settings columns")
await _migrate_012_add_bot_settings(conn)
await set_version(conn, 12)
applied += 1
if applied > 0:
logger.info(
"Applied %d migration(s), schema now at version %d", applied, await get_version(conn)
@@ -680,3 +687,31 @@ async def _migrate_011_add_last_advert_time(conn: aiosqlite.Connection) -> None:
raise
await conn.commit()
async def _migrate_012_add_bot_settings(conn: aiosqlite.Connection) -> None:
"""
Add bot_enabled and bot_code columns to app_settings table.
This enables user-defined Python code to be executed when messages are received,
allowing for custom bot responses.
"""
try:
await conn.execute("ALTER TABLE app_settings ADD COLUMN bot_enabled INTEGER DEFAULT 0")
logger.debug("Added bot_enabled column to app_settings")
except aiosqlite.OperationalError as e:
if "duplicate column" in str(e).lower():
logger.debug("bot_enabled column already exists, skipping")
else:
raise
try:
await conn.execute("ALTER TABLE app_settings ADD COLUMN bot_code TEXT DEFAULT ''")
logger.debug("Added bot_code column to app_settings")
except aiosqlite.OperationalError as e:
if "duplicate column" in str(e).lower():
logger.debug("bot_code column already exists, skipping")
else:
raise
await conn.commit()
+8
View File
@@ -263,3 +263,11 @@ class AppSettings(BaseModel):
default=0,
description="Unix timestamp of last advertisement sent (0 = never)",
)
bot_enabled: bool = Field(
default=False,
description="Whether the message bot is enabled",
)
bot_code: str = Field(
default="",
description="Python code for the message bot function",
)
+46 -2
View File
@@ -47,6 +47,8 @@ async def create_message_from_decrypted(
timestamp: int,
received_at: int | None = None,
path: str | None = None,
channel_name: str | None = None,
trigger_bot: bool = True,
) -> int | None:
"""Create a message record from decrypted channel packet content.
@@ -56,11 +58,13 @@ async def create_message_from_decrypted(
Args:
packet_id: ID of the raw packet being processed
channel_key: Hex string channel key
channel_name: Channel name (e.g. "#general"), for bot context
sender: Sender name (will be prefixed to message) or None
message_text: The decrypted message content
timestamp: Sender timestamp from the packet
received_at: When the packet was received (defaults to now)
path: Hex-encoded routing path (None for historical decryption)
path: Hex-encoded routing path
trigger_bot: Whether to trigger bot response (False for historical decryption)
Returns the message ID if created, None if duplicate.
"""
@@ -162,6 +166,22 @@ async def create_message_from_decrypted(
},
)
# Run bot if enabled (for incoming channel messages, not historical decryption)
if trigger_bot:
from app.bot import run_bot_for_message
await run_bot_for_message(
sender_name=sender,
sender_key=None, # Channel messages don't have a sender public key
message_text=message_text,
is_dm=False,
channel_key=channel_key_normalized,
channel_name=channel_name,
sender_timestamp=timestamp,
path=path,
is_outgoing=False,
)
return msg_id
@@ -173,6 +193,7 @@ async def create_dm_message_from_decrypted(
received_at: int | None = None,
path: str | None = None,
outgoing: bool = False,
trigger_bot: bool = True,
) -> int | None:
"""Create a message record from decrypted direct message packet content.
@@ -185,8 +206,9 @@ async def create_dm_message_from_decrypted(
their_public_key: The contact's full 64-char public key (conversation_key)
our_public_key: Our public key (to determine direction), or None
received_at: When the packet was received (defaults to now)
path: Hex-encoded routing path (None for historical decryption)
path: Hex-encoded routing path
outgoing: Whether this is an outgoing message (we sent it)
trigger_bot: Whether to trigger bot response (False for historical decryption)
Returns the message ID if created, None if duplicate.
"""
@@ -289,6 +311,26 @@ async def create_dm_message_from_decrypted(
# Update contact's last_contacted timestamp (for sorting)
await ContactRepository.update_last_contacted(conversation_key, received)
# Run bot if enabled (for incoming DMs only, not historical decryption or outgoing)
if trigger_bot and not outgoing:
from app.bot import run_bot_for_message
# Get contact name for the bot
contact = await ContactRepository.get_by_key(their_public_key)
sender_name = contact.name if contact else None
await run_bot_for_message(
sender_name=sender_name,
sender_key=their_public_key,
message_text=decrypted.message,
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=decrypted.timestamp,
path=path,
is_outgoing=False,
)
return msg_id
@@ -341,6 +383,7 @@ async def run_historical_dm_decryption(
received_at=packet_timestamp,
path=path_hex,
outgoing=outgoing,
trigger_bot=False, # Historical decryption should not trigger bot
)
if msg_id is not None:
@@ -535,6 +578,7 @@ async def _process_group_text(
msg_id = await create_message_from_decrypted(
packet_id=packet_id,
channel_key=channel.key,
channel_name=channel.name,
sender=decrypted.sender,
message_text=decrypted.message,
timestamp=decrypted.timestamp,
+13 -1
View File
@@ -682,7 +682,7 @@ class AppSettingsRepository:
"""
SELECT max_radio_contacts, favorites, auto_decrypt_dm_on_advert,
sidebar_sort_order, last_message_times, preferences_migrated,
advert_interval, last_advert_time
advert_interval, last_advert_time, bot_enabled, bot_code
FROM app_settings WHERE id = 1
"""
)
@@ -732,6 +732,8 @@ class AppSettingsRepository:
preferences_migrated=bool(row["preferences_migrated"]),
advert_interval=row["advert_interval"] or 0,
last_advert_time=row["last_advert_time"] or 0,
bot_enabled=bool(row["bot_enabled"]),
bot_code=row["bot_code"] or "",
)
@staticmethod
@@ -744,6 +746,8 @@ class AppSettingsRepository:
preferences_migrated: bool | None = None,
advert_interval: int | None = None,
last_advert_time: int | None = None,
bot_enabled: bool | None = None,
bot_code: str | None = None,
) -> AppSettings:
"""Update app settings. Only provided fields are updated."""
updates = []
@@ -782,6 +786,14 @@ class AppSettingsRepository:
updates.append("last_advert_time = ?")
params.append(last_advert_time)
if bot_enabled is not None:
updates.append("bot_enabled = ?")
params.append(1 if bot_enabled else 0)
if bot_code is not None:
updates.append("bot_code = ?")
params.append(bot_code)
if updates:
query = f"UPDATE app_settings SET {', '.join(updates)} WHERE id = 1"
await db.conn.execute(query, params)
+2
View File
@@ -63,11 +63,13 @@ async def _run_historical_channel_decryption(
msg_id = await create_message_from_decrypted(
packet_id=packet_id,
channel_key=channel_key_hex,
channel_name=display_name,
sender=result.sender,
message_text=result.message,
timestamp=result.timestamp,
received_at=packet_timestamp,
path=path_hex,
trigger_bot=False, # Historical decryption should not trigger bot
)
if msg_id is not None:
+32 -1
View File
@@ -1,7 +1,7 @@
import logging
from typing import Literal
from fastapi import APIRouter
from fastapi import APIRouter, HTTPException
from pydantic import BaseModel, Field
from app.models import AppSettings
@@ -11,6 +11,20 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/settings", tags=["settings"])
def validate_bot_code(code: str) -> None:
"""Validate bot code syntax. Raises HTTPException on error."""
if not code or not code.strip():
return # Empty code is valid (disables bot)
try:
compile(code, "<bot_code>", "exec")
except SyntaxError as e:
raise HTTPException(
status_code=400,
detail=f"Bot code syntax error at line {e.lineno}: {e.msg}",
) from None
class AppSettingsUpdate(BaseModel):
max_radio_contacts: int | None = Field(
default=None,
@@ -31,6 +45,14 @@ class AppSettingsUpdate(BaseModel):
ge=0,
description="Periodic advertisement interval in seconds (0 = disabled)",
)
bot_enabled: bool | None = Field(
default=None,
description="Whether the message bot is enabled",
)
bot_code: str | None = Field(
default=None,
description="Python code for the message bot function",
)
class FavoriteRequest(BaseModel):
@@ -94,6 +116,15 @@ async def update_settings(update: AppSettingsUpdate) -> AppSettings:
logger.info("Updating advert_interval to %d", update.advert_interval)
kwargs["advert_interval"] = update.advert_interval
if update.bot_enabled is not None:
logger.info("Updating bot_enabled to %s", update.bot_enabled)
kwargs["bot_enabled"] = update.bot_enabled
if update.bot_code is not None:
validate_bot_code(update.bot_code)
logger.info("Updating bot_code (length=%d)", len(update.bot_code))
kwargs["bot_code"] = update.bot_code
if kwargs:
return await AppSettingsRepository.update(**kwargs)
+1
View File
@@ -0,0 +1 @@
code[class*=language-],pre[class*=language-]{color:#ccc;background:none;font-family:Consolas,Monaco,Andale Mono,Ubuntu Mono,monospace;font-size:1em;text-align:left;white-space:pre;word-spacing:normal;word-break:normal;word-wrap:normal;line-height:1.5;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-hyphens:none;hyphens:none}pre[class*=language-]{padding:1em;margin:.5em 0;overflow:auto}:not(pre)>code[class*=language-],pre[class*=language-]{background:#2d2d2d}:not(pre)>code[class*=language-]{padding:.1em;border-radius:.3em;white-space:normal}.token.comment,.token.block-comment,.token.prolog,.token.doctype,.token.cdata{color:#999}.token.punctuation{color:#ccc}.token.tag,.token.attr-name,.token.namespace,.token.deleted{color:#e2777a}.token.function-name{color:#6196cc}.token.boolean,.token.number,.token.function{color:#f08d49}.token.property,.token.class-name,.token.constant,.token.symbol{color:#f8c555}.token.selector,.token.important,.token.atrule,.token.keyword,.token.builtin{color:#cc99cd}.token.string,.token.char,.token.attr-value,.token.regex,.token.variable{color:#7ec699}.token.operator,.token.entity,.token.url{color:#67cdcc}.token.important,.token.bold{font-weight:700}.token.italic{font-style:italic}.token.entity{cursor:help}.token.inserted{color:green}.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane>svg,.leaflet-pane>canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-tile::-moz-selection{background:transparent}.leaflet-tile::selection{background:transparent}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-overlay-pane svg{max-width:none!important;max-height:none!important}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer,.leaflet-container .leaflet-tile{max-width:none!important;max-height:none!important;width:auto;padding:0}.leaflet-container img.leaflet-tile{mix-blend-mode:plus-lighter}.leaflet-container.leaflet-touch-zoom{touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{touch-action:none;touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{touch-action:none}.leaflet-container{-webkit-tap-highlight-color:transparent}.leaflet-container a{-webkit-tap-highlight-color:rgba(51,181,229,.4)}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;box-sizing:border-box;z-index:800}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:visiblePainted;pointer-events:auto}.leaflet-top,.leaflet-bottom{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-popup{opacity:0;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{transform-origin:0 0}svg.leaflet-zoom-animated{will-change:transform}.leaflet-zoom-anim .leaflet-zoom-animated{transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile{transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-popup-pane,.leaflet-control{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:grabbing}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-image-layer,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-marker-icon.leaflet-interactive,.leaflet-image-layer.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive,sLine truncated
-1
View File
@@ -1 +0,0 @@
.leaflet-pane,.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-tile-container,.leaflet-pane>svg,.leaflet-pane>canvas,.leaflet-zoom-box,.leaflet-image-layer,.leaflet-layer{position:absolute;left:0;top:0}.leaflet-container{overflow:hidden}.leaflet-tile,.leaflet-marker-icon,.leaflet-marker-shadow{-webkit-user-select:none;-moz-user-select:none;user-select:none;-webkit-user-drag:none}.leaflet-tile::-moz-selection{background:transparent}.leaflet-tile::selection{background:transparent}.leaflet-safari .leaflet-tile{image-rendering:-webkit-optimize-contrast}.leaflet-safari .leaflet-tile-container{width:1600px;height:1600px;-webkit-transform-origin:0 0}.leaflet-marker-icon,.leaflet-marker-shadow{display:block}.leaflet-container .leaflet-overlay-pane svg{max-width:none!important;max-height:none!important}.leaflet-container .leaflet-marker-pane img,.leaflet-container .leaflet-shadow-pane img,.leaflet-container .leaflet-tile-pane img,.leaflet-container img.leaflet-image-layer,.leaflet-container .leaflet-tile{max-width:none!important;max-height:none!important;width:auto;padding:0}.leaflet-container img.leaflet-tile{mix-blend-mode:plus-lighter}.leaflet-container.leaflet-touch-zoom{touch-action:pan-x pan-y}.leaflet-container.leaflet-touch-drag{touch-action:none;touch-action:pinch-zoom}.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom{touch-action:none}.leaflet-container{-webkit-tap-highlight-color:transparent}.leaflet-container a{-webkit-tap-highlight-color:rgba(51,181,229,.4)}.leaflet-tile{filter:inherit;visibility:hidden}.leaflet-tile-loaded{visibility:inherit}.leaflet-zoom-box{width:0;height:0;box-sizing:border-box;z-index:800}.leaflet-overlay-pane svg{-moz-user-select:none}.leaflet-pane{z-index:400}.leaflet-tile-pane{z-index:200}.leaflet-overlay-pane{z-index:400}.leaflet-shadow-pane{z-index:500}.leaflet-marker-pane{z-index:600}.leaflet-tooltip-pane{z-index:650}.leaflet-popup-pane{z-index:700}.leaflet-map-pane canvas{z-index:100}.leaflet-map-pane svg{z-index:200}.leaflet-vml-shape{width:1px;height:1px}.lvml{behavior:url(#default#VML);display:inline-block;position:absolute}.leaflet-control{position:relative;z-index:800;pointer-events:visiblePainted;pointer-events:auto}.leaflet-top,.leaflet-bottom{position:absolute;z-index:1000;pointer-events:none}.leaflet-top{top:0}.leaflet-right{right:0}.leaflet-bottom{bottom:0}.leaflet-left{left:0}.leaflet-control{float:left;clear:both}.leaflet-right .leaflet-control{float:right}.leaflet-top .leaflet-control{margin-top:10px}.leaflet-bottom .leaflet-control{margin-bottom:10px}.leaflet-left .leaflet-control{margin-left:10px}.leaflet-right .leaflet-control{margin-right:10px}.leaflet-fade-anim .leaflet-popup{opacity:0;transition:opacity .2s linear}.leaflet-fade-anim .leaflet-map-pane .leaflet-popup{opacity:1}.leaflet-zoom-animated{transform-origin:0 0}svg.leaflet-zoom-animated{will-change:transform}.leaflet-zoom-anim .leaflet-zoom-animated{transition:transform .25s cubic-bezier(0,0,.25,1)}.leaflet-zoom-anim .leaflet-tile,.leaflet-pan-anim .leaflet-tile{transition:none}.leaflet-zoom-anim .leaflet-zoom-hide{visibility:hidden}.leaflet-interactive{cursor:pointer}.leaflet-grab{cursor:grab}.leaflet-crosshair,.leaflet-crosshair .leaflet-interactive{cursor:crosshair}.leaflet-popup-pane,.leaflet-control{cursor:auto}.leaflet-dragging .leaflet-grab,.leaflet-dragging .leaflet-grab .leaflet-interactive,.leaflet-dragging .leaflet-marker-draggable{cursor:move;cursor:grabbing}.leaflet-marker-icon,.leaflet-marker-shadow,.leaflet-image-layer,.leaflet-pane>svg path,.leaflet-tile-container{pointer-events:none}.leaflet-marker-icon.leaflet-interactive,.leaflet-image-layer.leaflet-interactive,.leaflet-pane>svg path.leaflet-interactive,svg.leaflet-image-layer.leaflet-interactive path{pointer-events:visiblePainted;pointer-events:auto}.leaflet-container{background:#ddd;outline-offset:1px}.leaflet-container a{color:#0078a8}.leaflet-zoom-box{border:2px dotted #38f;background:#ffffff80}.leaflet-container{font-family:Helvetica Neue,Arial,Helvetica,sans-serif;font-size:12px;font-size:.75rem;line-height:1.5}.leaflet-bar{box-shadow:0 1px 5px #000000a6;border-radius:4px}.leaflet-bar a{background-color:#fff;border-bottom:1px solid #ccc;width:26px;height:26px;line-height:26px;display:block;text-align:center;text-decoration:none;color:#000}.leaflet-bar a,.leaflet-control-layers-toggle{background-position:50% 50%;background-repeat:no-repeat;display:block}.leaflet-bar a:hover,.leaflet-bar a:focus{background-color:#f4f4f4}.leaflet-bar a:first-child{border-top-left-radius:4px;border-top-right-radius:4px}.leaflet-bar a:last-child{border-bottom-left-radius:4px;border-bottom-right-radius:4px;border-bottom:none}.leaflet-bar a.leaflet-disabled{cursor:default;background-color:#f4f4f4;color:#bbb}.leaflet-touch .leaflet-bar a{width:30px;height:30px;line-height:30px}.leaflet-touch .leaflet-bar a:first-child{border-top-left-radius:2px;border-top-right-radius:2px}.leaflet-touch .leaflet-bar a:last-child{border-bottLine truncated
+602
View File
@@ -0,0 +1,602 @@
var Ey=Object.defineProperty;var ky=(n,s,i)=>s in n?Ey(n,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[s]=i;var $o=(n,s,i)=>ky(n,typeof s!="symbol"?s+"":s,i);function Sy(n,s){for(var i=0;i<s.length;i++){const l=s[i];if(typeof l!="string"&&!Array.isArray(l)){for(const u in l)if(u!=="default"&&!(u in n)){const c=Object.getOwnPropertyDescriptor(l,u);c&&Object.defineProperty(n,u,c.get?c:{enumerable:!0,get:()=>l[u]})}}}return Object.freeze(Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}))}(function(){const s=document.createElement("link").relList;if(s&&s.supports&&s.supports("modulepreload"))return;for(const u of document.querySelectorAll('link[rel="modulepreload"]'))l(u);new MutationObserver(u=>{for(const c of u)if(c.type==="childList")for(const h of c.addedNodes)h.tagName==="LINK"&&h.rel==="modulepreload"&&l(h)}).observe(document,{childList:!0,subtree:!0});function i(u){const c={};return u.integrity&&(c.integrity=u.integrity),u.referrerPolicy&&(c.referrerPolicy=u.referrerPolicy),u.crossOrigin==="use-credentials"?c.credentials="include":u.crossOrigin==="anonymous"?c.credentials="omit":c.credentials="same-origin",c}function l(u){if(u.ep)return;u.ep=!0;const c=i(u);fetch(u.href,c)}})();var _l=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function ls(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function Cx(n){if(Object.prototype.hasOwnProperty.call(n,"__esModule"))return n;var s=n.default;if(typeof s=="function"){var i=function l(){return this instanceof l?Reflect.construct(s,arguments,this.constructor):s.apply(this,arguments)};i.prototype=s.prototype}else i={};return Object.defineProperty(i,"__esModule",{value:!0}),Object.keys(n).forEach(function(l){var u=Object.getOwnPropertyDescriptor(n,l);Object.defineProperty(i,l,u.get?u:{enumerable:!0,get:function(){return n[l]}})}),i}var Jf={exports:{}},tl={},e0={exports:{}},vt={};/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Yp;function By(){if(Yp)return vt;Yp=1;var n=Symbol.for("react.element"),s=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),c=Symbol.for("react.provider"),h=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),x=Symbol.for("react.lazy"),v=Symbol.iterator;function C(D){return D===null||typeof D!="object"?null:(D=v&&D[v]||D["@@iterator"],typeof D=="function"?D:null)}var P={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},M=Object.assign,k={};function w(D,H,q){this.props=D,this.context=H,this.refs=k,this.updater=q||P}w.prototype.isReactComponent={},w.prototype.setState=function(D,H){if(typeof D!="object"&&typeof D!="function"&&D!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,D,H,"setState")},w.prototype.forceUpdate=function(D){this.updater.enqueueForceUpdate(this,D,"forceUpdate")};function B(){}B.prototype=w.prototype;function b(D,H,q){this.props=D,this.context=H,this.refs=k,this.updater=q||P}var E=b.prototype=new B;E.constructor=b,M(E,w.prototype),E.isPureReactComponent=!0;var T=Array.isArray,F=Object.prototype.hasOwnProperty,I={current:null},j={key:!0,ref:!0,__self:!0,__source:!0};function O(D,H,q){var Q,ae={},ce=null,Ae=null;if(H!=null)for(Q in H.ref!==void 0&&(Ae=H.ref),H.key!==void 0&&(ce=""+H.key),H)F.call(H,Q)&&!j.hasOwnProperty(Q)&&(ae[Q]=H[Q]);var pe=arguments.length-2;if(pe===1)ae.children=q;else if(1<pe){for(var xe=Array(pe),Be=0;Be<pe;Be++)xe[Be]=arguments[Be+2];ae.children=xe}if(D&&D.defaultProps)for(Q in pe=D.defaultProps,pe)ae[Q]===void 0&&(ae[Q]=pe[Q]);return{$$typeof:n,type:D,key:ce,ref:Ae,props:ae,_owner:I.current}}function G(D,H){return{$$typeof:n,type:D.type,key:H,ref:D.ref,props:D.props,_owner:D._owner}}function U(D){return typeof D=="object"&&D!==null&&D.$$typeof===n}function K(D){var H={"=":"=0",":":"=2"};return"$"+D.replace(/[=:]/g,function(q){return H[q]})}var J=/\/+/g;function Y(D,H){return typeof D=="object"&&D!==null&&D.key!=null?K(""+D.key):H.toString(36)}function ie(D,H,q,Q,ae){var ce=typeof D;(ce==="undefined"||ce==="boolean")&&(D=null);var Ae=!1;if(D===null)Ae=!0;else switch(ce){case"string":case"number":Ae=!0;break;case"object":switch(D.$$typeof){case n:case s:Ae=!0}}if(Ae)return Ae=D,ae=ae(Ae),D=Q===""?"."+Y(Ae,0):Q,T(ae)?(q="",D!=null&&(q=D.replace(J,"$&/")+"/"),ie(ae,H,q,"",function(Be){return Be})):ae!=null&&(U(ae)&&(ae=G(ae,q+(!ae.key||Ae&&Ae.key===ae.key?"":(""+ae.key).replace(J,"$&/")+"/")+D)),H.push(ae)),1;if(Ae=0,Q=Q===""?".":Q+":",T(D))for(var pe=0;pe<D.length;pe++){ce=D[pe];var xe=Q+Y(ce,pe);Ae+=ie(ce,H,q,xe,ae)}else if(xe=C(D),typeof xe=="function")for(D=xe.call(D),pe=0;!(ce=D.next()).done;)ce=ce.value,xe=Q+Y(ce,pe++),Ae+=ie(ce,H,q,xe,ae);else if(ce==="object")throw H=String(D),Error("Objects are not valid as a React child (found: "+(H==="[object Object]"?"object with keys {"+Object.keys(D).join(", ")+"}":H)+"). If you meant to render a collection of children, use an array instead.");return Ae}function ge(D,H,q){if(D==null)return D;var Q=[],ae=0;return ie(D,Q,"","",function(ce){return H.call(q,ce,ae++)}),Q}function $(D){if(D._status===-1){var H=D._result;H=H(),H.then(function(q){(D._status===0||D._status===-1)&&(D._status=1,D._result=q)},function(q){(D._status===0||D._status===-1)&&(D._status=2,D._result=q)}),D._status===-1&&(D._status=0,D._result=H)}if(D._status===1)return D._result.default;throw D._result}var se={current:null},W={transition:null},te={ReactCurrentDispatcher:se,ReactCurrentBatchConfig:W,ReactCurrentOwner:I};function Z(){throw Error("act(...) is not supported in production builds of React.")}return vt.Children={map:ge,forEach:function(D,H,q){ge(D,function(){H.apply(this,arguments)},q)},count:function(D){var H=0;return ge(D,function(){H++}),H},toArray:function(D){return ge(D,function(H){return H})||[]},only:function(D){if(!U(D))throw Error("React.Children.only expected to receive a single React element child.");return D}},vt.Component=w,vt.Fragment=i,vt.Profiler=u,vt.PureComponent=b,vt.StrictMode=l,vt.Suspense=g,vt.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=te,vt.act=Z,vt.cloneElement=function(D,H,q){if(D==null)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+D+".");var Q=M({},D.props),ae=D.key,ce=D.ref,Ae=D._owner;if(H!=null){if(H.ref!==void 0&&(ce=H.ref,Ae=I.current),H.key!==void 0&&(ae=""+H.key),D.type&&D.type.defaultProps)var pe=D.type.defaultProps;for(xe in H)F.call(H,xe)&&!j.hasOwnProperty(xe)&&(Q[xe]=H[xe]===void 0&&pe!==void 0?pe[xe]:H[xe])}var xe=arguments.length-2;if(xe===1)Q.children=q;else if(1<xe){pe=Array(xe);for(var Be=0;Be<xe;Be++)pe[Be]=arguments[Be+2];Q.children=pe}return{$$typeof:n,type:D.type,key:ae,ref:ce,props:Q,_owner:Ae}},vt.createCLine truncated
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Jp;function Py(){if(Jp)return tl;Jp=1;var n=sd(),s=Symbol.for("react.element"),i=Symbol.for("react.fragment"),l=Object.prototype.hasOwnProperty,u=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,c={key:!0,ref:!0,__self:!0,__source:!0};function h(d,g,m){var x,v={},C=null,P=null;m!==void 0&&(C=""+m),g.key!==void 0&&(C=""+g.key),g.ref!==void 0&&(P=g.ref);for(x in g)l.call(g,x)&&!c.hasOwnProperty(x)&&(v[x]=g[x]);if(d&&d.defaultProps)for(x in g=d.defaultProps,g)v[x]===void 0&&(v[x]=g[x]);return{$$typeof:s,type:d,key:C,ref:P,props:v,_owner:u.current}}return tl.Fragment=i,tl.jsx=h,tl.jsxs=h,tl}var em;function Ty(){return em||(em=1,Jf.exports=Py()),Jf.exports}var _=Ty(),N=sd();const De=ls(N),z0=Sy({__proto__:null,default:De},[N]);var Zu={},t0={exports:{}},Yn={},n0={exports:{}},r0={};/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var tm;function Dy(){return tm||(tm=1,(function(n){function s(W,te){var Z=W.length;W.push(te);e:for(;0<Z;){var D=Z-1>>>1,H=W[D];if(0<u(H,te))W[D]=te,W[Z]=H,Z=D;else break e}}function i(W){return W.length===0?null:W[0]}function l(W){if(W.length===0)return null;var te=W[0],Z=W.pop();if(Z!==te){W[0]=Z;e:for(var D=0,H=W.length,q=H>>>1;D<q;){var Q=2*(D+1)-1,ae=W[Q],ce=Q+1,Ae=W[ce];if(0>u(ae,Z))ce<H&&0>u(Ae,ae)?(W[D]=Ae,W[ce]=Z,D=ce):(W[D]=ae,W[Q]=Z,D=Q);else if(ce<H&&0>u(Ae,Z))W[D]=Ae,W[ce]=Z,D=ce;else break e}}return te}function u(W,te){var Z=W.sortIndex-te.sortIndex;return Z!==0?Z:W.id-te.id}if(typeof performance=="object"&&typeof performance.now=="function"){var c=performance;n.unstable_now=function(){return c.now()}}else{var h=Date,d=h.now();n.unstable_now=function(){return h.now()-d}}var g=[],m=[],x=1,v=null,C=3,P=!1,M=!1,k=!1,w=typeof setTimeout=="function"?setTimeout:null,B=typeof clearTimeout=="function"?clearTimeout:null,b=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function E(W){for(var te=i(m);te!==null;){if(te.callback===null)l(m);else if(te.startTime<=W)l(m),te.sortIndex=te.expirationTime,s(g,te);else break;te=i(m)}}function T(W){if(k=!1,E(W),!M)if(i(g)!==null)M=!0,$(F);else{var te=i(m);te!==null&&se(T,te.startTime-W)}}function F(W,te){M=!1,k&&(k=!1,B(O),O=-1),P=!0;var Z=C;try{for(E(te),v=i(g);v!==null&&(!(v.expirationTime>te)||W&&!K());){var D=v.callback;if(typeof D=="function"){v.callback=null,C=v.priorityLevel;var H=D(v.expirationTime<=te);te=n.unstable_now(),typeof H=="function"?v.callback=H:v===i(g)&&l(g),E(te)}else l(g);v=i(g)}if(v!==null)var q=!0;else{var Q=i(m);Q!==null&&se(T,Q.startTime-te),q=!1}return q}finally{v=null,C=Z,P=!1}}var I=!1,j=null,O=-1,G=5,U=-1;function K(){return!(n.unstable_now()-U<G)}function J(){if(j!==null){var W=n.unstable_now();U=W;var te=!0;try{te=j(!0,W)}finally{te?Y():(I=!1,j=null)}}else I=!1}var Y;if(typeof b=="function")Y=function(){b(J)};else if(typeof MessageChannel<"u"){var ie=new MessageChannel,ge=ie.port2;ie.port1.onmessage=J,Y=function(){ge.postMessage(null)}}else Y=function(){w(J,0)};function $(W){j=W,I||(I=!0,Y())}function se(W,te){O=w(function(){W(n.unstable_now())},te)}n.unstable_IdlePriority=5,n.unstable_ImmediatePriority=1,n.unstable_LowPriority=4,n.unstable_NormalPriority=3,n.unstable_Profiling=null,n.unstable_UserBlockingPriority=2,n.unstable_cancelCallback=function(W){W.callback=null},n.unstable_continueExecution=function(){M||P||(M=!0,$(F))},n.unstable_forceFrameRate=function(W){0>W||125<W?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):G=0<W?Math.floor(1e3/W):5},n.unstable_getCurrentPriorityLevel=function(){return C},n.unstable_getFirstCallbackNode=function(){return i(g)},n.unstable_next=function(W){switch(C){case 1:case 2:case 3:var te=3;break;default:te=C}var Z=C;C=te;try{return W()}finally{C=Z}},n.unstable_pauseExecution=function(){},n.unstable_requestPaint=function(){},n.unstable_runWithPriority=function(W,te){switch(W){case 1:case 2:case 3:case 4:case 5:break;default:W=3}var Z=C;C=W;try{return te()}finally{C=Z}},n.unstable_scheduleCallback=function(W,te,Z){var D=n.unstable_now();switch(typeof Z=="object"&&Z!==null?(Z=Z.delay,Z=typeof Z=="number"&&0<Z?D+Z:D):Z=D,W){case 1:var H=-1;break;case 2:H=250;break;case 5:H=1073741823;break;case 4:H=1e4;break;default:H=5e3}return H=Z+H,W={id:x++,callback:te,priorityLevel:W,startTime:Z,expirationTime:H,sortIndex:-1},Z>D?(W.sortIndex=Z,s(m,W),i(g)===null&&W===i(m)&&(k?(B(O),O=-1):k=!0,se(T,Z-D))):(W.sortIndex=H,s(g,W),M||P||(M=!0,$(F))),W},n.unstable_shouldYield=K,n.unstable_wrapCallback=function(W){var te=C;return function(){var Z=C;C=te;try{return W.apply(this,arguments)}finally{C=Z}}}})(r0)),r0}var nm;function Ry(){return nm||(nm=1,n0.exports=Dy()),n0.exports}/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var rm;function Fy(){if(rm)return Yn;rm=1;var n=sd(),s=Ry();function i(e){for(var r="https://reactjs.org/docs/error-decoder.html?invariant="+e,a=1;a<arguments.length;a++)r+="&args[]="+encodeURIComponent(arguments[a]);return"Minified React error #"+e+"; visit "+r+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var l=new Set,u={};function c(e,r){h(e,r),h(e+"Capture",r)}function h(e,r){for(u[e]=r,e=0;e<r.length;e++)l.add(r[e])}var d=!(typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),g=Object.prototype.hasOwnProperty,m=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,x={},v={};function C(e){return g.call(v,e)?!0:g.call(x,e)?!1:m.test(e)?v[e]=!0:(x[e]=!0,!1)}function P(e,r,a,p){if(a!==null&&a.type===0)return!1;switch(typeof r){case"function":case"symbol":return!0;case"boolean":return p?!1:a!==null?!a.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function M(e,r,a,p){if(r===null||typeof r>"u"||P(e,r,a,p))return!0;if(p)return!1;if(a!==null)switch(a.type){case 3:return!r;case 4:return r===!1;case 5:return isNaN(r);case 6:return isNaN(r)||1>r}return!1}function k(e,r,a,p,y,S,z){this.acceptsBooleans=r===2||r===3||r===4,this.attributeName=p,this.attributeNamespace=y,this.mustUseProperty=a,this.propertyName=e,this.type=r,this.sanitizeURL=S,this.removeEmptyString=z}var w={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){w[e]=new k(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var r=e[0];w[r]=new k(r,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){w[e]=new k(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){w[e]=new k(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){w[e]=new k(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){w[e]=new k(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){w[e]=new k(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){w[e]=new k(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){w[e]=new k(e,5,!1,e.toLowerCase(),null,!1,!1)});var B=/[\-:]([a-z])/g;function b(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var r=e.replace(B,b);w[r]=new k(r,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var r=e.replace(B,b);w[r]=new k(r,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var r=e.replace(B,b);w[r]=new k(r,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){w[e]=new k(e,1,!1,e.toLowerCase(),null,!1,!1)}),w.xlinkHref=new k("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){w[e]=new k(e,1,!1,e.toLowerCase(),null,!0,!0)});function E(e,r,a,p){var y=w.hasOwnProperty(r)?w[r]:null;(y!==null?y.type!==0:p||!(2<r.length)||r[0]!=="o"&&r[0]!=="O"||r[1]!=="n"&&r[1]!= Line truncated
`+D+e}var q=!1;function Q(e,r){if(!e||q)return"";q=!0;var a=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(r)if(r=function(){throw Error()},Object.defineProperty(r.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(r,[])}catch(me){var p=me}Reflect.construct(e,[],r)}else{try{r.call()}catch(me){p=me}e.call(r.prototype)}else{try{throw Error()}catch(me){p=me}e()}}catch(me){if(me&&p&&typeof me.stack=="string"){for(var y=me.stack.split(`
`),S=p.stack.split(`
`),z=y.length-1,X=S.length-1;1<=z&&0<=X&&y[z]!==S[X];)X--;for(;1<=z&&0<=X;z--,X--)if(y[z]!==S[X]){if(z!==1||X!==1)do if(z--,X--,0>X||y[z]!==S[X]){var ne=`
`+y[z].replace(" at new "," at ");return e.displayName&&ne.includes("<anonymous>")&&(ne=ne.replace("<anonymous>",e.displayName)),ne}while(1<=z&&0<=X);break}}}finally{q=!1,Error.prepareStackTrace=a}return(e=e?e.displayName||e.name:"")?H(e):""}function ae(e){switch(e.tag){case 5:return H(e.type);case 16:return H("Lazy");case 13:return H("Suspense");case 19:return H("SuspenseList");case 0:case 2:case 15:return e=Q(e.type,!1),e;case 11:return e=Q(e.type.render,!1),e;case 1:return e=Q(e.type,!0),e;default:return""}}function ce(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case j:return"Fragment";case I:return"Portal";case G:return"Profiler";case O:return"StrictMode";case Y:return"Suspense";case ie:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case K:return(e.displayName||"Context")+".Consumer";case U:return(e._context.displayName||"Context")+".Provider";case J:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case ge:return r=e.displayName||null,r!==null?r:ce(e.type)||"Memo";case $:r=e._payload,e=e._init;try{return ce(e(r))}catch{}}return null}function Ae(e){var r=e.type;switch(e.tag){case 24:return"Cache";case 9:return(r.displayName||"Context")+".Consumer";case 10:return(r._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=r.render,e=e.displayName||e.name||"",r.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return r;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return ce(r);case 8:return r===O?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof r=="function")return r.displayName||r.name||null;if(typeof r=="string")return r}return null}function pe(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function xe(e){var r=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(r==="checkbox"||r==="radio")}function Be(e){var r=xe(e)?"checked":"value",a=Object.getOwnPropertyDescriptor(e.constructor.prototype,r),p=""+e[r];if(!e.hasOwnProperty(r)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var y=a.get,S=a.set;return Object.defineProperty(e,r,{configurable:!0,get:function(){return y.call(this)},set:function(z){p=""+z,S.call(this,z)}}),Object.defineProperty(e,r,{enumerable:a.enumerable}),{getValue:function(){return p},setValue:function(z){p=""+z},stopTracking:function(){e._valueTracker=null,delete e[r]}}}}function Oe(e){e._valueTracker||(e._valueTracker=Be(e))}function Xe(e){if(!e)return!1;var r=e._valueTracker;if(!r)return!0;var a=r.getValue(),p="";return e&&(p=xe(e)?e.checked?"true":"false":e.value),e=p,e!==a?(r.setValue(e),!0):!1}function Ee(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function je(e,r){var a=r.checked;return Z({},r,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??e._wrapperState.initialChecked})}function at(e,r){var a=r.defaultValue==null?"":r.defaultValue,p=r.checked!=null?r.checked:r.defaultChecked;a=pe(r.value!=null?r.value:a),e._wrapperState={initialChecked:p,initialValue:a,controlled:r.type==="checkbox"||r.type==="radio"?r.checked!=null:r.value!=null}}function mt(e,r){r=r.checked,r!=null&&E(e,"checked",r,!1)}function ot(e,r){mt(e,r);var a=pe(r.value),p=r.type;if(a!=null)p==="number"?(a===0&&e.value===""||e.value!=a)&&(e.value=""+a):e.value!==""+a&&(e.value=""+a);else if(p==="submit"||p==="reset"){e.removeAttribute("value");return}r.hasOwnProperty("value")?Ke(e,r.type,a):r.hasOwnProperty("defaultValue")&&Ke(e,r.type,pe(r.defaultValue)),r.checked==null&&r.defaultChecked!=null&&(e.defaultChecked=!!r.defaultChecked)}function qe(e,r,a){if(r.hasOwnProperty("value")||r.hasOwnProperty("defaultValue")){var p=r.type;if(!(p!=="submit"&&p!=="reset"||r.value!==void 0&&r.value!==null))return;r=""+e._wrapperState.initialValue,a||r===e.value||(e.value=r),e.defaultValue=r}a=e.name,a!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,a!==""&&(e.name=a)}function Ke(e,r,a){(r!=="number"||Ee(e.ownerDocument)!==e)&&(a==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+a&&(e.defaultValue=""+a))}var Qe=Array.isArray;function rt(e,r,a,p){if(e=e.options,r){r={};for(var y=0;y<a.length;y++)r["$"+a[y]]=!0;for(a=0;a<e.length;a++)y=r.hasOwnProperty("$"+e[a].value),e[a].selected!==y&&(e[a].selected=y),y&&p&&(e[a].defaultSelected=!0)}else{for(a=""+pe(a),r=null,y=0;y<e.length;y++){if(e[y].value===a){e[y].selected=!0,p&&(e[y].defaultSelected=!0);return}r!==null||e[y].disabled||(r=e[y])}r!==null&&(r.selected=!0)}}function He(e,r){if(r.dangerouslySetInnerH Line truncated
`).replace(ee,"")}function he(e,r,a){if(r=le(r),le(e)!==r&&a)throw Error(i(425))}function be(){}var Me=null,et=null;function ht(e,r){return e==="textarea"||e==="noscript"||typeof r.children=="string"||typeof r.children=="number"||typeof r.dangerouslySetInnerHTML=="object"&&r.dangerouslySetInnerHTML!==null&&r.dangerouslySetInnerHTML.__html!=null}var dn=typeof setTimeout=="function"?setTimeout:void 0,ln=typeof clearTimeout=="function"?clearTimeout:void 0,On=typeof Promise=="function"?Promise:void 0,Tn=typeof queueMicrotask=="function"?queueMicrotask:typeof On<"u"?function(e){return On.resolve(null).then(e).catch(eo)}:dn;function eo(e){setTimeout(function(){throw e})}function za(e,r){var a=r,p=0;do{var y=a.nextSibling;if(e.removeChild(a),y&&y.nodeType===8)if(a=y.data,a==="/$"){if(p===0){e.removeChild(y),rr(r);return}p--}else a!=="$"&&a!=="$?"&&a!=="$!"||p++;a=y}while(a);rr(r)}function Jr(e){for(;e!=null;e=e.nextSibling){var r=e.nodeType;if(r===1||r===3)break;if(r===8){if(r=e.data,r==="$"||r==="$!"||r==="$?")break;if(r==="/$")return null}}return e}function ou(e){e=e.previousSibling;for(var r=0;e;){if(e.nodeType===8){var a=e.data;if(a==="$"||a==="$!"||a==="$?"){if(r===0)return e;r--}else a==="/$"&&r++}e=e.previousSibling}return null}var vi=Math.random().toString(36).slice(2),yr="__reactFiber$"+vi,to="__reactProps$"+vi,Ft="__reactContainer$"+vi,no="__reactEvents$"+vi,Gd="__reactListeners$"+vi,$d="__reactHandles$"+vi;function Ai(e){var r=e[yr];if(r)return r;for(var a=e.parentNode;a;){if(r=a[Ft]||a[yr]){if(a=r.alternate,r.child!==null||a!==null&&a.child!==null)for(e=ou(e);e!==null;){if(a=e[yr])return a;e=ou(e)}return r}e=a,a=e.parentNode}return null}function yi(e){return e=e[yr]||e[Ft],!e||e.tag!==5&&e.tag!==6&&e.tag!==13&&e.tag!==3?null:e}function _i(e){if(e.tag===5||e.tag===6)return e.stateNode;throw Error(i(33))}function Ls(e){return e[to]||null}var Kd=[],Ms=-1;function ro(e){return{current:e}}function qt(e){0>Ms||(e.current=Kd[Ms],Kd[Ms]=null,Ms--)}function Zt(e,r){Ms++,Kd[Ms]=e.current,e.current=r}var io={},Dn=ro(io),qn=ro(!1),Io=io;function Is(e,r){var a=e.type.contextTypes;if(!a)return io;var p=e.stateNode;if(p&&p.__reactInternalMemoizedUnmaskedChildContext===r)return p.__reactInternalMemoizedMaskedChildContext;var y={},S;for(S in a)y[S]=r[S];return p&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=r,e.__reactInternalMemoizedMaskedChildContext=y),y}function Gn(e){return e=e.childContextTypes,e!=null}function su(){qt(qn),qt(Dn)}function Ah(e,r,a){if(Dn.current!==io)throw Error(i(168));Zt(Dn,r),Zt(qn,a)}function yh(e,r,a){var p=e.stateNode;if(r=r.childContextTypes,typeof p.getChildContext!="function")return a;p=p.getChildContext();for(var y in p)if(!(y in r))throw Error(i(108,Ae(e)||"Unknown",y));return Z({},a,p)}function au(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||io,Io=Dn.current,Zt(Dn,e),Zt(qn,qn.current),!0}function _h(e,r,a){var p=e.stateNode;if(!p)throw Error(i(169));a?(e=yh(e,r,Io),p.__reactInternalMemoizedMergedChildContext=e,qt(qn),qt(Dn),Zt(Dn,e)):qt(qn),Zt(qn,a)}var wi=null,lu=!1,Qd=!1;function wh(e){wi===null?wi=[e]:wi.push(e)}function ZA(e){lu=!0,wh(e)}function oo(){if(!Qd&&wi!==null){Qd=!0;var e=0,r=Ct;try{var a=wi;for(Ct=1;e<a.length;e++){var p=a[e];do p=p(!0);while(p!==null)}wi=null,lu=!1}catch(y){throw wi!==null&&(wi=wi.slice(e+1)),Ll(ma,oo),y}finally{Ct=r,Qd=!1}}return null}var Os=[],js=0,uu=null,cu=0,_r=[],wr=0,Oo=null,bi=1,Ci="";function jo(e,r){Os[js++]=cu,Os[js++]=uu,uu=e,cu=r}function bh(e,r,a){_r[wr++]=bi,_r[wr++]=Ci,_r[wr++]=Oo,Oo=e;var p=bi;e=Ci;var y=32-ct(p)-1;p&=~(1<<y),a+=1;var S=32-ct(r)+y;if(30<S){var z=y-y%5;S=(p&(1<<z)-1).toString(32),p>>=z,y-=z,bi=1<<32-ct(r)+y|a<<y|p,Ci=S+e}else bi=1<<S|a<<y|p,Ci=e}function Yd(e){e.return!==null&&(jo(e,1),bh(e,1,0))}function Xd(e){for(;e===uu;)uu=Os[--js],Os[js]=null,cu=Os[--js],Os[js]=null;for(;e===Oo;)Oo=_r[--wr],_r[wr]=null,Ci=_r[--wr],_r[wr]=null,bi=_r[--wr],_r[wr]=null}var lr=null,ur=null,Kt=!1,Lr=null;function Ch(e,r){var a=kr(5,null,null,0);a.elementType="DELETED",a.stateNode=r,a.return=e,r=e.deletions,r===null?(e.deletions=[a],e.flags|=16):r.push(a)}function Eh(e,r){switch(e.tag){case 5:var a=e.type;return r=r.nodeType!==1||a.toLowerCase()!==r.nodeName.toLowerCase()?null:r,r!==null?(e.stateNode=r,lr=e,ur=Jr(r.firstChild),!0):!1;case 6:return r=e.pendingProps===""||r.nodeType!==3?null:r,r!==null?(e.stateNode=r,lr=e,ur=null,!0):!1;case 13:return r=r.nodeType!==8?null:r,r!==null?(a=Oo!==null?{id:bi,overflow:Ci}:null,e.memoizedState={dehydrated:r,treeContext:a,retryLane:1073741824},a=kr(18,null,null,0),a.stateNode=r,a.return=e,e.child=a,lr=e,ur=null,!0):!1;default:return!1}}function Jd(e){return(e.mode&1)!==0&&(e.flags&128)===0}function ef(e){if(Kt){var r=ur;if(r){var a=r;if(!Eh(e,r)){if(Jd(e))throw Error(i(418));r=Jr(a.nextSibling);var p=lr;r&&Eh(e,r)?Ch(p,a):(e.flags=e.flags&-4097|2,Kt=!1,lr=e)}}else{if(Jd(e))throw Error(i(418));e.flags=e.flags&-4097|2,Kt=!1,lr=e}}}function kh(e){for(e=e. Line truncated
Error generating stack: `+S.message+`
`+S.stack}return{value:e,source:r,stack:y,digest:null}}function bf(e,r,a){return{value:e,source:null,stack:a??null,digest:r??null}}function Cf(e,r){try{console.error(r.value)}catch(a){setTimeout(function(){throw a})}}var JA=typeof WeakMap=="function"?WeakMap:Map;function sp(e,r,a){a=ki(-1,a),a.tag=3,a.payload={element:null};var p=r.value;return a.callback=function(){Tu||(Tu=!0,jf=p),Cf(e,r)},a}function ap(e,r,a){a=ki(-1,a),a.tag=3;var p=e.type.getDerivedStateFromError;if(typeof p=="function"){var y=r.value;a.payload=function(){return p(y)},a.callback=function(){Cf(e,r)}}var S=e.stateNode;return S!==null&&typeof S.componentDidCatch=="function"&&(a.callback=function(){Cf(e,r),typeof p!="function"&&(uo===null?uo=new Set([this]):uo.add(this));var z=r.stack;this.componentDidCatch(r.value,{componentStack:z!==null?z:""})}),a}function lp(e,r,a){var p=e.pingCache;if(p===null){p=e.pingCache=new JA;var y=new Set;p.set(r,y)}else y=p.get(r),y===void 0&&(y=new Set,p.set(r,y));y.has(a)||(y.add(a),e=hy.bind(null,e,r,a),r.then(e,e))}function up(e){do{var r;if((r=e.tag===13)&&(r=e.memoizedState,r=r!==null?r.dehydrated!==null:!0),r)return e;e=e.return}while(e!==null);return null}function cp(e,r,a,p,y){return(e.mode&1)===0?(e===r?e.flags|=65536:(e.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(r=ki(-1,1),r.tag=2,ao(a,r,1))),a.lanes|=1),e):(e.flags|=65536,e.lanes=y,e)}var ey=T.ReactCurrentOwner,$n=!1;function jn(e,r,a,p){r.child=e===null?Th(r,null,a,p):Hs(r,e.child,a,p)}function dp(e,r,a,p,y){a=a.render;var S=r.ref;return Us(r,y),p=mf(e,r,a,p,S,y),a=gf(),e!==null&&!$n?(r.updateQueue=e.updateQueue,r.flags&=-2053,e.lanes&=~y,Si(e,r,y)):(Kt&&a&&Yd(r),r.flags|=1,jn(e,r,p,y),r.child)}function fp(e,r,a,p,y){if(e===null){var S=a.type;return typeof S=="function"&&!qf(S)&&S.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(r.tag=15,r.type=S,hp(e,r,S,p,y)):(e=Mu(a.type,null,p,r,r.mode,y),e.ref=r.ref,e.return=r,r.child=e)}if(S=e.child,(e.lanes&y)===0){var z=S.memoizedProps;if(a=a.compare,a=a!==null?a:Qr,a(z,p)&&e.ref===r.ref)return Si(e,r,y)}return r.flags|=1,e=po(S,p),e.ref=r.ref,e.return=r,r.child=e}function hp(e,r,a,p,y){if(e!==null){var S=e.memoizedProps;if(Qr(S,p)&&e.ref===r.ref)if($n=!1,r.pendingProps=p=S,(e.lanes&y)!==0)(e.flags&131072)!==0&&($n=!0);else return r.lanes=e.lanes,Si(e,r,y)}return Ef(e,r,a,p,y)}function pp(e,r,a){var p=r.pendingProps,y=p.children,S=e!==null?e.memoizedState:null;if(p.mode==="hidden")if((r.mode&1)===0)r.memoizedState={baseLanes:0,cachePool:null,transitions:null},Zt(Gs,cr),cr|=a;else{if((a&1073741824)===0)return e=S!==null?S.baseLanes|a:a,r.lanes=r.childLanes=1073741824,r.memoizedState={baseLanes:e,cachePool:null,transitions:null},r.updateQueue=null,Zt(Gs,cr),cr|=e,null;r.memoizedState={baseLanes:0,cachePool:null,transitions:null},p=S!==null?S.baseLanes:a,Zt(Gs,cr),cr|=p}else S!==null?(p=S.baseLanes|a,r.memoizedState=null):p=a,Zt(Gs,cr),cr|=p;return jn(e,r,y,a),r.child}function mp(e,r){var a=r.ref;(e===null&&a!==null||e!==null&&e.ref!==a)&&(r.flags|=512,r.flags|=2097152)}function Ef(e,r,a,p,y){var S=Gn(a)?Io:Dn.current;return S=Is(r,S),Us(r,y),a=mf(e,r,a,p,S,y),p=gf(),e!==null&&!$n?(r.updateQueue=e.updateQueue,r.flags&=-2053,e.lanes&=~y,Si(e,r,y)):(Kt&&p&&Yd(r),r.flags|=1,jn(e,r,a,y),r.child)}function gp(e,r,a,p,y){if(Gn(a)){var S=!0;au(r)}else S=!1;if(Us(r,y),r.stateNode===null)Eu(e,r),ip(r,a,p),wf(r,a,p,y),p=!0;else if(e===null){var z=r.stateNode,X=r.memoizedProps;z.props=X;var ne=z.context,me=a.contextType;typeof me=="object"&&me!==null?me=br(me):(me=Gn(a)?Io:Dn.current,me=Is(r,me));var Se=a.getDerivedStateFromProps,Te=typeof Se=="function"||typeof z.getSnapshotBeforeUpdate=="function";Te||typeof z.UNSAFE_componentWillReceiveProps!="function"&&typeof z.componentWillReceiveProps!="function"||(X!==p||ne!==me)&&op(r,z,p,me),so=!1;var ke=r.memoizedState;z.state=ke,gu(r,p,z,y),ne=r.memoizedState,X!==p||ke!==ne||qn.current||so?(typeof Se=="function"&&(_f(r,a,Se,p),ne=r.memoizedState),(X=so||rp(r,a,X,p,ke,ne,me))?(Te||typeof z.UNSAFE_componentWillMount!="function"&&typeof z.componentWillMount!="function"||(typeof z.componentWillMount=="function"&&z.componentWillMount(),typeof z.UNSAFE_componentWillMount=="function"&&z.UNSAFE_componentWillMount()),typeof z.componentDidMount=="function"&&(r.flags|=4194308)):(typeof z.componentDidMount=="function"&&(r.flags|=4194308),r.memoizedProps=p,r.memoizedState=ne),z.props=p,z.state=ne,z.context=me,p=X):(typeof z.componentDidMount=="function"&&(r.flags|=4194308),p=!1)}else{z=r.stateNode,Rh(e,r),X=r.memoizedProps,me=r.type===r.elementType?X:Mr(r.type,X),z.props=me,Te=r.pendingProps,ke=z.context,ne=a.contextType,typeof ne=="object"&&ne!==null?ne=br(ne):(ne=Gn(a)?Io:Dn.current,ne=Is(r,ne));var Ie=a.getDerivedStateFromProps;(Se=typeof Ie=="function"||typeof z.getSnapshotBeforeUpdate=="function")||typeof z.UNSAFE_componentWillReceiveProps!="function"&&typeof z.componentWillReceiveProps!="function"||(X!==Te||ke!==ne)&&op(r,z, Line truncated
`)}function Qs(n,s,i){const l=Math.floor(Date.now()/1e3);return{id:-Date.now(),type:"PRIV",conversation_key:n,text:s,sender_timestamp:l,received_at:l,paths:null,txt_type:0,signature:null,outgoing:i,acked:1}}function Vy(n){const s=N.useRef(null),i=N.useRef(null),l=N.useCallback(()=>{i.current!==null&&(clearInterval(i.current),i.current=null),s.current=null},[]),u=N.useCallback(async()=>{const h=s.current;if(!h)return;let d=null,g=null;for(let m=0;m<2;m++)try{d=await ut.requestTelemetry(h.conversationId,"");break}catch(x){g=x instanceof Error?x:new Error("Unknown error"),m===0&&await new Promise(v=>setTimeout(v,2e3))}if(d){const m=Qs(h.conversationId,Hy(h,d),!1);n(x=>[...x,m])}else{const m=Qs(h.conversationId,`Duty cycle poll failed after retry: ${(g==null?void 0:g.message)??"Unknown error"}`,!1);n(x=>[...x,m])}},[n]),c=N.useCallback(async(h,d)=>{const g=h.trim().toLowerCase();if(g==="dutycycle_start"){l();let m=null,x=null;for(let P=0;P<2;P++)try{m=await ut.requestTelemetry(d,"");break}catch(M){x=M instanceof Error?M:new Error("Unknown error"),P===0&&await new Promise(k=>setTimeout(k,2e3))}if(!m){const P=Qs(d,`Failed to start duty cycle tracking after retry: ${(x==null?void 0:x.message)??"Unknown error"}`,!1);return n(M=>[...M,P]),!0}const v=Math.floor(Date.now()/1e3);s.current={startTime:v,uptime:m.uptime_seconds,txAirtime:m.airtime_seconds,rxAirtime:m.rx_airtime_seconds,sentFlood:m.sent_flood,sentDirect:m.sent_direct,recvFlood:m.recv_flood,recvDirect:m.recv_direct,conversationId:d};const C=Qs(d,`Airtime/duty cycle statistics gathering begins at ${v}. Logs will follow every 5 minutes. To stop, run dutycycle_stop or navigate away from this conversation.`,!1);return n(P=>[...P,C]),i.current=window.setInterval(u,jy),!0}if(g==="dutycycle_stop"){if(s.current&&s.current.conversationId===d){await u(),l();const m=Qs(d,"Airtime/duty cycle statistics gathering stopped.",!1);n(x=>[...x,m])}else{const m=Qs(d,"Duty cycle tracking is not active.",!1);n(x=>[...x,m])}return!0}return!1},[n,l,u]);return N.useEffect(()=>()=>{i.current!==null&&clearInterval(i.current)},[]),{handleAirtimeCommand:c,stopTracking:l}}function oc(n){if(n<60)return`${n}s`;const s=Math.floor(n/86400),i=Math.floor(n%86400/3600),l=Math.floor(n%3600/60);return s>0?i>0&&l>0?`${s}d${i}h${l}m`:i>0?`${s}d${i}h`:l>0?`${s}d${l}m`:`${s}d`:i>0?l>0?`${i}h${l}m`:`${i}h`:`${l}m`}function Uy(n){return["Telemetry",`Battery Voltage: ${n.battery_volts.toFixed(3)}V`,`Uptime: ${oc(n.uptime_seconds)}`,`TX Airtime: ${oc(n.airtime_seconds)}`,`RX Airtime: ${oc(n.rx_airtime_seconds)}`,"",`Noise Floor: ${n.noise_floor_dbm} dBm`,`Last RSSI: ${n.last_rssi_dbm} dBm`,`Last SNR: ${n.last_snr_db.toFixed(1)} dB`,"",`Packets: ${n.packets_received.toLocaleString()} rx / ${n.packets_sent.toLocaleString()} tx`,`Flood: ${n.recv_flood.toLocaleString()} rx / ${n.sent_flood.toLocaleString()} tx`,`Direct: ${n.recv_direct.toLocaleString()} rx / ${n.sent_direct.toLocaleString()} tx`,`Duplicates: ${n.flood_dups.toLocaleString()} flood / ${n.direct_dups.toLocaleString()} direct`,"",`TX Queue: ${n.tx_queue_len}`,`Debug Flags: ${n.full_events}`].join(`
`)}function Zy(n){if(n.length===0)return`Neighbors
No neighbors reported`;const s=[...n].sort((l,u)=>u.snr-l.snr),i=[`Neighbors (${s.length})`];for(const l of s){const u=l.name||l.pubkey_prefix,c=l.snr>=0?`+${l.snr.toFixed(1)}`:l.snr.toFixed(1);i.push(`${u}, ${c} dB [${oc(l.last_heard_seconds)} ago]`)}return i.join(`
`)}function Wy(n){if(n.length===0)return`ACL
No ACL entries`;const s=[`ACL (${n.length})`];for(const i of n){const l=i.name||i.pubkey_prefix;s.push(`${l}: ${i.permission_name}`)}return s.join(`
`)}function Ko(n,s,i,l=0){const u=Math.floor(Date.now()/1e3);return{id:-Date.now()-l,type:"PRIV",conversation_key:n,text:s,sender_timestamp:u,received_at:u,paths:null,txt_type:0,signature:null,outgoing:i,acked:1}}function qy(n,s,i){const[l,u]=N.useState(!1),{handleAirtimeCommand:c,stopTracking:h}=Vy(i);N.useEffect(()=>{u(!1),h()},[n==null?void 0:n.id,h]);const d=N.useMemo(()=>{if(!n||n.type!=="contact")return!1;const x=s.find(v=>v.public_key===n.id);return(x==null?void 0:x.type)===ad},[n,s]),g=N.useCallback(async x=>{if(!(!n||n.type!=="contact")&&d)try{const v=await ut.requestTelemetry(n.id,x),C=Ko(n.id,Uy(v),!1,0),P=Ko(n.id,Zy(v.neighbors),!1,1),M=Ko(n.id,Wy(v.acl),!1,2);i(k=>[...k,C,P,M]),u(!0)}catch(v){const C=Ko(n.id,`Telemetry request failed: ${v instanceof Error?v.message:"Unknown error"}`,!1,0);i(P=>[...P,C])}},[n,d,i]),m=N.useCallback(async x=>{if(!n||n.type!=="contact"||!d||!l||await c(x,n.id))return;const C=Ko(n.id,`> ${x}`,!0,0);i(P=>[...P,C]);try{const P=await ut.sendRepeaterCommand(n.id,x),M=Ko(n.id,P.response,!1,1);P.sender_timestamp&&(M.sender_timestamp=P.sender_timestamp),i(k=>[...k,M])}catch(P){const M=Ko(n.id,`Command failed: ${P instanceof Error?P.message:"Unknown error"}`,!1,1);i(k=>[...k,M])}},[n,d,l,i,c]);return{repeaterLoggedIn:l,activeContactIsRepeater:d,handleTelemetryRequest:g,handleRepeaterCommand:m}}const kx="remoteterm-lastMessageTime",Sx="remoteterm-sortOrder";let Qc={};function am(n){Qc={...n}}function lm(){return{...Qc}}function i0(n,s){return Qc[n]=s,{...Qc}}function Hr(n,s){return`${n}-${s}`}function Gy(){try{const n=localStorage.getItem(kx);return n?JSON.parse(n):{}}catch{return{}}}function $y(){try{return localStorage.getItem(Sx)==="alpha"?"alpha":"recent"}catch{return"recent"}}function um(){try{localStorage.removeItem(kx),localStorage.removeItem(Sx)}catch{}}function cm(n,s){if(!s)return!1;const i=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`@\\[${i}\\]`,"i").test(n)}function Ky(n,s,i,l=null){const[u,c]=N.useState({}),[h,d]=N.useState({}),[g,m]=N.useState(lm),x=N.useRef(l);N.useEffect(()=>{x.current=l},[l]);const v=N.useRef(new Set),C=N.useRef(new Set);N.useEffect(()=>{const B=n.filter(T=>!v.current.has(T.key)),b=s.filter(T=>T.public_key&&!C.current.has(T.public_key));if(B.length===0&&b.length===0)return;B.forEach(T=>v.current.add(T.key)),b.forEach(T=>C.current.add(T.public_key)),(async()=>{const T=[...B.map(F=>({type:"CHAN",conversation_key:F.key})),...b.map(F=>({type:"PRIV",conversation_key:F.public_key}))];if(T.length!==0)try{const I={};for(let U=0;U<T.length;U+=200){const K=T.slice(U,U+200),J=await ut.getMessagesBulk(K,H0);Object.assign(I,J)}const j={},O={},G={};for(const U of B){const K=I[`CHAN:${U.key}`]||[];if(K.length>0){const J=Hr("channel",U.key),Y=U.last_read_at||0,ie=K.filter($=>!$.outgoing&&$.received_at>Y);ie.length>0&&(j[J]=ie.length,ie.some($=>cm($.text,x.current))&&(O[J]=!0));const ge=Math.max(...K.map($=>$.received_at));G[J]=ge,i0(J,ge)}}for(const U of b){const K=I[`PRIV:${U.public_key}`]||[];if(K.length>0){const J=Hr("contact",U.public_key),Y=U.last_read_at||0,ie=K.filter($=>!$.outgoing&&$.received_at>Y);ie.length>0&&(j[J]=ie.length,ie.some($=>cm($.text,x.current))&&(O[J]=!0));const ge=Math.max(...K.map($=>$.received_at));G[J]=ge,i0(J,ge)}}Object.keys(j).length>0&&c(U=>({...U,...j})),Object.keys(O).length>0&&d(U=>({...U,...O})),m(lm())}catch(F){console.error("Failed to fetch messages bulk:",F)}})()},[n,s]),N.useEffect(()=>{if(i&&i.type!=="raw"&&i.type!=="map"){const B=Hr(i.type,i.id);c(b=>{if(b[B]){const E={...b};return delete E[B],E}return b}),d(b=>{if(b[B]){const E={...b};return delete E[B],E}return b}),i.type==="channel"?ut.markChannelRead(i.id).catch(b=>{console.error("Failed to mark channel as read on server:",b)}):i.type==="contact"&&ut.markContactRead(i.id).catch(b=>{console.error("Failed to mark contact as read on server:",b)})}},[i]);const P=N.useCallback((B,b)=>{c(E=>({...E,[B]:(E[B]||0)+1})),b&&d(E=>({...E,[B]:!0}))},[]),M=N.useCallback(()=>{c({}),d({}),ut.markAllRead().catch(B=>{console.error("Failed to mark all as read on server:",B)})},[]),k=N.useCallback(B=>{if(B.type==="raw"||B.type==="map")return;const b=Hr(B.type,B.id);c(E=>{if(E[b]){const T={...E};return delete T[b],T}return E}),d(E=>{if(E[b]){const T={...E};return delete T[b],T}return E}),B.type==="channel"?ut.markChannelRead(B.id).catch(E=>{console.error("Failed to mark channel as read on server:",E)}):B.type==="contact"&&ut.markContactRead(B.id).catch(E=>{console.error("Failed to mark contact as read on server:",E)})},[]),w=N.useCallback(B=>{let b=null;if(B.type==="CHAN"&&B.conversation_key?b=Hr("channel",B.conversation_key):B.type==="PRIV"&&B.conversation_key&&(b=Hr("contact",B.conversation_key)),b){const E=B.received_at||Math.floor(Date.now()/1e3),T=i0(b,E);m(T)}},[]);return{unreadCounts:u,mentions:h,lastMessageTimes:g,incrementUnread:P,markAllRead:M,markConversationRead:k,trackNewMessage:w}}var V0=Ex();const Bx=ls(V0);function Qy(n){if(typeof document>"u")return;l Line truncated
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const E_=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),k_=n=>n.replace(/^([A-Z])|[\s-_]+(\w)/g,(s,i,l)=>l?l.toUpperCase():i.toLowerCase()),hm=n=>{const s=k_(n);return s.charAt(0).toUpperCase()+s.slice(1)},Px=(...n)=>n.filter((s,i,l)=>!!s&&s.trim()!==""&&l.indexOf(s)===i).join(" ").trim(),S_=n=>{for(const s in n)if(s.startsWith("aria-")||s==="role"||s==="title")return!0};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/var B_={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const P_=N.forwardRef(({color:n="currentColor",size:s=24,strokeWidth:i=2,absoluteStrokeWidth:l,className:u="",children:c,iconNode:h,...d},g)=>N.createElement("svg",{ref:g,...B_,width:s,height:s,stroke:n,strokeWidth:l?Number(i)*24/Number(s):i,className:Px("lucide",u),...!c&&!S_(d)&&{"aria-hidden":"true"},...d},[...h.map(([m,x])=>N.createElement(m,x)),...Array.isArray(c)?c:[c]]));/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const U0=(n,s)=>{const i=N.forwardRef(({className:l,...u},c)=>N.createElement(P_,{ref:c,iconNode:s,className:Px(`lucide-${E_(hm(n))}`,`lucide-${n}`,l),...u}));return i.displayName=hm(n),i};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const T_=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],D_=U0("check",T_);/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const R_=[["path",{d:"M4 5h16",key:"1tepv9"}],["path",{d:"M4 12h16",key:"1lakjw"}],["path",{d:"M4 19h16",key:"1djgab"}]],F_=U0("menu",R_);/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const N_=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],Tx=U0("x",N_);function L_({health:n,config:s,onSettingsClick:i,onMenuClick:l}){const u=(n==null?void 0:n.radio_connected)??!1,[c,h]=N.useState(!1),d=async()=>{h(!0);try{const g=await ut.reconnectRadio();g.connected&&At.success("Reconnected",{description:g.message})}catch(g){At.error("Reconnection failed",{description:g instanceof Error?g.message:"Check radio connection and power"})}finally{h(!1)}};return _.jsxs("div",{className:"flex items-center gap-4 px-4 py-2 bg-[#252525] border-b border-[#333] text-xs",children:[l&&_.jsx("button",{onClick:l,className:"md:hidden p-1 bg-transparent border-none text-[#e0e0e0] cursor-pointer","aria-label":"Open menu",children:_.jsx(F_,{className:"h-5 w-5"})}),_.jsx("h1",{className:"text-base font-semibold mr-auto",children:"RemoteTerm"}),_.jsxs("div",{className:"flex items-center gap-1 text-[#888]",children:[_.jsx("div",{className:`w-2 h-2 rounded-full ${u?"bg-[#4caf50]":"bg-[#666]"}`}),_.jsx("span",{className:"hidden lg:inline text-[#e0e0e0]",children:u?"Connected":"Disconnected"})]}),s&&_.jsxs("div",{className:"hidden lg:flex items-center gap-2 text-[#888]",children:[_.jsx("span",{className:"text-[#e0e0e0]",children:s.name||"Unnamed"}),_.jsx("span",{className:"font-mono text-[#888] cursor-pointer hover:text-[#4a9eff]",onClick:()=>{navigator.clipboard.writeText(s.public_key),At.success("Public key copied!")},title:"Click to copy public key",children:s.public_key.toLowerCase()})]}),!u&&_.jsx("button",{onClick:d,disabled:c,className:"px-3 py-1 bg-[#4a3000] border border-[#6b4500] text-[#ffa500] rounded text-xs cursor-pointer hover:bg-[#5a3a00] disabled:opacity-50 disabled:cursor-not-allowed",children:c?"Reconnecting...":"Reconnect"}),_.jsxs("button",{onClick:i,className:"px-3 py-1 bg-[#333] border border-[#444] text-[#e0e0e0] rounded text-xs cursor-pointer hover:bg-[#444]",children:[_.jsx("span",{role:"img","aria-label":"Settings",children:"🔧"})," ","Radio & Config"]})]})}const M_=12;function I_(n){return n.slice(0,M_)}function Ni(n,s){return n||I_(s)}const ia=2,O_={text:"🛜",background:"#444444",textColor:"#ffffff"};function j_(n){let s=0;for(let i=0;i<n.length;i++){const l=n.charCodeAt(i);s=(s<<5)-s+l,s=s&s}return Math.abs(s)}const z_=/[\u{1F1E0}-\u{1F1FF}]{2}|[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]/u;function H_(n,s){if(!n)return s.slice(0,2).toUpperCase();const i=n.match(z_);if(i)return i[0];const l=n.match(/[a-zA-Z]/g);if(!l||l.length===0)return s.slice(0,2).toUpperCase();const u=n.indexOf(" ");if(u!==-1){const c=l[0],h=n.slice(u+1).match(/[a-zA-Z]/);if(h)return(c+h[0]).toUpperCase()}return l[0].toUpperCase()}function V_(n){const s=j_(n),i=s%360,l=50+(s>>8)%30,u=35+(s>>16)%20,c=`hsl(${i}, ${l}%, ${u}%)`,h=u<45?"#ffffff":"#000000";return{background:c,text:h}}function U_(n,s,i){if(i===ia)return O_;const l=H_(n,s),u=V_(s);return{text:l,background:u.background,textColor:u.text}}function b0({name:n,publicKey:s,size:i=28,contactType:l}){const u=U_(n,s,l);return _.jsx("div",{className:"flex items-center justify-center rounded-full font-semibold flex-shrink-0 select-none",style:{backgroundColor:u.background,color:u.textColor,width:i,height:i,fontSize:i*.45},children:u.text})}const Dx="remoteterm-favorites";function rs(n,s,i){return n.some(l=>l.type===s&&l.id===i)}function Z_(){try{const n=localStorage.getItem(Dx);return n?JSON.parse(n):[]}catch{return[]}}function pm(){try{localStorage.removeItem(Dx)}catch{}}function Rx(n){var s,i,l="";if(typeof n=="string"||typeof n=="number")l+=n;else if(typeof n=="object")if(Array.isArray(n)){var u=n.length;for(s=0;s<u;s++)n[s]&&(i=Rx(n[s]))&&(l&&(l+=" "),l+=i)}else for(i in n)n[i]&&(l&&(l+=" "),l+=i);return l}function Fx(){for(var n,s,i=0,l="",u=arguments.length;i<u;i++)(n=arguments[i])&&(s=Rx(n))&&(l&&(l+=" "),l+=s);return l}const W_=(n,s)=>{const i=new Array(n.length+s.length);for(let l=0;l<n.length;l++)i[l]=n[l];for(let l=0;l<s.length;l++)i[n.length+l]=s[l];return i},q_=(n,s)=>({classGroupId:n,validator:s}),Nx=(n=new Map,s=null,i)=>({nextPart:n,validators:s,classGroupId:i}),Yc="-",mm=[],G_="arbitrary..",$_=n=>{const s=Q_(n),{conflictingClassGroups:i,conflictingClassGroupModifiers:l}=n;return{getClassGroupId:h=>{if(h.startsWith("[")&&h.endsWith("]"))return K_(h);const d=h.split(Yc),g=d[0]===""&&d.length>1?1:0;return Lx(d,g,s)},getConflictingClassGroupIds:(h,d)=>{if(d){const g=l[h],m=i[h];return g?m?W_(m,g):g:m||mm}return i[h]||mm}}},Lx=(n,s,i)=>{if(n.length-s===0)return i.classGroupId;const u=n[s],c=i.nextPart.get(u);if(c){const m=Lx(n,s+1,c);if(m)return m}const h=i.validators;if(h===null)return;const d=s===0?n.join(Yc):n.slice(s).join(Yc),g=h.length;for(let m=0;m<g;m++){const x=h[m];if(x.validator(d))return x.classGroupId}},K_=n=>n.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const s=n.slice(1,-1),i=s.indexOf(":"),l=s.slice(0,i);return l?G_+l:void 0})(),Q_=n=>{const{theme:s,classLine truncated
.`.concat(Rw,` {
overflow: hidden `).concat(l,`;
padding-right: `).concat(d,"px ").concat(l,`;
}
body[`).concat(na,`] {
overflow: hidden `).concat(l,`;
overscroll-behavior: contain;
`).concat([s&&"position: relative ".concat(l,";"),i==="margin"&&`
padding-left: `.concat(u,`px;
padding-top: `).concat(c,`px;
padding-right: `).concat(h,`px;
margin-left:0;
margin-top:0;
margin-right: `).concat(d,"px ").concat(l,`;
`),i==="padding"&&"padding-right: ".concat(d,"px ").concat(l,";")].filter(Boolean).join(""),`
}
.`).concat(ac,` {
right: `).concat(d,"px ").concat(l,`;
}
.`).concat(lc,` {
margin-right: `).concat(d,"px ").concat(l,`;
}
.`).concat(ac," .").concat(ac,` {
right: 0 `).concat(l,`;
}
.`).concat(lc," .").concat(lc,` {
margin-right: 0 `).concat(l,`;
}
body[`).concat(na,`] {
`).concat(Fw,": ").concat(d,`px;
}
`)},Rm=function(){var n=parseInt(document.body.getAttribute(na)||"0",10);return isFinite(n)?n:0},Xw=function(){N.useEffect(function(){return document.body.setAttribute(na,(Rm()+1).toString()),function(){var n=Rm()-1;n<=0?document.body.removeAttribute(na):document.body.setAttribute(na,n.toString())}},[])},Jw=function(n){var s=n.noRelative,i=n.noImportant,l=n.gapMode,u=l===void 0?"margin":l;Xw();var c=N.useMemo(function(){return Kw(u)},[u]);return N.createElement(Qw,{styles:Yw(c,!s,u,i?"":"!important")})},k0=!1;if(typeof window<"u")try{var Xu=Object.defineProperty({},"passive",{get:function(){return k0=!0,!0}});window.addEventListener("test",Xu,Xu),window.removeEventListener("test",Xu,Xu)}catch{k0=!1}var Xs=k0?{passive:!1}:!1,eb=function(n){return n.tagName==="TEXTAREA"},rv=function(n,s){if(!(n instanceof Element))return!1;var i=window.getComputedStyle(n);return i[s]!=="hidden"&&!(i.overflowY===i.overflowX&&!eb(n)&&i[s]==="visible")},tb=function(n){return rv(n,"overflowY")},nb=function(n){return rv(n,"overflowX")},Fm=function(n,s){var i=s.ownerDocument,l=s;do{typeof ShadowRoot<"u"&&l instanceof ShadowRoot&&(l=l.host);var u=iv(n,l);if(u){var c=ov(n,l),h=c[1],d=c[2];if(h>d)return!0}l=l.parentNode}while(l&&l!==i.body);return!1},rb=function(n){var s=n.scrollTop,i=n.scrollHeight,l=n.clientHeight;return[s,i,l]},ib=function(n){var s=n.scrollLeft,i=n.scrollWidth,l=n.clientWidth;return[s,i,l]},iv=function(n,s){return n==="v"?tb(s):nb(s)},ov=function(n,s){return n==="v"?rb(s):ib(s)},ob=function(n,s){return n==="h"&&s==="rtl"?-1:1},sb=function(n,s,i,l,u){var c=ob(n,window.getComputedStyle(s).direction),h=c*l,d=i.target,g=s.contains(d),m=!1,x=h>0,v=0,C=0;do{if(!d)break;var P=ov(n,d),M=P[0],k=P[1],w=P[2],B=k-w-c*M;(M||B)&&iv(n,d)&&(v+=B,C+=M);var b=d.parentNode;d=b&&b.nodeType===Node.DOCUMENT_FRAGMENT_NODE?b.host:b}while(!g&&d!==document.body||g&&(s.contains(d)||s===d));return(x&&Math.abs(v)<1||!x&&Math.abs(C)<1)&&(m=!0),m},Ju=function(n){return"changedTouches"in n?[n.changedTouches[0].clientX,n.changedTouches[0].clientY]:[0,0]},Nm=function(n){return[n.deltaX,n.deltaY]},Lm=function(n){return n&&"current"in n?n.current:n},ab=function(n,s){return n[0]===s[0]&&n[1]===s[1]},lb=function(n){return`
.block-interactivity-`.concat(n,` {pointer-events: none;}
.allow-interactivity-`).concat(n,` {pointer-events: all;}
`)},ub=0,Js=[];function cb(n){var s=N.useRef([]),i=N.useRef([0,0]),l=N.useRef(),u=N.useState(ub++)[0],c=N.useState(nv)[0],h=N.useRef(n);N.useEffect(function(){h.current=n},[n]),N.useEffect(function(){if(n.inert){document.body.classList.add("block-interactivity-".concat(u));var k=Dw([n.lockRef.current],(n.shards||[]).map(Lm),!0).filter(Boolean);return k.forEach(function(w){return w.classList.add("allow-interactivity-".concat(u))}),function(){document.body.classList.remove("block-interactivity-".concat(u)),k.forEach(function(w){return w.classList.remove("allow-interactivity-".concat(u))})}}},[n.inert,n.lockRef.current,n.shards]);var d=N.useCallback(function(k,w){if("touches"in k&&k.touches.length===2||k.type==="wheel"&&k.ctrlKey)return!h.current.allowPinchZoom;var B=Ju(k),b=i.current,E="deltaX"in k?k.deltaX:b[0]-B[0],T="deltaY"in k?k.deltaY:b[1]-B[1],F,I=k.target,j=Math.abs(E)>Math.abs(T)?"h":"v";if("touches"in k&&j==="h"&&I.type==="range")return!1;var O=window.getSelection(),G=O&&O.anchorNode,U=G?G===I||G.contains(I):!1;if(U)return!1;var K=Fm(j,I);if(!K)return!0;if(K?F=j:(F=j==="v"?"h":"v",K=Fm(j,I)),!K)return!1;if(!l.current&&"changedTouches"in k&&(E||T)&&(l.current=F),!F)return!0;var J=l.current||F;return sb(J,w,k,J==="h"?E:T)},[]),g=N.useCallback(function(k){var w=k;if(!(!Js.length||Js[Js.length-1]!==c)){var B="deltaY"in w?Nm(w):Ju(w),b=s.current.filter(function(F){return F.name===w.type&&(F.target===w.target||w.target===F.shadowParent)&&ab(F.delta,B)})[0];if(b&&b.should){w.cancelable&&w.preventDefault();return}if(!b){var E=(h.current.shards||[]).map(Lm).filter(Boolean).filter(function(F){return F.contains(w.target)}),T=E.length>0?d(w,E[0]):!h.current.noIsolation;T&&w.cancelable&&w.preventDefault()}}},[]),m=N.useCallback(function(k,w,B,b){var E={name:k,delta:w,target:B,should:b,shadowParent:db(B)};s.current.push(E),setTimeout(function(){s.current=s.current.filter(function(T){return T!==E})},1)},[]),x=N.useCallback(function(k){i.current=Ju(k),l.current=void 0},[]),v=N.useCallback(function(k){m(k.type,Nm(k),k.target,d(k,n.lockRef.current))},[]),C=N.useCallback(function(k){m(k.type,Ju(k),k.target,d(k,n.lockRef.current))},[]);N.useEffect(function(){return Js.push(c),n.setCallbacks({onScrollCapture:v,onWheelCapture:v,onTouchMoveCapture:C}),document.addEventListener("wheel",g,Xs),document.addEventListener("touchmove",g,Xs),document.addEventListener("touchstart",x,Xs),function(){Js=Js.filter(function(k){return k!==c}),document.removeEventListener("wheel",g,Xs),document.removeEventListener("touchmove",g,Xs),document.removeEventListener("touchstart",x,Xs)}},[]);var P=n.removeScrollBar,M=n.inert;return N.createElement(N.Fragment,null,M?N.createElement(c,{styles:lb(u)}):null,P?N.createElement(Jw,{noRelative:n.noRelative,gapMode:n.gapMode}):null)}function db(n){for(var s=null;n!==null;)n instanceof ShadowRoot&&(s=n.host,n=n.host),n=n.parentNode;return s}const fb=zw(tv,cb);var sv=N.forwardRef(function(n,s){return N.createElement(ud,si({},n,{ref:s,sideCar:fb}))});sv.classNames=ud.classNames;var hb=function(n){if(typeof document>"u")return null;var s=Array.isArray(n)?n[0]:n;return s.ownerDocument.body},ea=new WeakMap,ec=new WeakMap,tc={},h0=0,av=function(n){return n&&(n.host||av(n.parentNode))},pb=function(n,s){return s.map(function(i){if(n.contains(i))return i;var l=av(i);return l&&n.contains(l)?l:(console.error("aria-hidden",i,"in not contained inside",n,". Doing nothing"),null)}).filter(function(i){return!!i})},mb=function(n,s,i,l){var u=pb(s,Array.isArray(n)?n:[n]);tc[i]||(tc[i]=new WeakMap);var c=tc[i],h=[],d=new Set,g=new Set(u),m=function(v){!v||d.has(v)||(d.add(v),m(v.parentNode))};u.forEach(m);var x=function(v){!v||g.has(v)||Array.prototype.forEach.call(v.children,function(C){if(d.has(C))x(C);else try{var P=C.getAttribute(l),M=P!==null&&P!=="false",k=(ea.get(C)||0)+1,w=(c.get(C)||0)+1;ea.set(C,k),c.set(C,w),h.push(C),k===1&&M&&ec.set(C,!0),w===1&&C.setAttribute(i,"true"),M||C.setAttribute(l,"true")}catch(B){console.error("aria-hidden: cannot operate on ",C,B)}})};return x(s),d.clear(),h0++,function(){h.forEach(function(v){var C=ea.get(v)-1,P=c.get(v)-1;ea.set(v,C),c.set(v,P),C||(ec.has(v)||v.removeAttribute(l),ec.delete(v)),P||v.removeAttribute(i)}),h0--,h0||(ea=new WeakMap,ea=new WeakMap,ec=new WeakMap,tc={})}},gb=function(n,s,i){i===void 0&&(i="data-aria-hidden");var l=Array.from(Array.isArray(n)?n:[n]),u=hb(n);return u?(l.push.apply(l,Array.from(u.querySelectorAll("[aria-live], script"))),mb(l,u,i,"aria-hidden")):function(){return null}};function xb(n){const s=vb(n),i=N.forwardRef((l,u)=>{const{children:c,...h}=l,d=N.Children.toArray(c),g=d.find(yb);if(g){const m=g.props.children,x=d.map(v=>v===g?N.Children.count(m)>1?N.Children.only(null):N.isValidElement(m)?m.props.children:null:v);return _.jsx(s,{...h,ref:u,children:N.isValidElement(m)?N.cloneElement(m,void 0,x):null})}return _.jsx(s,{...h,ref:u,children:c})});return i.displayName=`${n}.Slot`,i}function vb(n){const s=N.forwardRef((i,l)=>{const{children:u Line truncated
If you want to hide the \`${s.titleName}\`, you can wrap it with our VisuallyHidden component.
For more information, see https://radix-ui.com/primitives/docs/components/${s.docsSlug}`;return N.useEffect(()=>{n&&(document.getElementById(n)||console.error(i))},[i,n]),null},Db="DialogDescriptionWarning",Rb=({contentRef:n,descriptionId:s})=>{const l=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${wv(Db).contentName}}.`;return N.useEffect(()=>{var c;const u=(c=n.current)==null?void 0:c.getAttribute("aria-describedby");s&&u&&(document.getElementById(s)||console.warn(l))},[l,n,s]),null},bv=uv,Cv=fv,dd=hv,fd=pv,hd=gv,pd=vv,Ev=yv;const Q0=bv,Fb=Cv,kv=N.forwardRef(({className:n,...s},i)=>_.jsx(dd,{ref:i,className:pt("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",n),...s}));kv.displayName=dd.displayName;const md=N.forwardRef(({className:n,children:s,...i},l)=>_.jsxs(Fb,{children:[_.jsx(kv,{}),_.jsxs(fd,{ref:l,className:pt("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",n),...i,children:[s,_.jsxs(Ev,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[_.jsx(Tx,{className:"h-4 w-4"}),_.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));md.displayName=fd.displayName;const gd=({className:n,...s})=>_.jsx("div",{className:pt("flex flex-col space-y-1.5 text-center sm:text-left",n),...s});gd.displayName="DialogHeader";const Y0=({className:n,...s})=>_.jsx("div",{className:pt("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",n),...s});Y0.displayName="DialogFooter";const xd=N.forwardRef(({className:n,...s},i)=>_.jsx(hd,{ref:i,className:pt("text-lg font-semibold leading-none tracking-tight",n),...s}));xd.displayName=hd.displayName;const vd=N.forwardRef(({className:n,...s},i)=>_.jsx(pd,{ref:i,className:pt("text-sm text-muted-foreground",n),...s}));vd.displayName=pd.displayName;function Nb(){const n=window.location.hash.slice(1);if(!n)return null;if(n==="raw")return{type:"raw",name:"raw"};if(n==="map")return{type:"map",name:"map"};if(n==="visualizer")return{type:"visualizer",name:"visualizer"};if(n.startsWith("map/focus/")){const u=n.slice(10);return u?{type:"map",name:"map",mapFocusKey:decodeURIComponent(u)}:{type:"map",name:"map"}}const s=n.indexOf("/");if(s===-1)return null;const i=n.slice(0,s),l=decodeURIComponent(n.slice(s+1));return(i==="channel"||i==="contact")&&l?{type:i,name:l}:null}function Sv(n){return`#map/focus/${encodeURIComponent(n)}`}function Lb(n){if(!n)return"";if(n.type==="raw")return"#raw";if(n.type==="map")return"#map";if(n.type==="visualizer")return"#visualizer";const s=n.type==="channel"&&n.name.startsWith("#")?n.name.slice(1):n.name;return`#${n.type}/${encodeURIComponent(s)}`}function Mb(n){const s=Lb(n);s!==window.location.hash&&window.history.replaceState(null,"",s||window.location.pathname)}function Ib({open:n,onClose:s,paths:i,senderInfo:l,contacts:u,config:c}){const h=i.map(g=>({...g,resolved:$1(g.path,l,u,c)})),d=i.length===1;return _.jsx(Q0,{open:n,onOpenChange:g=>!g&&s(),children:_.jsxs(md,{className:"max-w-md max-h-[80vh] flex flex-col",children:[_.jsxs(gd,{children:[_.jsxs(xd,{children:["Message Path",!d&&`s (${i.length})`]}),_.jsx(vd,{children:d?_.jsxs(_.Fragment,{children:["This shows ",_.jsx("em",{children:"one route"})," that this message traveled through the mesh network. Routers may be incorrectly identified due to prefix collisions between heard and non-heard router advertisements."]}):_.jsxs(_.Fragment,{children:["This message was received via ",_.jsxs("strong",{children:[i.length," different routes"]}),". Routers may be incorrectly identified due to prefix collisions."]})})]}),_.jsxs("div",{className:"flex-1 overflow-y-auto py-2 space-y-4",children:[h.map((g,m)=>_.jsxs("div",{children:[!d&&_.jsxs("div",{className:"text-xs text-muted-foreground font-medium mb-2 pb-1 border-b border-border",children:["Path ",m+1," — received ",oa(g.received_at)]}),_.jsx(Ob,{resolved:g.resolved,senderInfo:l,hideStraightLine:!d})]},m)),!d&&h.length>0&&(()=>{const g=h[0].resolved;return Lt(g.sender.lat,g.sender.lon)&&Lt(g.receiver.lat,g.receiver.lon)?_.jsxs("div",{className:"pt-3 mt-1 border-t border-border",children:[_.jsx("span",{className:"text-sm text-muted-foreground",children:"Straight-line distance: "}),_.jsx("span",{className:"text-sm font-medium",c Line truncated
`).map((Q,ae,ce)=>_.jsxs("span",{children:[Hb(Q,d),ae<ce.length-1&&_.jsx("br",{})]},ae)),!te&&_.jsxs(_.Fragment,{children:[_.jsx("span",{className:"text-[10px] text-muted-foreground/50 ml-2",children:oa(O.sender_timestamp||O.received_at)}),!O.outgoing&&O.paths&&O.paths.length>0&&_.jsx(Im,{paths:O.paths,variant:"inline",onClick:()=>k({paths:O.paths,senderInfo:F(O,U,J)})})]}),O.outgoing&&(O.acked>0?` ✓${O.acked>1?O.acked:""}`:" ?")]})]})]},O.id)})]}),C&&_.jsx("button",{onClick:b,className:"absolute bottom-4 right-4 w-10 h-10 rounded-full bg-muted hover:bg-accent border border-border flex items-center justify-center shadow-lg transition-opacity",title:"Scroll to bottom",children:_.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"text-muted-foreground",children:_.jsx("polyline",{points:"6 9 12 15 18 9"})})}),M&&_.jsx(Ib,{open:!0,onClose:()=>k(null),paths:M.paths,senderInfo:M.senderInfo,contacts:s,config:g??null})]})}const Om=156,Ub=140,Zb=156,Wb=120,qb=8,Gb=N.forwardRef(function({onSend:s,disabled:i,placeholder:l,isRepeaterMode:u,conversationType:c,senderName:h},d){const[g,m]=N.useState(""),[x,v]=N.useState(!1),C=N.useRef(null);N.useImperativeHandle(d,()=>({appendText:F=>{var I;m(j=>j+F),(I=C.current)==null||I.focus()}}));const P=N.useMemo(()=>{if(c==="contact")return{warningAt:Ub,dangerAt:Om,hardLimit:Om};if(c==="channel"){const F=(h==null?void 0:h.length)??10,I=Math.max(1,Zb-F-2);return{warningAt:Wb,dangerAt:Math.max(1,I-qb),hardLimit:I}}return null},[c,h]),{limitState:M,warningMessage:k}=N.useMemo(()=>{if(!P)return{limitState:"normal",warningMessage:null};const F=g.length;return F>=P.hardLimit?{limitState:"error",warningMessage:"likely truncated by radio"}:F>=P.dangerAt?{limitState:"danger",warningMessage:"may impact multi-repeater hop delivery"}:F>=P.warningAt?{limitState:"warning",warningMessage:"may impact multi-repeater hop delivery"}:{limitState:"normal",warningMessage:null}},[g.length,P]),w=P?P.hardLimit-g.length:0,B=N.useCallback(async F=>{F.preventDefault();const I=g.trim();if(u){if(x||i)return;v(!0);try{await s(I),m("")}catch(j){console.error("Failed to request telemetry:",j),At.error("Failed to request telemetry",{description:j instanceof Error?j.message:"Check radio connection"});return}finally{v(!1)}setTimeout(()=>{var j;return(j=C.current)==null?void 0:j.focus()},0)}else{if(!I||x||i)return;v(!0);try{await s(I),m("")}catch(j){console.error("Failed to send message:",j),At.error("Failed to send message",{description:j instanceof Error?j.message:"Check radio connection"});return}finally{v(!1)}setTimeout(()=>{var j;return(j=C.current)==null?void 0:j.focus()},0)}},[g,x,i,s,u]),b=N.useCallback(F=>{F.key==="Enter"&&!F.shiftKey&&(F.preventDefault(),B(F))},[B]),E=u?!0:g.trim().length>0,T=!u&&P!==null;return _.jsxs("form",{className:"px-4 py-3 border-t border-border flex flex-col gap-1",onSubmit:B,children:[_.jsxs("div",{className:"flex gap-2",children:[_.jsx(on,{ref:C,type:u?"password":"text",autoComplete:u?"off":void 0,value:g,onChange:F=>m(F.target.value),onKeyDown:b,placeholder:l||(u?"Enter password for admin login...":"Type a message..."),disabled:i||x,className:"flex-1 min-w-0"}),_.jsx(mn,{type:"submit",disabled:i||x||!E,className:"flex-shrink-0",children:x?u?"Logging in...":"Sending...":u?g.trim()?"Log in with password":"Log in as guest/use repeater ACLs":"Send"})]}),T&&_.jsxs("div",{className:"flex items-center justify-end gap-2 text-xs",children:[_.jsxs("span",{className:pt("tabular-nums",M==="error"||M==="danger"?"text-red-500 font-medium":M==="warning"?"text-yellow-500":"text-muted-foreground"),children:[g.length,"/",P.hardLimit,w<0&&` (${w})`]}),k&&_.jsxs("span",{className:pt(M==="error"?"text-red-500":"text-yellow-500"),children:["— ",k]})]})]})});function jm(n){const s=$b(n),i=N.forwardRef((l,u)=>{const{children:c,...h}=l,d=N.Children.toArray(c),g=d.find(Qb);if(g){const m=g.props.children,x=d.map(v=>v===g?N.Children.count(m)>1?N.Children.only(null):N.isValidElement(m)?m.props.children:null:v);return _.jsx(s,{...h,ref:u,children:N.isValidElement(m)?N.cloneElement(m,void 0,x):null})}return _.jsx(s,{...h,ref:u,children:c})});return i.displayName=`${n}.Slot`,i}function $b(n){const s=N.forwardRef((i,l)=>{const{children:u,...c}=i;if(N.isValidElement(u)){const h=Xb(u),d=Yb(c,u.props);return u.type!==N.Fragment&&(d.ref=l?Sl(l,h):h),N.cloneElement(u,d)}return N.Children.count(u)>1?N.Children.only(null):null});return s.displayName=`${n}.SlotClone`,s}var Kb=Symbol("radix.slottable");function Qb(n){return N.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===Kb}function Yb(n,s){const i={...s};for(const l in s){const u=n[l],c=s[l];/^on[A-Z]/.test(l)?u&&c?i[l]=(...d)=>{const g=c(...d);return u(...d),g}:u&&(i[l]=u):l==="style"?i[l]={...u,...c}:l==="className"&&(i[l]=[u,c].filter(Boolean).join(" "))}return{...n,...i}}function Line truncated
/**
* Reset the text fill color so that placeholder is visible
*/
.`.concat(B,`:empty {
-webkit-text-fill-color: inherit !important;
}
/**
* Hack to apply on some CSS on IE10 and IE11
*/
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
/**
* IE doesn't support '-webkit-text-fill-color'
* So we use 'color: transparent' to make the text transparent on IE
* Unlike other browsers, it doesn't affect caret color in IE
*/
.`).concat(B,` {
color: transparent !important;
}
.`).concat(B,`::selection {
background-color: #accef7 !important;
color: transparent !important;
}
}
`),E=c.forwardRef(function(I,j){var O=I.autoFocus,G=I.disabled,U=I.form,K=I.highlight,J=I.ignoreTabKey,Y=J===void 0?!1:J,ie=I.insertSpaces,ge=ie===void 0?!0:ie,$=I.maxLength,se=I.minLength,W=I.name,te=I.onBlur,Z=I.onClick,D=I.onFocus,H=I.onKeyDown,q=I.onKeyUp,Q=I.onValueChange,ae=I.padding,ce=ae===void 0?0:ae,Ae=I.placeholder,pe=I.preClassName,xe=I.readOnly,Be=I.required,Oe=I.style,Xe=I.tabSize,Ee=Xe===void 0?2:Xe,je=I.textareaClassName,at=I.textareaId,mt=I.value,ot=u(I,["autoFocus","disabled","form","highlight","ignoreTabKey","insertSpaces","maxLength","minLength","name","onBlur","onClick","onFocus","onKeyDown","onKeyUp","onValueChange","padding","placeholder","preClassName","readOnly","required","style","tabSize","textareaClassName","textareaId","value"]),qe=c.useRef({stack:[],offset:-1}),Ke=c.useRef(null),Qe=c.useState(!0),rt=Qe[0],He=Qe[1],Et={paddingTop:typeof ce=="object"?ce.top:ce,paddingRight:typeof ce=="object"?ce.right:ce,paddingBottom:typeof ce=="object"?ce.bottom:ce,paddingLeft:typeof ce=="object"?ce.left:ce},zt=K(mt),Qt=function(_e,fe){return _e.substring(0,fe).split(`
`)},Dt=c.useCallback(function(_e,fe){var ve,we,Ge;fe===void 0&&(fe=!1);var re=qe.current,ye=re.stack,Ce=re.offset;if(ye.length&&Ce>-1){qe.current.stack=ye.slice(0,Ce+1);var Ne=qe.current.stack.length;if(Ne>P){var Je=Ne-P;qe.current.stack=ye.slice(Je,Ne),qe.current.offset=Math.max(qe.current.offset-Je,0)}}var Fe=Date.now();if(fe){var ft=qe.current.stack[qe.current.offset];if(ft&&Fe-ft.timestamp<M){var St=/[^a-z0-9]([a-z0-9]+)$/i,xt=(ve=Qt(ft.value,ft.selectionStart).pop())===null||ve===void 0?void 0:ve.match(St),an=(we=Qt(_e.value,_e.selectionStart).pop())===null||we===void 0?void 0:we.match(St);if(xt!=null&&xt[1]&&(!((Ge=an==null?void 0:an[1])===null||Ge===void 0)&&Ge.startsWith(xt[1]))){qe.current.stack[qe.current.offset]=n(n({},_e),{timestamp:Fe});return}}}qe.current.stack.push(n(n({},_e),{timestamp:Fe})),qe.current.offset++},[]),Gt=c.useCallback(function(){var _e=Ke.current;if(_e){var fe=_e.value,ve=_e.selectionStart,we=_e.selectionEnd;Dt({value:fe,selectionStart:ve,selectionEnd:we})}},[Dt]),Yt=function(_e){var fe=Ke.current;fe&&(fe.value=_e.value,fe.selectionStart=_e.selectionStart,fe.selectionEnd=_e.selectionEnd,Q==null||Q(_e.value))},$t=function(_e){var fe=Ke.current,ve=qe.current.stack[qe.current.offset];ve&&fe&&(qe.current.stack[qe.current.offset]=n(n({},ve),{selectionStart:fe.selectionStart,selectionEnd:fe.selectionEnd})),Dt(_e),Yt(_e)},Ht=function(){var _e=qe.current,fe=_e.stack,ve=_e.offset,we=fe[ve-1];we&&(Yt(we),qe.current.offset=Math.max(ve-1,0))},Rt=function(){var _e=qe.current,fe=_e.stack,ve=_e.offset,we=fe[ve+1];we&&(Yt(we),qe.current.offset=Math.min(ve+1,fe.length-1))},Vt=function(_e){if(!(H&&(H(_e),_e.defaultPrevented))){_e.key==="Escape"&&_e.currentTarget.blur();var fe=_e.currentTarget,ve=fe.value,we=fe.selectionStart,Ge=fe.selectionEnd,re=(ge?" ":" ").repeat(Ee);if(_e.key==="Tab"&&!Y&&rt)if(_e.preventDefault(),_e.shiftKey){var ye=Qt(ve,we),Ce=ye.length-1,Ne=Qt(ve,Ge).length-1,Je=ve.split(`
`).map(function(Mt,Le){return Le>=Ce&&Le<=Ne&&Mt.startsWith(re)?Mt.substring(re.length):Mt}).join(`
`);if(ve!==Je){var Fe=ye[Ce];$t({value:Je,selectionStart:Fe!=null&&Fe.startsWith(re)?we-re.length:we,selectionEnd:Ge-(ve.length-Je.length)})}}else if(we!==Ge){var ye=Qt(ve,we),ft=ye.length-1,St=Qt(ve,Ge).length-1,Fe=ye[ft];$t({value:ve.split(`
`).map(function(Br,li){return li>=ft&&li<=St?re+Br:Br}).join(`
`),selectionStart:Fe&&/\S/.test(Fe)?we+re.length:we,selectionEnd:Ge+re.length*(St-ft+1)})}else{var xt=we+re.length;$t({value:ve.substring(0,we)+re+ve.substring(Ge),selectionStart:xt,selectionEnd:xt})}else if(_e.key==="Backspace"){var an=we!==Ge,dt=ve.substring(0,we);if(dt.endsWith(re)&&!an){_e.preventDefault();var xt=we-re.length;$t({value:ve.substring(0,we-re.length)+ve.substring(Ge),selectionStart:xt,selectionEnd:xt})}}else if(_e.key==="Enter"){if(we===Ge){var Pt=Qt(ve,we).pop(),vn=Pt==null?void 0:Pt.match(/^\s+/);if(vn!=null&&vn[0]){_e.preventDefault();var wt=`
`+vn[0],xt=we+wt.length;$t({value:ve.substring(0,we)+wt+ve.substring(Ge),selectionStart:xt,selectionEnd:xt})}}}else if(_e.keyCode===m||_e.keyCode===x||_e.keyCode===v||_e.keyCode===C){var kt=void 0;_e.keyCode===m&&_e.shiftKey?kt=["(",")"]:_e.keyCode===x?_e.shiftKey?kt=["{","}"]:kt=["[","]"]:_e.keyCode===v?_e.shiftKey?kt=['"','"']:kt=["'","'"]:_e.keyCode===C&&!_e.shiftKey&&(kt=["`","`"]),we!==Ge&&kt&&(_e.preventDefault(),$t({value:ve.substring(0,we)+kt[0]+ve.substring(we,Ge)+kt[1]+ve.substring(Ge),selectionStart:we,selectionEnd:Ge+2}))}else(w?_e.metaKey&&_e.keyCode===d:_e.ctrlKey&&_e.keyCode===d)&&!_e.shiftKey&&!_e.altKey?(_e.preventDefault(),Ht()):(w?_e.metaKey&&_e.keyCode===d&&_e.shiftKey:k?_e.ctrlKey&&_e.keyCode===h:_e.ctrlKey&&_e.keyCode===d&&_e.shiftKey)&&!_e.altKey?(_e.preventDefault(),Rt()):_e.keyCode===g&&_e.ctrlKey&&(!w||_e.shiftKey)&&(_e.preventDefault(),He(function(Mt){return!Mt}))}},Pe=function(_e){var fe=_e.currentTarget,ve=fe.value,we=fe.selectionStart,Ge=fe.selectionEnd;Dt({value:ve,selectionStart:we,selectionEnd:Ge},!0),Q(ve)};return c.useEffect(function(){Gt()},[Gt]),c.useImperativeHandle(j,function(){return{get session(){return{history:qe.current}},set session(_e){qe.current=_e.history}}},[]),c.createElement("div",n({},ot,{style:n(n({},T.container),Oe)}),c.createElement("pre",n({className:pe,"aria-hidden":"true",style:n(n(n({},T.editor),T.highlight),Et)},typeof zt=="string"?{dangerouslySetInnerHTML:{__html:zt+"<br />"}}:{children:zt})),c.createElement("textarea",{ref:function(_e){return Ke.current=_e},style:n(n(n({},T.editor),T.textarea),Et),className:B+(je?" ".concat(je):""),id:at,value:mt,onChange:Pe,onKeyDown:Vt,onClick:Z,onKeyUp:q,onFocus:D,onBlur:te,disabled:G,form:U,maxLength:$,minLength:se,name:W,placeholder:Ae,readOnly:xe,required:Be,autoFocus:O,autoCapitalize:"off",autoComplete:"off",autoCorrect:"off",spellCheck:!1,"data-gramm":!1}),c.createElement("style",{dangerouslySetInnerHTML:{__html:b}}))}),T={container:{position:"relative",textAlign:"left",boxSizing:"border-box",padding:0,overflow:"hidden"},textarea:{position:"absolute",top:0,left:0,height:"100%",width:"100%",resize:"none",color:"inherit",overflow:"hidden",MozOsxFontSmoothing:"grayscale",WebkitFontSmoothing:"antialiased",WebkitTextFillColor:"transparent"},highlight:{position:"relative",pointerEvents:"none"},editor:{margin:0,border:0,background:"none",boxSizing:"inherit",display:"inherit",fontFamily:"inherit",fontSize:"inherit",fontStyle:"inherit",fontVariantLigatures:"inherit",fontWeight:"inherit",letterSpacing:"inherit",lineHeight:"inherit",tabSize:"inherit",textIndent:"inherit",textRendering:"inherit",textTransform:"inherit",whiteSpace:"pre-wrap",wordBreak:"keep-all",overflowWrap:"break-word"}};return Xn.default=E,Xn}var B2=S2();const P2=ls(B2);var m0={exports:{}},Hm;function T2(){return Hm||(Hm=1,(function(n){var s=typeof window<"u"?window:typeof WorkerGlobalScope<"u"&&self instanceof WorkerGlobalScope?self:{};/**
* Prism: Lightweight, robust, elegant syntax highlighting
*
* @license MIT <https://opensource.org/licenses/MIT>
* @author Lea Verou <https://lea.verou.me>
* @namespace
* @public
*/var i=(function(l){var u=/(?:^|\s)lang(?:uage)?-([\w-]+)(?=\s|$)/i,c=0,h={},d={manual:l.Prism&&l.Prism.manual,disableWorkerMessageHandler:l.Prism&&l.Prism.disableWorkerMessageHandler,util:{encode:function b(E){return E instanceof g?new g(E.type,b(E.content),E.alias):Array.isArray(E)?E.map(b):E.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/\u00a0/g," ")},type:function(b){return Object.prototype.toString.call(b).slice(8,-1)},objId:function(b){return b.__id||Object.defineProperty(b,"__id",{value:++c}),b.__id},clone:function b(E,T){T=T||{};var F,I;switch(d.util.type(E)){case"Object":if(I=d.util.objId(E),T[I])return T[I];F={},T[I]=F;for(var j in E)E.hasOwnProperty(j)&&(F[j]=b(E[j],T));return F;case"Array":return I=d.util.objId(E),T[I]?T[I]:(F=[],T[I]=F,E.forEach(function(O,G){F[G]=b(O,T)}),F);default:return E}},getLanguage:function(b){for(;b;){var E=u.exec(b.className);if(E)return E[1].toLowerCase();b=b.parentElement}return"none"},setLanguage:function(b,E){b.className=b.className.replace(RegExp(u,"gi"),""),b.classList.add("language-"+E)},currentScript:function(){if(typeof document>"u")return null;if(document.currentScript&&document.currentScript.tagName==="SCRIPT")return document.currentScript;try{throw new Error}catch(F){var b=(/at [^(\r\n]*\((.*):[^:]+:[^:]+\)$/i.exec(F.stack)||[])[1];if(b){var E=document.getElementsByTagName("script");for(var T in E)if(E[T].src==b)return E[T]}return null}},isActive:function(b,E,T){for(var F="no-"+E;b;){var I=b.classList;if(I.contains(E))return!0;if(I.contains(F))return!1;b=b.parentElement}return!!T}},languages:{plain:h,plaintext:h,text:h,txt:h,extend:function(b,E){var T=d.util.clone(d.languages[b]);for(var F in E)T[F]=E[F];return T},insertBefore:function(b,E,T,F){F=F||d.languages;var I=F[b],j={};for(var O in I)if(I.hasOwnProperty(O)){if(O==E)for(var G in T)T.hasOwnProperty(G)&&(j[G]=T[G]);T.hasOwnProperty(O)||(j[O]=I[O])}var U=F[b];return F[b]=j,d.languages.DFS(d.languages,function(K,J){J===U&&K!=b&&(this[K]=j)}),j},DFS:function b(E,T,F,I){I=I||{};var j=d.util.objId;for(var O in E)if(E.hasOwnProperty(O)){T.call(E,O,E[O],F||O);var G=E[O],U=d.util.type(G);U==="Object"&&!I[j(G)]?(I[j(G)]=!0,b(G,T,null,I)):U==="Array"&&!I[j(G)]&&(I[j(G)]=!0,b(G,T,O,I))}}},plugins:{},highlightAll:function(b,E){d.highlightAllUnder(document,b,E)},highlightAllUnder:function(b,E,T){var F={callback:T,container:b,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};d.hooks.run("before-highlightall",F),F.elements=Array.prototype.slice.apply(F.container.querySelectorAll(F.selector)),d.hooks.run("before-all-elements-highlight",F);for(var I=0,j;j=F.elements[I++];)d.highlightElement(j,E===!0,F.callback)},highlightElement:function(b,E,T){var F=d.util.getLanguage(b),I=d.languages[F];d.util.setLanguage(b,F);var j=b.parentElement;j&&j.nodeName.toLowerCase()==="pre"&&d.util.setLanguage(j,F);var O=b.textContent,G={element:b,language:F,grammar:I,code:O};function U(J){G.highlightedCode=J,d.hooks.run("before-insert",G),G.element.innerHTML=G.highlightedCode,d.hooks.run("after-highlight",G),d.hooks.run("complete",G),T&&T.call(G.element)}if(d.hooks.run("before-sanity-check",G),j=G.element.parentElement,j&&j.nodeName.toLowerCase()==="pre"&&!j.hasAttribute("tabindex")&&j.setAttribute("tabindex","0"),!G.code){d.hooks.run("complete",G),T&&T.call(G.element);return}if(d.hooks.run("before-highlight",G),!G.grammar){U(d.util.encode(G.code));return}if(E&&l.Worker){var K=new Worker(d.filename);K.onmessage=function(J){U(J.data)},K.postMessage(JSON.stringify({language:G.language,code:G.code,immediateClose:!0}))}else U(d.highlight(G.code,G.grammar,G.language))},highlight:function(b,E,T){var F={code:b,grammar:E,language:T};if(d.hooks.run("before-tokenize",F),!F.grammar)throw new Error('The language "'+F.language+'" has no grammar.');return F.tokens=d.tokenize(F.code,F.grammar),d.hooks.run("after-tokenize",F),g.stringify(d.util.encode(F.tokens),F.language)},tokenize:function(b,E){var T=E.rest;if(T){for(var F in T)E[F]=T[F];delete E.rest}var I=new v;return C(I,I.head,b),x(b,I,E,I.head,0),M(I)},hooks:{all:{},add:function(b,E){var T=d.hooks.all;T[b]=T[b]||[],T[b].push(E)},run:function(b,E){var T=d.hooks.all[b];if(!(!T||!T.length))for(var F=0,I;I=T[F++];)I(E)}},Token:g};l.Prism=d;function g(b,E,T,F){this.type=b,this.content=E,this.alias=T,this.length=(F||"").length|0}g.stringify=function b(E,T){if(typeof E=="string")return E;if(Array.isArray(E)){var F="";return E.forEach(function(U){F+=b(U,T)}),F}var I={type:E.type,content:b(E.content,T),tag:"span",classes:["token",E.type],attributes:{},language:T},j=E.alias;j&&(Array.isArray(j)?Array.prototype.push.apply(I.classes,j):I.classes.push(j)),d.hooks.run("wrap",I);var O="";for(var G in I.attributes)O+=" "+G+'="'+(I.attributes[G]||"").replace(/"/g,"&quot;")+'"';return"<"+I.tag+' class="'+I.classes.join(" ")+'"'+O+">"+I.content+"</"+I.tag+">"};function m(b,E,T,F){b.lastIndex=E;var I=b.exec(T);if(I&&F&&I[1]){var j=I[1].length;I.indexLine truncated
`),w.hasAttribute("data-start")||w.setAttribute("data-start",String(G+1))}B.textContent=I,i.highlightElement(B)},function(I){w.setAttribute(d,x),B.textContent=I})}}),i.plugins.fileHighlight={highlight:function(w){for(var B=(w||document).querySelectorAll(v),b=0,E;E=B[b++];)i.highlightElement(E)}};var M=!1;i.fileHighlight=function(){M||(console.warn("Prism.fileHighlight is deprecated. Use `Prism.plugins.fileHighlight.highlight` instead."),M=!0),i.plugins.fileHighlight.highlight.apply(this,arguments)}})()})(m0)),m0.exports}var Vm=T2(),Um={},Zm;function D2(){return Zm||(Zm=1,Prism.languages.python={comment:{pattern:/(^|[^\\])#.*/,lookbehind:!0,greedy:!0},"string-interpolation":{pattern:/(?:f|fr|rf)(?:("""|''')[\s\S]*?\1|("|')(?:\\.|(?!\2)[^\\\r\n])*\2)/i,greedy:!0,inside:{interpolation:{pattern:/((?:^|[^{])(?:\{\{)*)\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}]|\{(?!\{)(?:[^{}])+\})+\})+\}/,lookbehind:!0,inside:{"format-spec":{pattern:/(:)[^:(){}]+(?=\}$)/,lookbehind:!0},"conversion-option":{pattern:/![sra](?=[:}]$)/,alias:"punctuation"},rest:null}},string:/[\s\S]+/}},"triple-quoted-string":{pattern:/(?:[rub]|br|rb)?("""|''')[\s\S]*?\1/i,greedy:!0,alias:"string"},string:{pattern:/(?:[rub]|br|rb)?("|')(?:\\.|(?!\1)[^\\\r\n])*\1/i,greedy:!0},function:{pattern:/((?:^|\s)def[ \t]+)[a-zA-Z_]\w*(?=\s*\()/g,lookbehind:!0},"class-name":{pattern:/(\bclass\s+)\w+/i,lookbehind:!0},decorator:{pattern:/(^[\t ]*)@\w+(?:\.\w+)*/m,lookbehind:!0,alias:["annotation","punctuation"],inside:{punctuation:/\./}},keyword:/\b(?:_(?=\s*:)|and|as|assert|async|await|break|case|class|continue|def|del|elif|else|except|exec|finally|for|from|global|if|import|in|is|lambda|match|nonlocal|not|or|pass|print|raise|return|try|while|with|yield)\b/,builtin:/\b(?:__import__|abs|all|any|apply|ascii|basestring|bin|bool|buffer|bytearray|bytes|callable|chr|classmethod|cmp|coerce|compile|complex|delattr|dict|dir|divmod|enumerate|eval|execfile|file|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|intern|isinstance|issubclass|iter|len|list|locals|long|map|max|memoryview|min|next|object|oct|open|ord|pow|property|range|raw_input|reduce|reload|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unichr|unicode|vars|xrange|zip)\b/,boolean:/\b(?:False|None|True)\b/,number:/\b0(?:b(?:_?[01])+|o(?:_?[0-7])+|x(?:_?[a-f0-9])+)\b|(?:\b\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\B\.\d+(?:_\d+)*)(?:e[+-]?\d+(?:_\d+)*)?j?(?!\w)/i,operator:/[-+%=]=?|!=|:=|\*\*?=?|\/\/?=?|<[<=>]?|>[=>]?|[&|^~]/,punctuation:/[{}[\];(),.:]/},Prism.languages.python["string-interpolation"].inside.interpolation.inside.rest=Prism.languages.python,Prism.languages.py=Prism.languages.python),Um}D2();var R2=["a","button","div","form","h2","h3","img","input","label","li","nav","ol","p","select","span","svg","ul"],F2=R2.reduce((n,s)=>{const i=W0(`Primitive.${s}`),l=N.forwardRef((u,c)=>{const{asChild:h,...d}=u,g=h?i:s;return typeof window<"u"&&(window[Symbol.for("radix-ui")]=!0),_.jsx(g,{...d,ref:c})});return l.displayName=`Primitive.${s}`,{...n,[s]:l}},{}),N2="Separator",Wm="horizontal",L2=["horizontal","vertical"],rA=N.forwardRef((n,s)=>{const{decorative:i,orientation:l=Wm,...u}=n,c=M2(l)?l:Wm,d=i?{role:"none"}:{"aria-orientation":c==="vertical"?c:void 0,role:"separator"};return _.jsx(F2.div,{"data-orientation":c,...d,...u,ref:s})});rA.displayName=N2;function M2(n){return L2.includes(n)}var iA=rA;const vo=N.forwardRef(({className:n,orientation:s="horizontal",decorative:i=!0,...l},u)=>_.jsx(iA,{ref:u,decorative:i,orientation:s,className:pt("shrink-0 bg-border",s==="horizontal"?"h-[1px] w-full":"h-full w-[1px]",n),...l}));vo.displayName=iA.displayName;const g0=[{name:"USA/Canada",freq:910.525,bw:62.5,sf:7,cr:5},{name:"Australia",freq:915.8,bw:250,sf:10,cr:5},{name:"Australia (narrow)",freq:916.575,bw:62.5,sf:7,cr:8},{name:"Australia SA, WA",freq:923.125,bw:62.5,sf:8,cr:8},{name:"Australia QLD",freq:923.125,bw:62.5,sf:8,cr:5},{name:"New Zealand",freq:917.375,bw:250,sf:11,cr:5},{name:"New Zealand (narrow)",freq:917.375,bw:62.5,sf:7,cr:5},{name:"EU/UK/Switzerland Long Range",freq:869.525,bw:250,sf:11,cr:5},{name:"EU/UK/Switzerland Medium Range",freq:869.525,bw:250,sf:10,cr:5},{name:"EU/UK/Switzerland Narrow",freq:869.618,bw:62.5,sf:8,cr:8},{name:"Czech Republic (Narrow)",freq:869.432,bw:62.5,sf:7,cr:5},{name:"EU 433MHz Long Range",freq:433.65,bw:250,sf:11,cr:5},{name:"Portugal 433MHz",freq:433.375,bw:62.5,sf:9,cr:6},{name:"Portugal 868MHz",freq:869.618,bw:62.5,sf:7,cr:6},{name:"Vietnam",freq:920.25,bw:250,sf:11,cr:5}];function I2({open:n,config:s,health:i,appSettings:l,onClose:u,onSave:c,onSaveAppSettings:h,onSetPrivateKey:d,onReboot:g,onAdvertise:m,onHealthRefresh:x,onRefreshAppSettings:v}){const[C,P]=N.useState("radio"),[M,k]=N.useState(""),[w,B]=N.useState(""),[b,E]=N.useState(""),[T,F]=N.useState(""),[I,j]=N.useState(""),[O,G]=N.useState(""),[U,K]=N.useState(""),[J,Y]=N.useState(""),[ie,ge]=N.useState(""),[$,se]=N.useState(""),[W,te]=N.useState(!1),[Z,D]=N. Line truncated
"""
Process incoming messages and optionally return a reply.
Args:
sender_name: Display name of sender (may be None)
sender_key: 64-char hex public key (empty for channel msgs)
message_text: The message content
is_dm: True for direct messages, False for channel
channel_key: 32-char hex key for channels, None for DMs
channel_name: Channel name with hash (e.g. "#bot"), None for DMs
sender_timestamp: Sender's timestamp (unix seconds, may be None)
path: Hex-encoded routing path (may be None)
Returns:
None for no reply, or a string to send as reply
"""
# Example: Only respond in #bot channel to "!pling" command
if channel_name == "#bot" and "!pling" in message_text.lower():
return "[BOT] Plong!"
return None`,[ot,qe]=N.useState(!1),[Ke,Qe]=N.useState(mt);N.useEffect(()=>{s&&(k(s.name),B(String(s.lat)),E(String(s.lon)),F(String(s.tx_power)),j(String(s.radio.freq)),G(String(s.radio.bw)),K(String(s.radio.sf)),Y(String(s.radio.cr)))},[s]),N.useEffect(()=>{l&&(se(String(l.max_radio_contacts)),Ee(l.auto_decrypt_dm_on_advert),at(String(l.advert_interval)),qe(l.bot_enabled),l.bot_code&&Qe(l.bot_code))},[l]),N.useEffect(()=>{n&&v()},[n,v]);const rt=N.useMemo(()=>{const Pe=parseFloat(I),_e=parseFloat(O),fe=parseInt(U,10),ve=parseInt(J,10);for(const we of g0)if(we.freq===Pe&&we.bw===_e&&we.sf===fe&&we.cr===ve)return we.name;return"custom"},[I,O,U,J]),He=Pe=>{if(Pe==="custom")return;const _e=g0.find(fe=>fe.name===Pe);_e&&(j(String(_e.freq)),G(String(_e.bw)),K(String(_e.sf)),Y(String(_e.cr)))},Et=()=>{if(!navigator.geolocation){At.error("Geolocation not supported",{description:"Your browser does not support geolocation"});return}ae(!0),navigator.geolocation.getCurrentPosition(Pe=>{B(Pe.coords.latitude.toFixed(6)),E(Pe.coords.longitude.toFixed(6)),ae(!1),At.success("Location updated")},Pe=>{ae(!1),At.error("Failed to get location",{description:Pe.message})},{enableHighAccuracy:!0,timeout:1e4})},zt=async()=>{Ae(""),te(!0);try{const Pe={lat:parseFloat(w),lon:parseFloat(b),tx_power:parseInt(T,10),radio:{freq:parseFloat(I),bw:parseFloat(O),sf:parseInt(U,10),cr:parseInt(J,10)}};await c(Pe),At.success("Radio config saved, rebooting..."),te(!1),D(!0),await g(),u()}catch(Pe){Ae(Pe instanceof Error?Pe.message:"Failed to save"),te(!1)}finally{D(!1)}},Qt=async()=>{Ae(""),te(!0);try{await c({name:M});const _e=parseInt(je,10);!isNaN(_e)&&_e!==(l==null?void 0:l.advert_interval)&&await h({advert_interval:_e}),At.success("Identity settings saved")}catch(Pe){Ae(Pe instanceof Error?Pe.message:"Failed to save")}finally{te(!1)}},Dt=async()=>{Ae(""),te(!0);try{const Pe=parseInt($,10);!isNaN(Pe)&&Pe!==(l==null?void 0:l.max_radio_contacts)&&await h({max_radio_contacts:Pe}),At.success("Serial settings saved")}catch(Pe){Ae(Pe instanceof Error?Pe.message:"Failed to save")}finally{te(!1)}},Gt=async()=>{if(!ie.trim()){Ae("Private key is required");return}Ae(""),te(!0);try{await d(ie.trim()),ge(""),At.success("Private key set, rebooting..."),te(!1),D(!0),await g(),u()}catch(Pe){Ae(Pe instanceof Error?Pe.message:"Failed to set private key"),te(!1)}finally{D(!1)}},Yt=async()=>{if(confirm("Are you sure you want to reboot the radio? The connection will drop temporarily.")){Ae(""),D(!0);try{await g(),u()}catch(Pe){Ae(Pe instanceof Error?Pe.message:"Failed to reboot radio")}finally{D(!1)}}},$t=async()=>{q(!0);try{await m()}finally{q(!1)}},Ht=async()=>{const Pe=parseInt(pe,10);if(isNaN(Pe)||Pe<1){At.error("Invalid retention days",{description:"Retention days must be at least 1"});return}Oe(!0);try{const _e=await ut.runMaintenance(Pe);At.success("Database cleanup complete",{description:`Deleted ${_e.packets_deleted} old packet${_e.packets_deleted===1?"":"s"}`}),await x()}catch(_e){console.error("Failed to run maintenance:",_e),At.error("Database cleanup failed",{description:_e instanceof Error?_e.message:"Unknown error"})}finally{Oe(!1)}},Rt=async()=>{te(!0),Ae("");try{await h({auto_decrypt_dm_on_advert:Xe}),At.success("Database settings saved")}catch(Pe){console.error("Failed to save database settings:",Pe),Ae(Pe instanceof Error?Pe.message:"Failed to save"),At.error("Failed to save settings")}finally{te(!1)}},Vt=async()=>{te(!0),Ae("");try{await h({bot_enabled:ot,bot_code:Ke}),At.success("Bot settings saved")}catch(Pe){console.error("Failed to save bot settings:",Pe),Ae(Pe instanceof Error?Pe.message:"Failed to save"),At.error("Failed to save settings")}finally{te(!1)}};return _.jsx(Q0,{open:n,onOpenChange:Pe=>!Pe&&u(),children:_.jsxs(md,{className:"sm:max-w-[50vw] sm:min-w-[500px] max-h-[90vh] overflow-y-auto",children:[_.jsxs(gd,{children:[_.jsx(xd,{children:"Radio & Settings"}),_.jsxs(vd,{className:"sr-only",children:[C==="radio"&&"Configure radio frequency, power, and location settings",C==="identity"&&"Manage radio name, public key, private key, and advertising settings",C==="serial"&&"View serial port connection and configure contact sync",C==="database"&&"View database statistics and clean up old packets",C==="advertise"&&"Send a flood advertisement to announce your presence",C==="bot"&&"Configure automatic message bot with Python code"]})]}),s?_.jsxs(J0,{value:C,onValueChange:Pe=>P(Pe),className:"w-full",children:[_.jsxs(yd,{className:"grid w-full grid-cols-6",children:[_.jsx(dr,{value:"radio",children:"Radio"}),_.jsx(dr,{value:"identity",children:"Identity"}),_.jsx(dr,{value:"serial",children:"Serial"}),_.jsx(dr,{value:"database",children:"Database"}),_.jsx(dr,{value:"advertise",children:"Advertise"}),_.jsx(dr,{value:"bot",children:"Bot"})]}),_.jsxs(fr,{value:"radio",className:"space-y-4 mt-4",children:[_.jsxs("div",{className:"space-y-2",children:[_.jsx(jt,{htmlFor:"preset",children:"Preset"}),_.jsxs("select",{id:"preset",value:rt,o Line truncated
(c) 2012 by Cédric Mesnil. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/return(function(l){var u=i,c=u.lib,h=c.WordArray,d=c.Hasher,g=u.algo,m=h.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),x=h.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),v=h.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),C=h.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),P=h.create([0,1518500249,1859775393,2400959708,2840853838]),M=h.create([1352829926,1548603684,1836072691,2053994217,0]),k=g.RIPEMD160=d.extend({_doReset:function(){this._hash=h.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(I,j){for(var O=0;O<16;O++){var G=j+O,U=I[G];I[G]=(U<<8|U>>>24)&16711935|(U<<24|U>>>8)&4278255360}var K=this._hash.words,J=P.words,Y=M.words,ie=m.words,ge=x.words,$=v.words,se=C.words,W,te,Z,D,H,q,Q,ae,ce,Ae;q=W=K[0],Q=te=K[1],ae=Z=K[2],ce=D=K[3],Ae=H=K[4];for(var pe,O=0;O<80;O+=1)pe=W+I[j+ie[O]]|0,O<16?pe+=w(te,Z,D)+J[0]:O<32?pe+=B(te,Z,D)+J[1]:O<48?pe+=b(te,Z,D)+J[2]:O<64?pe+=E(te,Z,D)+J[3]:pe+=T(te,Z,D)+J[4],pe=pe|0,pe=F(pe,$[O]),pe=pe+H|0,W=H,H=D,D=F(Z,10),Z=te,te=pe,pe=q+I[j+ge[O]]|0,O<16?pe+=T(Q,ae,ce)+Y[0]:O<32?pe+=E(Q,ae,ce)+Y[1]:O<48?pe+=b(Q,ae,ce)+Y[2]:O<64?pe+=B(Q,ae,ce)+Y[3]:pe+=w(Q,ae,ce)+Y[4],pe=pe|0,pe=F(pe,se[O]),pe=pe+Ae|0,q=Ae,Ae=ce,ce=F(ae,10),ae=Q,Q=pe;pe=K[1]+Z+ce|0,K[1]=K[2]+D+Ae|0,K[2]=K[3]+H+q|0,K[3]=K[4]+W+Q|0,K[4]=K[0]+te+ae|0,K[0]=pe},_doFinalize:function(){var I=this._data,j=I.words,O=this._nDataBytes*8,G=I.sigBytes*8;j[G>>>5]|=128<<24-G%32,j[(G+64>>>9<<4)+14]=(O<<8|O>>>24)&16711935|(O<<24|O>>>8)&4278255360,I.sigBytes=(j.length+1)*4,this._process();for(var U=this._hash,K=U.words,J=0;J<5;J++){var Y=K[J];K[J]=(Y<<8|Y>>>24)&16711935|(Y<<24|Y>>>8)&4278255360}return U},clone:function(){var I=d.clone.call(this);return I._hash=this._hash.clone(),I}});function w(I,j,O){return I^j^O}function B(I,j,O){return I&j|~I&O}function b(I,j,O){return(I|~j)^O}function E(I,j,O){return I&O|j&~O}function T(I,j,O){return I^(j|~O)}function F(I,j){return I<<j|I>>>32-j}u.RIPEMD160=d._createHelper(k),u.HmacRIPEMD160=d._createHmacHelper(k)})(),i.RIPEMD160})})(bc)),bc.exports}var Cc={exports:{}},aC=Cc.exports,ug;function bd(){return ug||(ug=1,(function(n,s){(function(i,l){n.exports=l(_t())})(aC,function(i){(function(){var l=i,u=l.lib,c=u.Base,h=l.enc,d=h.Utf8,g=l.algo;g.HMAC=c.extend({init:function(m,x){m=this._hasher=new m.init,typeof x=="string"&&(x=d.parse(x));var v=m.blockSize,C=v*4;x.sigBytes>C&&(x=m.finalize(x)),x.clamp();for(var P=this._oKey=x.clone(),M=this._iKey=x.clone(),k=P.words,w=M.words,B=0;B<v;B++)k[B]^=1549556828,w[B]^=909522486;P.sigBytes=M.sigBytes=C,this.reset()},reset:function(){var m=this._hasher;m.reset(),m.update(this._iKey)},update:function(m){return this._hasher.update(m),this},finalize:function(m){var x=this._hasher,v=x.finalize(m);x.reset();var C=x.finalize(this._oKey.clone().concat(v));return C}})})()})})(Cc)),Cc.exports}var Ec={exports:{}},lC=Ec.exports,cg;function uC(){return cg||(cg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),Tl(),bd())})(lC,function(i){return(function(){var l=i,u=l.lib,c=u.Base,h=u.WordArray,d=l.algo,g=d.SHA256,m=d.HMAC,x=d.PBKDF2=c.extend({cfg:c.extend({keySize:128/32,hasher:g,iterations:25e4}),init:function(v){this.cfg=this.cfg.extend(v)},compute:function(v,C){for(var P=this.cfg,M=m.create(P.hasher,v),k=h.create(),w=h.create([1]),B=k.words,b=w.words,E=P.keySize,T=P.iterations;B.length<E;){var F=M.update(C).finalize(w);M.reset();for(var I=F.words,j=I.length,O=F,G=1;G<T;G++){O=M.finalize(O),M.reset();for(var U=O.words,K=0;K<j;K++)I[K]^=U[K]}k.concat(F),b[0]++}return k.sigBytes=E*4,k}});l.PBKDF2=function(v,C,P){return x.create(P).compute(v,C)}})(),i.PBKDF2})})(Ec)),Ec.exports}var kc={exports:{}},cC=kc.exports,dg;function wo(){return dg||(dg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),oA(),bd())})(cC,function(i){return(function(){var l=i,u=l.lib,c=u.Base,h=u.WordArray,d=l.algo,g=d.MD5,m=d.EvpKDF=c.extend({cfg:c.extend({keySize:128/32,hasher:g,iterations:1}),init:function(x){this.cfg=this.cfg.extend(x)},compute:function(x,v){for(var C,P=this.cfg,M=P.hasher.create(),k=h.create(),w=k.words,B=P.keySize,b=P.iterations;w.length<B;){C&&M.update(C),C=M.update(x).finalize(v),M.reset();for(var E=1;E<b;E++)C=M.finalize(C),M.reset();k.concat(C)}return k.sigBytes=B*4,k}});l.EvpKDF=function(x,v,C){return m.create(C).compute(x,v)}})(),i.EvpKDF})})(kc)),kc.exports}var Sc={exports:{}},dC=Sc.exports,fg;function bLine truncated
* Counter block mode compatible with Dr Brian Gladman fileenc.c
* derived from CryptoJS.mode.CTR
* Jan Hruby jhruby.web@gmail.com
*/return i.mode.CTRGladman=(function(){var l=i.lib.BlockCipherMode.extend();function u(d){if((d>>24&255)===255){var g=d>>16&255,m=d>>8&255,x=d&255;g===255?(g=0,m===255?(m=0,x===255?x=0:++x):++m):++g,d=0,d+=g<<16,d+=m<<8,d+=x}else d+=1<<24;return d}function c(d){return(d[0]=u(d[0]))===0&&(d[1]=u(d[1])),d}var h=l.Encryptor=l.extend({processBlock:function(d,g){var m=this._cipher,x=m.blockSize,v=this._iv,C=this._counter;v&&(C=this._counter=v.slice(0),this._iv=void 0),c(C);var P=C.slice(0);m.encryptBlock(P,0);for(var M=0;M<x;M++)d[g+M]^=P[M]}});return l.Decryptor=h,l})(),i.mode.CTRGladman})})(Tc)),Tc.exports}var Dc={exports:{}},vC=Dc.exports,gg;function AC(){return gg||(gg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(vC,function(i){return i.mode.OFB=(function(){var l=i.lib.BlockCipherMode.extend(),u=l.Encryptor=l.extend({processBlock:function(c,h){var d=this._cipher,g=d.blockSize,m=this._iv,x=this._keystream;m&&(x=this._keystream=m.slice(0),this._iv=void 0),d.encryptBlock(x,0);for(var v=0;v<g;v++)c[h+v]^=x[v]}});return l.Decryptor=u,l})(),i.mode.OFB})})(Dc)),Dc.exports}var Rc={exports:{}},yC=Rc.exports,xg;function _C(){return xg||(xg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(yC,function(i){return i.mode.ECB=(function(){var l=i.lib.BlockCipherMode.extend();return l.Encryptor=l.extend({processBlock:function(u,c){this._cipher.encryptBlock(u,c)}}),l.Decryptor=l.extend({processBlock:function(u,c){this._cipher.decryptBlock(u,c)}}),l})(),i.mode.ECB})})(Rc)),Rc.exports}var Fc={exports:{}},wC=Fc.exports,vg;function bC(){return vg||(vg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(wC,function(i){return i.pad.AnsiX923={pad:function(l,u){var c=l.sigBytes,h=u*4,d=h-c%h,g=c+d-1;l.clamp(),l.words[g>>>2]|=d<<24-g%4*8,l.sigBytes+=d},unpad:function(l){var u=l.words[l.sigBytes-1>>>2]&255;l.sigBytes-=u}},i.pad.Ansix923})})(Fc)),Fc.exports}var Nc={exports:{}},CC=Nc.exports,Ag;function EC(){return Ag||(Ag=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(CC,function(i){return i.pad.Iso10126={pad:function(l,u){var c=u*4,h=c-l.sigBytes%c;l.concat(i.lib.WordArray.random(h-1)).concat(i.lib.WordArray.create([h<<24],1))},unpad:function(l){var u=l.words[l.sigBytes-1>>>2]&255;l.sigBytes-=u}},i.pad.Iso10126})})(Nc)),Nc.exports}var Lc={exports:{}},kC=Lc.exports,yg;function SC(){return yg||(yg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(kC,function(i){return i.pad.Iso97971={pad:function(l,u){l.concat(i.lib.WordArray.create([2147483648],1)),i.pad.ZeroPadding.pad(l,u)},unpad:function(l){i.pad.ZeroPadding.unpad(l),l.sigBytes--}},i.pad.Iso97971})})(Lc)),Lc.exports}var Mc={exports:{}},BC=Mc.exports,_g;function PC(){return _g||(_g=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(BC,function(i){return i.pad.ZeroPadding={pad:function(l,u){var c=u*4;l.clamp(),l.sigBytes+=c-(l.sigBytes%c||c)},unpad:function(l){for(var u=l.words,c=l.sigBytes-1,c=l.sigBytes-1;c>=0;c--)if(u[c>>>2]>>>24-c%4*8&255){l.sigBytes=c+1;break}}},i.pad.ZeroPadding})})(Mc)),Mc.exports}var Ic={exports:{}},TC=Ic.exports,wg;function DC(){return wg||(wg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(TC,function(i){return i.pad.NoPadding={pad:function(){},unpad:function(){}},i.pad.NoPadding})})(Ic)),Ic.exports}var Oc={exports:{}},RC=Oc.exports,bg;function FC(){return bg||(bg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),bn())})(RC,function(i){return(function(l){var u=i,c=u.lib,h=c.CipherParams,d=u.enc,g=d.Hex,m=u.format;m.Hex={stringify:function(x){return x.ciphertext.toString(g)},parse:function(x){var v=g.parse(x);return h.create({ciphertext:v})}}})(),i.format.Hex})})(Oc)),Oc.exports}var jc={exports:{}},NC=jc.exports,Cg;function LC(){return Cg||(Cg=1,(function(n,s){(function(i,l,u){n.exports=l(_t(),us(),cs(),wo(),bn())})(NC,function(i){return(function(){var l=i,u=l.lib,c=u.BlockCipher,h=l.algo,d=[],g=[],m=[],x=[],v=[],C=[],P=[],M=[],k=[],w=[];(function(){for(var E=[],T=0;T<256;T++)T<128?E[T]=T<<1:E[T]=T<<1^283;for(var F=0,I=0,T=0;T<256;T++){var j=I^I<<1^I<<2^I<<3^I<<4;j=j>>>8^j&255^99,d[F]=j,g[j]=F;var O=E[F],G=E[O],U=E[G],K=E[j]*257^j*16843008;m[F]=K<<24|K>>>8,x[F]=K<<16|K>>>16,v[F]=K<<8|K>>>24,C[F]=K;var K=U*16843009^G*65537^O*257^F*16843008;P[j]=K<<24|K>>>8,M[j]=K<<16|K>>>16,k[j]=K<<8|K>>>24,w[j]=K,F?(F=O^E[E[E[U^O]]],I^=E[E[I]]):F=I=1}})();var B=[0,1,2,4,8,16,32,64,128,27,54],b=h.AES=c.extend({_doReset:function(){var E;if(!(this._nRounds&&this._keyPriorReset===this._key)){for(var T=this._keyPriorReset=this._key,F=T.words,I=T.sigBytes/4,j=this._nRounds=I+6,O=(j+1)*4,G=this._keySchedule=[],U=0;U<O;U++)U<I?G[U]=F[U]:(E=G[U-1],U%I?I>6&&U%I==4&&(E=d[E>>>24]<<24|d[E>>>16&255]<<16|d[E>>>8&255]<<8|d[E&255]):(E=E<<8|E>>>24,E=d[E>>>24]<<24|d[E>>>16&255]<<16|d[E>>>8&255]<<8|d[E&255],E^=B[U/I|0]<<24),G[U]=G[U-I]^E);for(var K=this._invKeySchedule=[],J=0;J<O;J++){var U=O-J;if(J%4)var E=G[U];else var E=G[U-4];J<4||U<=4?K[J]=E:K[J]=P[d[E>>>24]]^M[d[E>>>16&255]]^k[d[E>>>8&255]]^w[d[E&255]]}}},encryptBlock:Line truncated
• Timestamp (4 bytes) - send time as unix timestamp
• Request Type (1 byte) - type of request (GetStats, GetTelemetryData, etc.)
• Request Data (remaining bytes) - additional request-specific data`,startByte:d+g,endByte:d+u.length-1,value:C});const P={type:n.PayloadType.Request,version:n.PayloadVersion.Version1,isValid:!0,timestamp:0,requestType:n.RequestType.GetStats,requestData:"",destinationHash:m,sourceHash:x,cipherMac:v,ciphertext:C};return c!=null&&c.includeSegments&&(P.segments=h),P}catch(h){return{type:n.PayloadType.Request,version:n.PayloadVersion.Version1,isValid:!1,errors:[h instanceof Error?h.message:"Failed to decode request payload"],timestamp:0,requestType:n.RequestType.GetStats,requestData:"",destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:""}}}}return ul.RequestPayloadDecoder=i,ul}var cl={},Gg;function xE(){if(Gg)return cl;Gg=1,Object.defineProperty(cl,"__esModule",{value:!0}),cl.ResponsePayloadDecoder=void 0;const n=pr(),s=Sn();class i{static decode(u,c){try{if(u.length<4){const M={type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!1,errors:["Response payload too short (minimum 4 bytes: dest + source + MAC)"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return c!=null&&c.includeSegments&&(M.segments=[{name:"Invalid Response Data",description:"Response payload too short (minimum 4 bytes required)",startByte:c.segmentOffset||0,endByte:(c.segmentOffset||0)+u.length-1,value:(0,s.bytesToHex)(u)}]),M}const h=[],d=(c==null?void 0:c.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(u[g]);c!=null&&c.includeSegments&&h.push({name:"Destination Hash",description:"First byte of destination node public key",startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.byteToHex)(u[g]);c!=null&&c.includeSegments&&h.push({name:"Source Hash",description:"First byte of source node public key",startByte:d+g,endByte:d+g,value:x}),g+=1;const v=(0,s.bytesToHex)(u.subarray(g,g+2));c!=null&&c.includeSegments&&h.push({name:"Cipher MAC",description:"MAC for encrypted data in next field",startByte:d+g,endByte:d+g+1,value:v}),g+=2;const C=(0,s.bytesToHex)(u.subarray(g));c!=null&&c.includeSegments&&u.length>g&&h.push({name:"Ciphertext",description:"Encrypted response data (tag + content)",startByte:d+g,endByte:d+u.length-1,value:C});const P={type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,sourceHash:x,cipherMac:v,ciphertext:C,ciphertextLength:u.length-4};return c!=null&&c.includeSegments&&(P.segments=h),P}catch(h){return{type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!1,errors:[h instanceof Error?h.message:"Failed to decode response payload"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0}}}}return cl.ResponsePayloadDecoder=i,cl}var dl={},$g;function vE(){if($g)return dl;$g=1,Object.defineProperty(dl,"__esModule",{value:!0}),dl.AnonRequestPayloadDecoder=void 0;const n=pr(),s=Sn();class i{static decode(u,c){try{if(u.length<35){const M={type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!1,errors:["AnonRequest payload too short (minimum 35 bytes: dest + public key + MAC)"],destinationHash:"",senderPublicKey:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return c!=null&&c.includeSegments&&(M.segments=[{name:"Invalid AnonRequest Data",description:"AnonRequest payload too short (minimum 35 bytes required: 1 for dest hash + 32 for public key + 2 for MAC)",startByte:c.segmentOffset||0,endByte:(c.segmentOffset||0)+u.length-1,value:(0,s.bytesToHex)(u)}]),M}const h=[],d=(c==null?void 0:c.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(u[0]);c!=null&&c.includeSegments&&h.push({name:"Destination Hash",description:`First byte of destination node public key: 0x${m}`,startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.bytesToHex)(u.subarray(1,33));c!=null&&c.includeSegments&&h.push({name:"Sender Public Key",description:"Ed25519 public key of the sender (32 bytes)",startByte:d+g,endByte:d+g+31,value:x}),g+=32;const v=(0,s.bytesToHex)(u.subarray(33,35));c!=null&&c.includeSegments&&h.push({name:"Cipher MAC",description:"MAC for encrypted data verification (2 bytes)",startByte:d+g,endByte:d+g+1,value:v}),g+=2;const C=(0,s.bytesToHex)(u.subarray(35));c!=null&&c.includeSegments&&u.length>35&&h.push({name:"Ciphertext",description:`Encrypted message data (${u.length-35} bytes). Contains encrypted plaintext with this structure:
• Timestamp (4 bytes) - send time as unix timestamp
• Sync Timestamp (4 bytes) - room server only, sender's "sync messages SINCE x" timestamp
• Password (remaining bytes) - password for repeater/room`,startByte:d+g,endByte:d+u.length-1,value:C});const P={type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,senderPublicKey:x,cipherMac:v,ciphertext:C,ciphertextLength:u.length-35};return c!=null&&c.includeSegments&&(P.segments=h),P}catch(h){return{type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!1,errors:[h instanceof Error?h.message:"Failed to decode AnonRequest payload"],destinationHash:"",senderPublicKey:"",cipherMac:"",ciphertext:"",ciphertextLength:0}}}}return dl.AnonRequestPayloadDecoder=i,dl}var fl={},Kg;function AE(){if(Kg)return fl;Kg=1,Object.defineProperty(fl,"__esModule",{value:!0}),fl.AckPayloadDecoder=void 0;const n=pr(),s=Sn();class i{static decode(u,c){try{if(u.length<4){const x={type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!1,errors:["Ack payload too short (minimum 4 bytes for checksum)"],checksum:""};return c!=null&&c.includeSegments&&(x.segments=[{name:"Invalid Ack Data",description:"Ack payload too short (minimum 4 bytes required for checksum)",startByte:c.segmentOffset||0,endByte:(c.segmentOffset||0)+u.length-1,value:(0,s.bytesToHex)(u)}]),x}const h=[],d=(c==null?void 0:c.segmentOffset)||0,g=(0,s.bytesToHex)(u.subarray(0,4));c!=null&&c.includeSegments&&h.push({name:"Checksum",description:`CRC checksum of message timestamp, text, and sender pubkey: 0x${g}`,startByte:d,endByte:d+3,value:g}),c!=null&&c.includeSegments&&u.length>4&&h.push({name:"Additional Data",description:"Extra data in Ack payload",startByte:d+4,endByte:d+u.length-1,value:(0,s.bytesToHex)(u.subarray(4))});const m={type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!0,checksum:g};return c!=null&&c.includeSegments&&(m.segments=h),m}catch(h){return{type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!1,errors:[h instanceof Error?h.message:"Failed to decode Ack payload"],checksum:""}}}}return fl.AckPayloadDecoder=i,fl}var hl={},Qg;function yE(){if(Qg)return hl;Qg=1,Object.defineProperty(hl,"__esModule",{value:!0}),hl.PathPayloadDecoder=void 0;const n=pr(),s=Sn();class i{static decode(u){try{if(u.length<2)return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:["Path payload too short (minimum 2 bytes: path length + extra type)"],pathLength:0,pathHashes:[],extraType:0,extraData:""};const c=u[0];if(u.length<1+c+1)return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:[`Path payload too short (need ${1+c+1} bytes for path length + path + extra type)`],pathLength:c,pathHashes:[],extraType:0,extraData:""};const h=[];for(let m=0;m<c;m++)h.push((0,s.byteToHex)(u[1+m]));const d=u[1+c];let g="";return u.length>1+c+1&&(g=(0,s.bytesToHex)(u.subarray(1+c+1))),{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!0,pathLength:c,pathHashes:h,extraType:d,extraData:g}}catch(c){return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:[c instanceof Error?c.message:"Failed to decode Path payload"],pathLength:0,pathHashes:[],extraType:0,extraData:""}}}}return hl.PathPayloadDecoder=i,hl}var pl={},Yg;function _E(){if(Yg)return pl;Yg=1,Object.defineProperty(pl,"__esModule",{value:!0}),pl.TextMessagePayloadDecoder=void 0;const n=pr(),s=Sn();class i{static decode(u,c){try{if(u.length<4){const M={type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,isValid:!1,errors:["TextMessage payload too short (minimum 4 bytes: dest + source + MAC)"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return c!=null&&c.includeSegments&&(M.segments=[{name:"Invalid TextMessage Data",description:"TextMessage payload too short (minimum 4 bytes required)",startByte:c.segmentOffset||0,endByte:(c.segmentOffset||0)+u.length-1,value:(0,s.bytesToHex)(u)}]),M}const h=[],d=(c==null?void 0:c.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(u[g]);c!=null&&c.includeSegments&&h.push({name:"Destination Hash",description:"First byte of destination node public key",startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.byteToHex)(u[g]);c!=null&&c.includeSegments&&h.push({name:"Source Hash",description:"First byte of source node public key",startByte:d+g,endByte:d+g,value:x}),g+=1;const v=(0,s.bytesToHex)(u.subarray(g,g+2));c!=null&&c.includeSegments&&h.push({name:"Cipher MAC",description:"MAC for encrypted data in next field",startByte:d+g,endByte:d+g+1,value:v}),g+=2;const C=(0,s.bytesToHex)(u.subarray(g));c!=null&&c.includeSegments&&u.length>g&&h.push({name:"Ciphertext",description:"Encrypted message data (timestamp + message text)",startByte:d+g,endByte:d+u.length-1,value:C});const P={type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,sourceHash:x,cipherMac:v,ciphertext:C,ciphertextLength:u.length-4};return c!=null&&c.includeSegments&&(P.segments=h),P}catch(h){return{type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,i Line truncated
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
*/var IE=xl.exports,ix;function OE(){return ix||(ix=1,(function(n,s){(function(i,l){l(s)})(IE,(function(i){var l="1.9.4";function u(t){var o,f,A,R;for(f=1,A=arguments.length;f<A;f++){R=arguments[f];for(o in R)t[o]=R[o]}return t}var c=Object.create||(function(){function t(){}return function(o){return t.prototype=o,new t}})();function h(t,o){var f=Array.prototype.slice;if(t.bind)return t.bind.apply(t,f.call(arguments,1));var A=f.call(arguments,2);return function(){return t.apply(o,A.length?A.concat(f.call(arguments)):arguments)}}var d=0;function g(t){return"_leaflet_id"in t||(t._leaflet_id=++d),t._leaflet_id}function m(t,o,f){var A,R,V,ee;return ee=function(){A=!1,R&&(V.apply(f,R),R=!1)},V=function(){A?R=arguments:(t.apply(f,arguments),setTimeout(ee,o),A=!0)},V}function x(t,o,f){var A=o[1],R=o[0],V=A-R;return t===A&&f?t:((t-R)%V+V)%V+R}function v(){return!1}function C(t,o){if(o===!1)return t;var f=Math.pow(10,o===void 0?6:o);return Math.round(t*f)/f}function P(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function M(t){return P(t).split(/\s+/)}function k(t,o){Object.prototype.hasOwnProperty.call(t,"options")||(t.options=t.options?c(t.options):{});for(var f in o)t.options[f]=o[f];return t.options}function w(t,o,f){var A=[];for(var R in t)A.push(encodeURIComponent(f?R.toUpperCase():R)+"="+encodeURIComponent(t[R]));return(!o||o.indexOf("?")===-1?"?":"&")+A.join("&")}var B=/\{ *([\w_ -]+) *\}/g;function b(t,o){return t.replace(B,function(f,A){var R=o[A];if(R===void 0)throw new Error("No value provided for variable "+f);return typeof R=="function"&&(R=R(o)),R})}var E=Array.isArray||function(t){return Object.prototype.toString.call(t)==="[object Array]"};function T(t,o){for(var f=0;f<t.length;f++)if(t[f]===o)return f;return-1}var F="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function I(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var j=0;function O(t){var o=+new Date,f=Math.max(0,16-(o-j));return j=o+f,window.setTimeout(t,f)}var G=window.requestAnimationFrame||I("RequestAnimationFrame")||O,U=window.cancelAnimationFrame||I("CancelAnimationFrame")||I("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function K(t,o,f){if(f&&G===O)t.call(o);else return G.call(window,h(t,o))}function J(t){t&&U.call(window,t)}var Y={__proto__:null,extend:u,create:c,bind:h,get lastId(){return d},stamp:g,throttle:m,wrapNum:x,falseFn:v,formatNum:C,trim:P,splitWords:M,setOptions:k,getParamString:w,template:b,isArray:E,indexOf:T,emptyImageUrl:F,requestFn:G,cancelFn:U,requestAnimFrame:K,cancelAnimFrame:J};function ie(){}ie.extend=function(t){var o=function(){k(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},f=o.__super__=this.prototype,A=c(f);A.constructor=o,o.prototype=A;for(var R in this)Object.prototype.hasOwnProperty.call(this,R)&&R!=="prototype"&&R!=="__super__"&&(o[R]=this[R]);return t.statics&&u(o,t.statics),t.includes&&(ge(t.includes),u.apply(null,[A].concat(t.includes))),u(A,t),delete A.statics,delete A.includes,A.options&&(A.options=f.options?c(f.options):{},u(A.options,t.options)),A._initHooks=[],A.callInitHooks=function(){if(!this._initHooksCalled){f.callInitHooks&&f.callInitHooks.call(this),this._initHooksCalled=!0;for(var V=0,ee=A._initHooks.length;V<ee;V++)A._initHooks[V].call(this)}},o},ie.include=function(t){var o=this.prototype.options;return u(this.prototype,t),t.options&&(this.prototype.options=o,this.mergeOptions(t.options)),this},ie.mergeOptions=function(t){return u(this.prototype.options,t),this},ie.addInitHook=function(t){var o=Array.prototype.slice.call(arguments,1),f=typeof t=="function"?t:function(){this[t].apply(this,o)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(f),this};function ge(t){if(!(typeof L>"u"||!L||!L.Mixin)){t=E(t)?t:[t];for(var o=0;o<t.length;o++)t[o]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",new Error().stack)}}var $={on:function(t,o,f){if(typeof t=="object")for(var A in t)this._on(A,t[A],o);else{t=M(t);for(var R=0,V=t.length;R<V;R++)this._on(t[R],o,f)}return this},off:function(t,o,f){if(!arguments.length)delete this._events;else if(typeof t=="object")for(var A in t)this._off(A,t[A],o);else{t=M(t);for(var R=arguments.length===1,V=0,ee=t.length;V<ee;V++)R?this._off(t[V]):this._off(t[V],o,f)}return this},_on:function(t,o,f,A){if(typeof o!="function"){console.warn("wrong listener type: "+typeof o);return}if(this._listens(t,o,f)===!1){f===this&&(f=void 0);var R={fn:o,ctx:f};A&&(R.once=!0),this._events=this._events||{},this._events[t]=this._events[t]||[],this._events[t].push(R)}},_off:function(t,o,f){var A,R,V;if(this._events&&(A=this._events[t],!!A)){if(arguments.length===1){if(this._firingCount)for(R=0,V=A.length;R<V;R++)A[R].fn=v;delete this._events[t];return}if(typeof o!="function"){console.warn("wrong listener type: "+typeof o);return}var ee=Line truncated
// SHA256 round constants
const K: array<u32, 64> = array<u32, 64>(
0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u,
0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u, 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u,
0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u, 0x06ca6351u, 0x14292967u,
0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u, 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u,
0xa2bfe8a1u, 0xa81a664bu, 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, 0x682e6ff3u,
0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u
);
// Character lookup table (a-z = 0-25, 0-9 = 26-35, dash = 36)
const CHARS: array<u32, 37> = array<u32, 37>(
0x61u, 0x62u, 0x63u, 0x64u, 0x65u, 0x66u, 0x67u, 0x68u, 0x69u, 0x6au, // a-j
0x6bu, 0x6cu, 0x6du, 0x6eu, 0x6fu, 0x70u, 0x71u, 0x72u, 0x73u, 0x74u, // k-t
0x75u, 0x76u, 0x77u, 0x78u, 0x79u, 0x7au, // u-z
0x30u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u, 0x39u, // 0-9
0x2du // dash
);
struct Params {
target_channel_hash: u32,
batch_offset: u32,
name_length: u32,
batch_size: u32,
target_mac: u32, // First 2 bytes of target MAC (in high 16 bits)
ciphertext_words: u32, // Number of 32-bit words in ciphertext
ciphertext_len_bits: u32, // Length of ciphertext in bits
verify_mac: u32, // 1 to verify MAC, 0 to skip
}
@group(0) @binding(0) var<uniform> params: Params;
@group(0) @binding(1) var<storage, read_write> match_count: atomic<u32>;
@group(0) @binding(2) var<storage, read_write> match_indices: array<u32>;
@group(0) @binding(3) var<storage, read> ciphertext: array<u32>; // Ciphertext data
fn rotr(x: u32, n: u32) -> u32 {
return (x >> n) | (x << (32u - n));
}
fn ch(x: u32, y: u32, z: u32) -> u32 {
return (x & y) ^ (~x & z);
}
fn maj(x: u32, y: u32, z: u32) -> u32 {
return (x & y) ^ (x & z) ^ (y & z);
}
fn sigma0(x: u32) -> u32 {
return rotr(x, 2u) ^ rotr(x, 13u) ^ rotr(x, 22u);
}
fn sigma1(x: u32) -> u32 {
return rotr(x, 6u) ^ rotr(x, 11u) ^ rotr(x, 25u);
}
fn gamma0(x: u32) -> u32 {
return rotr(x, 7u) ^ rotr(x, 18u) ^ (x >> 3u);
}
fn gamma1(x: u32) -> u32 {
return rotr(x, 17u) ^ rotr(x, 19u) ^ (x >> 10u);
}
// Convert index to room name bytes, returns the hash as a u32 for the first byte check
fn index_to_room_name(idx: u32, length: u32, msg: ptr<function, array<u32, 16>>) -> bool {
// Message starts with '#' (0x23)
var byte_pos = 0u;
var word_idx = 0u;
var current_word = 0x23000000u; // '#' in big-endian position 0
byte_pos = 1u;
var remaining = idx;
var prev_was_dash = false;
// Generate room name from index
for (var i = 0u; i < length; i++) {
let char_count = select(37u, 36u, i == 0u || i == length - 1u); // no dash at start/end
var char_idx = remaining % char_count;
remaining = remaining / char_count;
// Check for consecutive dashes (invalid)
let is_dash = char_idx == 36u && i > 0u && i < length - 1u;
if (is_dash && prev_was_dash) {
return false; // Invalid: consecutive dashes
}
prev_was_dash = is_dash;
// Map char index to actual character
let c = CHARS[char_idx];
// Pack byte into current word (big-endian)
let shift = (3u - byte_pos % 4u) * 8u;
if (byte_pos % 4u == 0u && byte_pos > 0u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
current_word = 0u;
}
current_word = current_word | (c << shift);
byte_pos = byte_pos + 1u;
}
// Add padding: 0x80 followed by zeros, then length in bits
let msg_len_bits = (length + 1u) * 8u; // +1 for '#'
// Add 0x80 padding byte
let shift = (3u - byte_pos % 4u) * 8u;
if (byte_pos % 4u == 0u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
current_word = 0x80000000u;
} else {
current_word = current_word | (0x80u << shift);
}
byte_pos = byte_pos + 1u;
// Store current word
if (byte_pos % 4u == 0u || word_idx < 14u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
}
// Zero-fill until word 14
for (var i = word_idx; i < 14u; i++) {
(*msg)[i] = 0u;
}
// Length in bits (64-bit, but we only use lower 32 bits for short messages)
(*msg)[14u] = 0u;
(*msg)[15u] = msg_len_bits;
return true;
}
fn sha256_block(msg: ptr<function, array<u32, 16>>) -> array<u32, 8> {
// Initialize hash values
var h: array<u32, 8> = array<u32, 8>(
0x6a09e667u, 0xbb67ae85u, 0x3c6ef372u, 0xa54ff53au,
0x510e527fu, 0x9b05688cu, 0x1f83d9abu, 0x5be0cd19u
);
// Message schedule
var w: array<u32, 64>;
for (var i = 0u; i < 16u; i++) {
w[i] = (*msg)[i];
}
for (var i = 16u; i < 64u; i++) {
w[i] = gamma1(w[i-2u]) + w[i-7u] + gamma0(w[i-15u]) + w[i-16u];
}
// Compression
var a = h[0]; var b = h[1]; var c = h[2]; var d = h[3];
var e = h[4]; var f = h[5]; var g = h[6]; var hh = h[7];
for (var i = 0u; i < 64u; i++) {
let t1 = hh + sigma1(e) + ch(e, f, g) + K[i] + w[i];
let t2 = sigma0(a) + maj(a, b, c);
hh = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
h[0] = h[0] + a; h[1] = h[1] + b; h[2] = h[2] + c; h[3] = h[3] + d;
h[4] = h[4] + e; h[5] = h[5] + f; h[6] = h[6] + g; h[7] = h[7] + hh;
return h;
}
// Compute SHA256 of the key (16 bytes) to get channel hash
fn sha256_key(key: array<u32, 4>) -> u32 {
var msg: array<u32, 16>;
// Key bytes (16 bytes = 4 words)
msg[0] = key[0];
msg[1] = key[1];
msg[2] = key[2];
msg[3] = key[3];
// Padding: 0x80 followed by zeros
msg[4] = 0x80000000u;
for (var i = 5u; i < 14u; i++) {
msg[i] = 0u;
}
// Length: 128 bits
msg[14] = 0u;
msg[15] = 128u;
let hash = sha256_block(&msg);
// Return first byte of hash (big-endian)
return hash[0] >> 24u;
}
// HMAC-SHA256 for MAC verification
// Key is 16 bytes (4 words), padded to 32 bytes with zeros for MeshCore
// Returns first 2 bytes of HMAC (as u32 in high 16 bits)
fn hmac_sha256_mac(key: array<u32, 4>, ciphertext_len: u32) -> u32 {
// HMAC: H((K' ^ opad) || H((K' ^ ipad) || message))
// K' is 64 bytes (32 bytes key + 32 bytes zero padding for MeshCore, then padded to 64)
// ipad = 0x36 repeated, opad = 0x5c repeated
// Build padded key (64 bytes = 16 words)
// MeshCore uses 32-byte secret: 16-byte key + 16 zero bytes
var k_pad: array<u32, 16>;
k_pad[0] = key[0];
k_pad[1] = key[1];
k_pad[2] = key[2];
k_pad[3] = key[3];
for (var i = 4u; i < 16u; i++) {
k_pad[i] = 0u;
}
// Inner hash: SHA256((K' ^ ipad) || message)
// First block: K' ^ ipad (64 bytes)
var inner_block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
inner_block[i] = k_pad[i] ^ 0x36363636u;
}
// Initialize hash state with first block
var h: array<u32, 8> = sha256_block(&inner_block);
// Process ciphertext blocks (continuing from h state)
let ciphertext_words = params.ciphertext_words;
var word_idx = 0u;
// Process full 64-byte blocks of ciphertext
while (word_idx + 16u <= ciphertext_words) {
var block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
block[i] = ciphertext[word_idx + i];
}
h = sha256_block_continue(&block, h);
word_idx = word_idx + 16u;
}
// Final block with remaining ciphertext + padding
var final_block: array<u32, 16>;
var remaining = ciphertext_words - word_idx;
for (var i = 0u; i < 16u; i++) {
if (i < remaining) {
final_block[i] = ciphertext[word_idx + i];
} else if (i == remaining) {
// Add 0x80 padding
final_block[i] = 0x80000000u;
} else {
final_block[i] = 0u;
}
}
// Add length (64 bytes of ipad + ciphertext length)
let total_bits = 512u + params.ciphertext_len_bits;
if (remaining < 14u) {
final_block[14] = 0u;
final_block[15] = total_bits;
h = sha256_block_continue(&final_block, h);
} else {
// Need extra block for length
h = sha256_block_continue(&final_block, h);
var len_block: array<u32, 16>;
for (var i = 0u; i < 14u; i++) {
len_block[i] = 0u;
}
len_block[14] = 0u;
len_block[15] = total_bits;
h = sha256_block_continue(&len_block, h);
}
let inner_hash = h;
// Outer hash: SHA256((K' ^ opad) || inner_hash)
var outer_block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
outer_block[i] = k_pad[i] ^ 0x5c5c5c5cu;
}
h = sha256_block(&outer_block);
// Second block: inner_hash (32 bytes) + padding
var hash_block: array<u32, 16>;
for (var i = 0u; i < 8u; i++) {
hash_block[i] = inner_hash[i];
}
hash_block[8] = 0x80000000u;
for (var i = 9u; i < 14u; i++) {
hash_block[i] = 0u;
}
hash_block[14] = 0u;
hash_block[15] = 512u + 256u; // 64 bytes opad + 32 bytes inner hash
h = sha256_block_continue(&hash_block, h);
// Return first 2 bytes (high 16 bits of first word)
return h[0] & 0xFFFF0000u;
}
// SHA256 block computation continuing from existing state
fn sha256_block_continue(msg: ptr<function, array<u32, 16>>, h_in: array<u32, 8>) -> array<u32, 8> {
var h = h_in;
// Message schedule
var w: array<u32, 64>;
for (var i = 0u; i < 16u; i++) {
w[i] = (*msg)[i];
}
for (var i = 16u; i < 64u; i++) {
w[i] = gamma1(w[i-2u]) + w[i-7u] + gamma0(w[i-15u]) + w[i-16u];
}
// Compression
var a = h[0]; var b = h[1]; var c = h[2]; var d = h[3];
var e = h[4]; var f = h[5]; var g = h[6]; var hh = h[7];
for (var i = 0u; i < 64u; i++) {
let t1 = hh + sigma1(e) + ch(e, f, g) + K[i] + w[i];
let t2 = sigma0(a) + maj(a, b, c);
hh = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
h[0] = h[0] + a; h[1] = h[1] + b; h[2] = h[2] + c; h[3] = h[3] + d;
h[4] = h[4] + e; h[5] = h[5] + f; h[6] = h[6] + g; h[7] = h[7] + hh;
return h;
}
// Process a single candidate and record match if found
fn process_candidate(name_idx: u32) {
// Generate message for this room name
var msg: array<u32, 16>;
let valid = index_to_room_name(name_idx, params.name_length, &msg);
if (!valid) {
return;
}
// Compute SHA256("#roomname") - this gives us the key
let key_hash = sha256_block(&msg);
// Take first 16 bytes (4 words) as the key
var key: array<u32, 4>;
key[0] = key_hash[0];
key[1] = key_hash[1];
key[2] = key_hash[2];
key[3] = key_hash[3];
// Compute SHA256(key) to get channel hash
let channel_hash = sha256_key(key);
// Check if channel hash matches target
if (channel_hash != params.target_channel_hash) {
return;
}
// Channel hash matches - verify MAC if enabled
if (params.verify_mac == 1u) {
let computed_mac = hmac_sha256_mac(key, params.ciphertext_len_bits);
if (computed_mac != params.target_mac) {
return;
}
}
// Found a match - record the index
let match_idx = atomicAdd(&match_count, 1u);
if (match_idx < 1024u) { // Limit stored matches
match_indices[match_idx] = name_idx;
}
}
// Each thread processes 32 candidates to amortize thread overhead
const CANDIDATES_PER_THREAD: u32 = 32u;
@compute @workgroup_size(256)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let base_idx = global_id.x * CANDIDATES_PER_THREAD;
for (var i = 0u; i < CANDIDATES_PER_THREAD; i++) {
let idx = base_idx + i;
if (idx >= params.batch_size) {
return;
}
let name_idx = params.batch_offset + idx;
process_candidate(name_idx);
}
}
`}async init(){if(!navigator.gpu)return console.warn("WebGPU not supported"),!1;try{const s=await navigator.gpu.requestAdapter();if(!s)return console.warn("No GPU adapter found"),!1;this.device=await s.requestDevice(),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),this.paramsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.matchCountBuffer=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST}),this.matchIndicesBuffer=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});for(let u=0;u<2;u++)this.matchCountReadBuffers[u]=this.device.createBuffer({size:4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),this.matchIndicesReadBuffers[u]=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST});const i=this.device.createShaderModule({code:this.shaderCode}),l=this.device.createPipelineLayout({bindGroupLayouts:[this.bindGroupLayout]});return this.pipeline=this.device.createComputePipeline({layout:l,compute:{module:i,entryPoint:"main"}}),!0}catch(s){return console.error("WebGPU initialization failed:",s),!1}}isAvailable(){return this.device!==null&&this.pipeline!==null}indexToRoomName(s,i){return ns(i,s)}countNamesForLength(s){return yl(s)}async runBatch(s,i,l,u,c,h){if(!this.device||!this.pipeline||!this.bindGroupLayout||!this.paramsBuffer||!this.matchCountBuffer||!this.matchIndicesBuffer||!this.matchCountReadBuffers[0]||!this.matchCountReadBuffers[1]||!this.matchIndicesReadBuffers[0]||!this.matchIndicesReadBuffers[1])throw new Error("GPU not initialized");const d=this.currentReadBufferIndex;this.currentReadBufferIndex=1-this.currentReadBufferIndex;const g=this.matchCountReadBuffers[d],m=this.matchIndicesReadBuffers[d],x=c&&h?1:0;let v,C=0,P=0;if(x){const F=new Uint8Array(c.length/2);for(let U=0;U<F.length;U++)F[U]=parseInt(c.substr(U*2,2),16);C=F.length*8;const I=Math.ceil(F.length/4)*4,j=new Uint8Array(I);j.set(F),v=new Uint32Array(I/4);for(let U=0;U<v.length;U++)v[U]=j[U*4]<<24|j[U*4+1]<<16|j[U*4+2]<<8|j[U*4+3];const O=parseInt(h.substr(0,2),16),G=parseInt(h.substr(2,2),16);P=O<<24|G<<16}else v=new Uint32Array([0]);const M=Math.max(v.length*4,4);(!this.ciphertextBuffer||this.ciphertextBufferSize<M)&&(this.ciphertextBuffer&&this.ciphertextBuffer.destroy(),this.ciphertextBuffer=this.device.createBuffer({size:M,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.ciphertextBufferSize=M,this.bindGroupDirty=!0);const k=new Uint32Array([s,l,i,u,P,v.length,C,x]);this.device.queue.writeBuffer(this.paramsBuffer,0,k),this.device.queue.writeBuffer(this.ciphertextBuffer,0,v),this.device.queue.writeBuffer(this.matchCountBuffer,0,Pd.ZERO_DATA),(this.bindGroupDirty||!this.bindGroup)&&(this.bindGroup=this.device.createBindGroup({layout:this.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.paramsBuffer}},{binding:1,resource:{buffer:this.matchCountBuffer}},{binding:2,resource:{buffer:this.matchIndicesBuffer}},{binding:3,resource:{buffer:this.ciphertextBuffer}}]}),this.bindGroupDirty=!1);const w=this.device.createCommandEncoder(),B=w.beginComputePass();B.setPipeline(this.pipeline),B.setBindGroup(0,this.bindGroup),B.dispatchWorkgroups(Math.ceil(u/(256*32))),B.end(),w.copyBufferToBuffer(this.matchCountBuffer,0,g,0,4),w.copyBufferToBuffer(this.matchIndicesBuffer,0,m,0,1024*4),this.device.queue.submit([w.finish()]),await g.mapAsync(GPUMapMode.READ);const E=new Uint32Array(g.getMappedRange())[0];g.unmap();const T=[];if(E>0){await m.mapAsync(GPUMapMode.READ);const F=new Uint32Array(m.getMappedRange());for(let I=0;I<Math.min(E,1024);I++)T.push(F[I]);m.unmap()}return T}destroy(){var s,i,l,u,c,h,d,g;(s=this.paramsBuffer)==null||s.destroy(),(i=this.matchCountBuffer)==null||i.destroy(),(l=this.matchIndicesBuffer)==null||l.destroy(),(u=this.ciphertextBuffer)==null||u.destroy(),(c=this.matchCountReadBuffers[0])==null||c.destroy(),(h=this.matchCountReadBuffers[1])==null||h.destroy(),(d=this.matchIndicesReadBuffers[0])==null||d.destroy(),(g=this.matchIndicesReadBuffers[1])==null||g.destroy(),this.paramsBuffer=null,this.matchCountBuffer=null,this.matchIndicesBuffer=null,this.ciphertextBuffer=null,this.ciphertextBufferSize=0,this.matchCountReadBuffers=[null,null],this.matchIndicesReadBuffers=[null,null],this.currentReadBufferIndex=0,this.bindGroup=null,this.bindGroupDirty=!0,this.device&&(this.device.destroy(),this.device=null),this.pipeline=null,this.bindGroupLayout=null}}Pd.ZERO_DATA=new Uint32Array([0]);function xS(){return typeof navigator<"u"&&"gpu"in navigator}class Ax{runBatch(s,i,l,u,c,h){const d=[],g=s.toString(16).padStart(2,"0") Line truncated
`).map(c=>c.trim().toLowerCase()).filter(c=>c.length>0);this.wordlist=u.filter(yx)}setWordlist(s){this.wordlist=s.map(i=>i.trim().toLowerCase()).filter(yx)}abort(){this.abortFlag=!0}isGpuAvailable(){return xS()}async decodePacket(s){var l;const i=s.trim().replace(/\s+/g,"").replace(/^0x/i,"");if(!i||!/^[0-9a-fA-F]+$/.test(i))return null;try{const c=(l=(await bt.MeshCorePacketDecoder.decodeWithVerification(i,{})).payload)==null?void 0:l.decoded;return!(c!=null&&c.channelHash)||!(c!=null&&c.ciphertext)||!(c!=null&&c.cipherMac)?null:{channelHash:c.channelHash,ciphertext:c.ciphertext,cipherMac:c.cipherMac,isGroupText:!0}}catch{return null}}async crack(s,i,l){this.abortFlag=!1,this.useTimestampFilter=(i==null?void 0:i.useTimestampFilter)??!0,this.useUtf8Filter=(i==null?void 0:i.useUtf8Filter)??!0,this.useSenderFilter=(i==null?void 0:i.useSenderFilter)??!0,this.validSeconds=(i==null?void 0:i.validSeconds)??I0,this.useCpu=(i==null?void 0:i.forceCpu)??!1;const u=(i==null?void 0:i.maxLength)??8,c=(i==null?void 0:i.startingLength)??1,h=(i==null?void 0:i.useDictionary)??!0,d=(i==null?void 0:i.startFromType)??"bruteforce",g=s.toLowerCase(),m=await this.decodePacket(g);if(!m)return{found:!1,error:"Invalid packet or not a GroupText packet"};const{channelHash:x,ciphertext:v,cipherMac:C}=m,P=parseInt(x,16);this.useCpu?this.cpuInstance||(this.cpuInstance=new Ax):this.gpuInstance||(this.gpuInstance=new Pd,await this.gpuInstance.init()||(this.useCpu=!0,this.cpuInstance=new Ax));const M=performance.now();let k=0,w=performance.now(),B=c,b=0,E=0,T=!1;if(i!=null&&i.startFrom){const Y=i.startFrom.toLowerCase();if(d==="dictionary"){const ie=this.wordlist.indexOf(Y);ie>=0&&(E=ie+1)}else{T=!0;const ie=pS(Y);ie&&(B=Math.max(c,ie.length),b=ie.index+1,b>=yl(B)&&(B++,b=0))}}let F=0;h&&!T&&this.wordlist.length>0&&(F+=this.wordlist.length-E);for(let Y=B;Y<=u;Y++)F+=yl(Y);F-=b;const I=(Y,ie,ge)=>{if(!l)return;const se=(performance.now()-M)/1e3,W=se>0?Math.round(k/se):0,te=F-k,Z=W>0?te/W:0;l({checked:k,total:F,percent:F>0?Math.min(100,k/F*100):0,rateKeysPerSec:W,etaSeconds:Z,elapsedSeconds:se,currentLength:ie,currentPosition:ge,phase:Y})},j=Y=>{if(!jA(v,C,Y))return{valid:!1};const ie=bt.ChannelCrypto.decryptGroupTextMessage(v,C,Y);return!ie.success||!ie.data?{valid:!1}:this.useTimestampFilter&&!mS(ie.data.timestamp,this.validSeconds)?{valid:!1}:this.useUtf8Filter&&!gS(ie.data.message)?{valid:!1}:this.useSenderFilter&&!ie.data.sender?{valid:!1}:{valid:!0,message:ie.data.sender?`${ie.data.sender}: ${ie.data.message}`:ie.data.message}};if(!T&&E===0&&B===c&&b===0){I("public-key",0,M0);const Y=j0(Kc);if(x===Y){const ie=j(Kc);if(ie.valid)return{found:!0,roomName:M0,key:Kc,decryptedMessage:ie.message}}}if(h&&!T&&this.wordlist.length>0)for(let Y=E;Y<this.wordlist.length;Y++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:this.wordlist[Y],resumeType:"dictionary"};const ie=this.wordlist[Y],ge=O0("#"+ie),$=j0(ge);if(parseInt($,16)===P){const W=j(ge);if(W.valid)return{found:!0,roomName:ie,key:ge,decryptedMessage:W.message,resumeFrom:ie,resumeType:"dictionary"}}k++;const se=performance.now();se-w>=200&&(I("wordlist",ie.length,ie),w=se,await new Promise(W=>setTimeout(W,0)))}const O=this.useCpu?1024:32768,G=(i==null?void 0:i.gpuDispatchMs)??1e3;let U=O,K=!1;for(let Y=B;Y<=u;Y++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ns(Y,0)||void 0,resumeType:"bruteforce"};const ie=yl(Y);let ge=Y===B?b:0;for(;ge<ie;){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:ns(Y,ge)||void 0,resumeType:"bruteforce"};const $=Math.min(U,ie-ge),se=performance.now();let W;this.useCpu?W=this.cpuInstance.runBatch(P,Y,ge,$,v,C):W=await this.gpuInstance.runBatch(P,Y,ge,$,v,C);const te=performance.now()-se;if(k+=$,!this.useCpu&&!K&&$>=O&&te>0){const D=G/te,H=Math.round($*D),q=Math.pow(2,Math.round(Math.log2(Math.max(O,H))));U=Math.max(O,q),K=!0}for(const D of W){const H=ns(Y,D);if(!H)continue;const q=O0("#"+H),Q=j(q);if(Q.valid)return{found:!0,roomName:H,key:q,decryptedMessage:Q.message,resumeFrom:H,resumeType:"bruteforce"}}ge+=$;const Z=performance.now();if(Z-w>=200){const D=ns(Y,Math.min(ge,ie-1))||"";I("bruteforce",Y,D),w=Z,await new Promise(H=>setTimeout(H,0))}}}return{found:!1,resumeFrom:ns(u,yl(u)-1)||void 0,resumeType:"bruteforce"}}destroy(){this.gpuInstance&&(this.gpuInstance.destroy(),this.gpuInstance=null),this.cpuInstance&&(this.cpuInstance.destroy(),this.cpuInstance=null)}}var y0,_x;function wS(){return _x||(_x=1,y0={webm:"data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlYm1Ch4EEQoWBAhhTgGcBAAAAAAAVkhFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua1OsggEwTbuMU6uEHFO7a1OsghV17AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAAEUq17GDD0JATYCNTGF2ZjU1LjMzLjEwMFdBjUxhdmY1NS4zMy4xMDBzpJBlrrXf3DCDVB8KcgbMpcr+RImIQJBgAAAAAAAWVK5rAQAAAAAAD++uAQAAAAAAADLXg Line truncated
NoSleep enabled for older iOS devices. This can interrupt
active or long-running network requests from completing successfully.
See https://github.com/richtr/NoSleep.js/issues/15 for more details.
`),this.noSleepTimer=window.setInterval(()=>{document.hidden||(window.location.href=window.location.href.split("#")[0],window.setTimeout(window.stop,0))},15e3),this.enabled=!0,Promise.resolve()):this.noSleepVideo.play().then(d=>(this.enabled=!0,d)).catch(d=>{throw this.enabled=!1,d})}disable(){l()?(this._wakeLock&&this._wakeLock.release(),this._wakeLock=null):i()?this.noSleepTimer&&(console.warn(`
NoSleep now disabled for older iOS devices.
`),window.clearInterval(this.noSleepTimer),this.noSleepTimer=null):this.noSleepVideo.pause(),this.enabled=!1}}return _0=u,_0}var CS=bS();const ES=ls(CS);function kS(n){if(n.length<4)return null;try{const i=parseInt(n.slice(0,2),16)&3;let l=2;if(i===0||i===3){if(n.length<l+8)return null;l+=8}if(n.length<l+2)return null;const u=parseInt(n.slice(l,l+2),16);l+=2;const c=u*2;return n.length<l+c?null:(l+=c,n.slice(l))}catch{return null}}function SS({packets:n,channels:s,onChannelCreate:i,onRunningChange:l,visible:u=!1}){const[c,h]=N.useState(!1),[d,g]=N.useState(6),[m,x]=N.useState(!1),[v,C]=N.useState(!0),[P,M]=N.useState(!1),[k,w]=N.useState(null),[B,b]=N.useState(new Map),[E,T]=N.useState([]),[F,I]=N.useState(!1),[j,O]=N.useState(null),[G,U]=N.useState(null),[K,J]=N.useState(0),Y=N.useRef(null),ie=N.useRef(null),ge=N.useRef(!1),$=N.useRef(!1),se=N.useRef(!1),W=N.useRef(new Map),te=N.useRef(!1),Z=N.useRef(6),D=N.useRef(!0),H=N.useRef(!1),q=N.useRef(new Set),Q=N.useRef(new Set);N.useEffect(()=>{const Ee=new _S;Y.current=Ee,O(Ee.isGpuAvailable());const je=new ES;return ie.current=je,()=>{Ee.destroy(),Y.current=null,je.disable(),ie.current=null}},[]),N.useEffect(()=>{!u||F||oS(async()=>{const{ENGLISH_WORDLIST:Ee}=await import("./wordlist-BtmChKSf.js");return{ENGLISH_WORDLIST:Ee}},[]).then(({ENGLISH_WORDLIST:Ee})=>{Y.current&&(Y.current.setWordlist(Ee),I(!0))}).catch(Ee=>{console.error("Failed to load wordlist:",Ee),At.error("Failed to load wordlist",{description:"Cracking will not be available"})})},[u,F]),N.useEffect(()=>{const Ee=()=>{ut.getUndecryptedPacketCount().then(({count:at})=>U(at)).catch(()=>U(null))};Ee();const je=setInterval(Ee,36e5);return()=>clearInterval(je)},[]);const ae=N.useMemo(()=>new Set(s.map(Ee=>Ee.key.toUpperCase())),[s]),ce=n.filter(Ee=>Ee.payload_type==="GROUP_TEXT"&&!Ee.decrypted);N.useEffect(()=>{let Ee=0;b(je=>{const at=new Map(je);let mt=!1;for(const ot of ce)if(!at.has(ot.id)){const qe=kS(ot.data);if(qe&&Q.current.has(qe)){Ee++;continue}qe&&Q.current.add(qe),at.set(ot.id,{packet:ot,attempts:0,lastAttemptLength:0,status:"pending"}),mt=!0}return mt?(W.current=at,at):je}),Ee>0&&J(je=>je+Ee)},[ce.length]),N.useEffect(()=>{W.current=B},[B]),N.useEffect(()=>{te.current=m},[m]),N.useEffect(()=>{Z.current=d},[d]),N.useEffect(()=>{D.current=v},[v]),N.useEffect(()=>{H.current=P},[P]),N.useEffect(()=>{q.current=new Set(ce.map(Ee=>Ee.id))},[ce]),N.useEffect(()=>{l==null||l(c)},[c,l]);const Ae=Array.from(B.values()).filter(Ee=>Ee.status==="pending").length,pe=Array.from(B.values()).filter(Ee=>Ee.status==="cracked").length,xe=Array.from(B.values()).filter(Ee=>Ee.status==="failed").length,Be=N.useCallback(async()=>{if(se.current||!Y.current||!ge.current)return;const Ee=W.current;let je=null,at=null;for(const[Ke,Qe]of Ee.entries())if(Qe.status==="pending"){je=Qe,at=Ke;break}if(!je&&te.current){const Ke=Array.from(Ee.entries()).filter(([,Qe])=>Qe.status==="failed"&&Qe.lastAttemptLength<10);Ke.length>0&&(Ke.sort((Qe,rt)=>Qe[1].lastAttemptLength-rt[1].lastAttemptLength),[at,je]=Ke[0])}if(!je||at===null){ge.current&&setTimeout(()=>Be(),1e3);return}if(!q.current.has(at)){b(Ke=>{const Qe=new Map(Ke);return Qe.delete(at),Qe}),ge.current&&setTimeout(()=>Be(),10);return}se.current=!0;const mt=Z.current,ot=je.lastAttemptLength>0,qe=ot?je.lastAttemptLength+1:mt;try{const Ke=await Y.current.crack(je.packet.data,{maxLength:qe,useSenderFilter:!0,useTimestampFilter:!0,useUtf8Filter:!0,...H.current&&{gpuDispatchMs:1e4},...ot&&{useDictionary:!1,startingLength:qe}},Qe=>{w(Qe)});if($.current){$.current=!1,se.current=!1,w(null);return}if(Ke.found&&Ke.roomName&&Ke.key){b(He=>{const Et=new Map(He),zt=Et.get(at);return zt&&Et.set(at,{...zt,status:"cracked",attempts:zt.attempts+1,lastAttemptLength:qe}),Et});const Qe={roomName:Ke.roomName,key:Ke.key,packetId:at,message:Ke.decryptedMessage||"",crackedAt:Date.now()};T(He=>[...He,Qe]);const rt=Ke.key.toUpperCase();if(!ae.has(rt))try{const He="#"+Ke.roomName;await i(He,Ke.key),D.current&&await ut.decryptHistoricalPackets({key_type:"channel",channel_name:He})}catch(He){console.error("Failed to create channel or decrypt historical:",He),At.error("Failed to save cracked channel",{description:He instanceof Error?He.message:"Channel discovered but could not be saved"})}}else b(Qe=>{const rt=new Map(Qe),He=rt.get(at);return He&&rt.set(at,{...He,status:"failed",attempts:He.attempts+1,lastAttemptLength:qe}),rt})}catch(Ke){console.error("Cracking error:",Ke),b(Qe=>{const rt=new Map(Qe),He=rt.get(at);return He&&rt.set(at,{...He,status:"failed",attempts:He.attempts+1,lastAttemptLength:qe}),rt})}se.current=!1,w(null),ge.current&&setTimeout(()=>Be(),100)},[ae,i]),Oe=()=>{var Ee;if(!j){At.error("WebGPU not available",{description:"Cracking requires Chrome 113+ or Edge 113+ with WebGPU support."});return}h(!0),ge.current=!0,$.current=!1,(Ee=ie.current)==null||Ee.enable(),Be()},Xe=()=>{var Ee,je;h(!1),ge.current=!1,$.current=!0,(Ee=Y.current)==null||Ee.abort(),(je=ie.current)==null|| Line truncated
//# sourceMappingURL=index-DpuVn1aK.js.map
+1
View File
@@ -0,0 +1 @@
{"version":3,"mappings":";;;;;;;;6CASa,IAAIA,EAAE,OAAO,IAAI,eAAe,EAAEC,EAAE,OAAO,IAAI,cAAc,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,mBAAmB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,eAAe,EAAEC,EAAE,OAAO,IAAI,mBAAmB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,YAAY,EAAEC,EAAE,OAAO,IAAI,YAAY,EAAEC,EAAE,OAAO,SAAS,SAASC,EAAEC,EAAE,CAAC,OAAUA,IAAP,MAAqB,OAAOA,GAAlB,SAA2B,MAAKA,EAAEF,GAAGE,EAAEF,CAAC,GAAGE,EAAE,YAAY,EAAqB,OAAOA,GAApB,WAAsBA,EAAE,KAAI,CAC1e,IAAIC,EAAE,CAAC,UAAU,UAAU,CAAC,MAAM,EAAE,EAAE,mBAAmB,UAAU,GAAG,oBAAoB,UAAU,GAAG,gBAAgB,UAAU,EAAE,EAAEC,EAAE,OAAO,OAAOC,EAAE,GAAG,SAASC,EAAEJ,EAAEK,EAAEC,EAAE,CAAC,KAAK,MAAMN,EAAE,KAAK,QAAQK,EAAE,KAAK,KAAKF,EAAE,KAAK,QAAQG,GAAGL,CAAC,CAACG,EAAE,UAAU,iBAAiB,GACnQA,EAAE,UAAU,SAAS,SAASJ,EAAEK,EAAE,CAAC,GAAc,OAAOL,GAAlB,UAAkC,OAAOA,GAApB,YAA6BA,GAAN,KAAQ,MAAM,MAAM,uHAAuH,EAAE,KAAK,QAAQ,gBAAgB,KAAKA,EAAEK,EAAE,UAAU,CAAC,EAAED,EAAE,UAAU,YAAY,SAASJ,EAAE,CAAC,KAAK,QAAQ,mBAAmB,KAAKA,EAAE,aAAa,CAAC,EAAE,SAASO,GAAG,EAAEA,EAAE,UAAUH,EAAE,UAAU,SAASI,EAAER,EAAEK,EAAEC,EAAE,CAAC,KAAK,MAAMN,EAAE,KAAK,QAAQK,EAAE,KAAK,KAAKF,EAAE,KAAK,QAAQG,GAAGL,CAAC,CAAC,IAAIQ,EAAED,EAAE,UAAU,IAAID,EACrfE,EAAE,YAAYD,EAAEN,EAAEO,EAAEL,EAAE,SAAS,EAAEK,EAAE,qBAAqB,GAAG,IAAIC,EAAE,MAAM,QAAQC,EAAE,OAAO,UAAU,eAAeC,EAAE,CAAC,QAAQ,IAAI,EAAEC,EAAE,CAAC,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,EAAE,EACxK,SAASC,EAAEd,EAAEK,EAAEC,EAAE,CAAC,IAAIS,EAAEC,GAAE,GAAGC,GAAE,KAAKC,GAAE,KAAK,GAASb,GAAN,KAAQ,IAAIU,KAAcV,EAAE,MAAX,SAAiBa,GAAEb,EAAE,KAAcA,EAAE,MAAX,SAAiBY,GAAE,GAAGZ,EAAE,KAAKA,EAAEM,EAAE,KAAKN,EAAEU,CAAC,GAAG,CAACF,EAAE,eAAeE,CAAC,IAAIC,GAAED,CAAC,EAAEV,EAAEU,CAAC,GAAG,IAAII,GAAE,UAAU,OAAO,EAAE,GAAOA,KAAJ,EAAMH,GAAE,SAASV,UAAU,EAAEa,GAAE,CAAC,QAAQC,GAAE,MAAMD,EAAC,EAAEE,GAAE,EAAEA,GAAEF,GAAEE,KAAID,GAAEC,EAAC,EAAE,UAAUA,GAAE,CAAC,EAAEL,GAAE,SAASI,EAAC,CAAC,GAAGpB,GAAGA,EAAE,aAAa,IAAIe,KAAKI,GAAEnB,EAAE,aAAamB,GAAWH,GAAED,CAAC,IAAZ,SAAgBC,GAAED,CAAC,EAAEI,GAAEJ,CAAC,GAAG,MAAM,CAAC,SAAS5B,EAAE,KAAKa,EAAE,IAAIiB,GAAE,IAAIC,GAAE,MAAMF,GAAE,OAAOJ,EAAE,OAAO,CAAC,CAC7a,SAASU,EAAEtB,EAAEK,EAAE,CAAC,MAAM,CAAC,SAASlB,EAAE,KAAKa,EAAE,KAAK,IAAIK,EAAE,IAAIL,EAAE,IAAI,MAAMA,EAAE,MAAM,OAAOA,EAAE,MAAM,CAAC,CAAC,SAASuB,EAAEvB,EAAE,CAAC,OAAiB,OAAOA,GAAlB,UAA4BA,IAAP,MAAUA,EAAE,WAAWb,CAAC,CAAC,SAASqC,EAAOxB,EAAE,CAAC,IAAIK,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,EAAE,MAAM,IAAIL,EAAE,QAAQ,QAAQ,SAASA,EAAE,CAAC,OAAOK,EAAEL,CAAC,CAAC,CAAC,CAAC,CAAC,IAAIyB,EAAE,OAAO,SAASC,EAAE1B,EAAEK,EAAE,CAAC,OAAiB,OAAOL,GAAlB,UAA4BA,IAAP,MAAgBA,EAAE,KAAR,KAAYwB,EAAO,GAAGxB,EAAE,GAAG,EAAEK,EAAE,SAAS,EAAE,CAAC,CAC/W,SAASsB,GAAE3B,EAAEK,EAAEC,EAAES,EAAEC,GAAE,CAAC,IAAIC,GAAE,OAAOjB,GAAmBiB,KAAd,aAA6BA,KAAZ,aAAcjB,EAAE,MAAK,IAAIkB,GAAE,GAAG,GAAUlB,IAAP,KAASkB,GAAE,OAAQ,QAAOD,GAAC,CAAE,IAAK,SAAS,IAAK,SAASC,GAAE,GAAG,MAAM,IAAK,SAAS,OAAOlB,EAAE,SAAQ,CAAE,KAAKb,EAAE,KAAKC,EAAE8B,GAAE,EAAE,CAAC,CAAC,GAAGA,GAAE,OAAOA,GAAElB,EAAEgB,GAAEA,GAAEE,EAAC,EAAElB,EAAOe,IAAL,GAAO,IAAIW,EAAER,GAAE,CAAC,EAAEH,EAAEL,EAAEM,EAAC,GAAGV,EAAE,GAASN,GAAN,OAAUM,EAAEN,EAAE,QAAQyB,EAAE,KAAK,EAAE,KAAKE,GAAEX,GAAEX,EAAEC,EAAE,GAAG,SAASN,GAAE,CAAC,OAAOA,EAAC,CAAC,GAASgB,IAAN,OAAUO,EAAEP,EAAC,IAAIA,GAAEM,EAAEN,GAAEV,GAAG,CAACU,GAAE,KAAKE,IAAGA,GAAE,MAAMF,GAAE,IAAI,IAAI,GAAGA,GAAE,KAAK,QAAQS,EAAE,KAAK,EAAE,KAAKzB,CAAC,GAAGK,EAAE,KAAKW,EAAC,GAAG,EAAyB,GAAvBE,GAAE,EAAEH,EAAOA,IAAL,GAAO,IAAIA,EAAE,IAAOL,EAAEV,CAAC,EAAE,QAAQmB,GAAE,EAAEA,GAAEnB,EAAE,OAAOmB,KAAI,CAACF,GACrfjB,EAAEmB,EAAC,EAAE,IAAIC,GAAEL,EAAEW,EAAET,GAAEE,EAAC,EAAED,IAAGS,GAAEV,GAAEZ,EAAEC,EAAEc,GAAEJ,EAAC,CAAC,SAASI,GAAErB,EAAEC,CAAC,EAAe,OAAOoB,IAApB,WAAsB,IAAIpB,EAAEoB,GAAE,KAAKpB,CAAC,EAAEmB,GAAE,EAAE,EAAEF,GAAEjB,EAAE,KAAI,GAAI,MAAMiB,GAAEA,GAAE,MAAMG,GAAEL,EAAEW,EAAET,GAAEE,IAAG,EAAED,IAAGS,GAAEV,GAAEZ,EAAEC,EAAEc,GAAEJ,EAAC,UAAqBC,KAAX,SAAa,MAAMZ,EAAE,OAAOL,CAAC,EAAE,MAAM,mDAAuEK,IAApB,kBAAsB,qBAAqB,OAAO,KAAKL,CAAC,EAAE,KAAK,IAAI,EAAE,IAAIK,GAAG,2EAA2E,EAAE,OAAOa,EAAC,CACzZ,SAASU,GAAE5B,EAAEK,EAAEC,EAAE,CAAC,GAASN,GAAN,KAAQ,OAAOA,EAAE,IAAIe,EAAE,GAAGC,GAAE,EAAE,OAAAW,GAAE3B,EAAEe,EAAE,GAAG,GAAG,SAASf,GAAE,CAAC,OAAOK,EAAE,KAAKC,EAAEN,GAAEgB,IAAG,CAAC,CAAC,EAASD,CAAC,CAAC,SAASc,EAAE7B,EAAE,CAAC,GAAQA,EAAE,UAAP,GAAe,CAAC,IAAIK,EAAEL,EAAE,QAAQK,EAAEA,EAAC,EAAGA,EAAE,KAAK,SAASA,EAAE,EAAQL,EAAE,UAAN,GAAoBA,EAAE,UAAP,MAAeA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAC,EAAE,SAASA,EAAE,EAAQL,EAAE,UAAN,GAAoBA,EAAE,UAAP,MAAeA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAC,CAAC,EAAOL,EAAE,UAAP,KAAiBA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAE,CAAC,GAAOL,EAAE,UAAN,EAAc,OAAOA,EAAE,QAAQ,QAAQ,MAAMA,EAAE,OAAQ,CAC5Z,IAAI8B,GAAE,CAAC,QAAQ,IAAI,EAAEC,EAAE,CAAC,WAAW,IAAI,EAAEC,GAAE,CAAC,uBAAuBF,GAAE,wBAAwBC,EAAE,kBAAkBnB,CAAC,EAAE,SAASqB,GAAG,CAAC,MAAM,MAAM,0DAA0D,CAAE,CACzM,OAAAC,GAAA,SAAiB,CAAC,IAAIN,GAAE,QAAQ,SAAS5B,EAAEK,EAAEC,EAAE,CAACsB,GAAE5B,EAAE,UAAU,CAACK,EAAE,MAAM,KAAK,SAAS,CAAC,EAAEC,CAAC,CAAC,EAAE,MAAM,SAASN,EAAE,CAAC,IAAIK,EAAE,EAAE,OAAAuB,GAAE5B,EAAE,UAAU,CAACK,GAAG,CAAC,EAASA,CAAC,EAAE,QAAQ,SAASL,EAAE,CAAC,OAAO4B,GAAE5B,EAAE,SAASA,EAAE,CAAC,OAAOA,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,SAASA,EAAE,CAAC,GAAG,CAACuB,EAAEvB,CAAC,EAAE,Line truncated
-542
View File
@@ -1,542 +0,0 @@
var Ay=Object.defineProperty;var vy=(n,s,i)=>s in n?Ay(n,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[s]=i;var Wo=(n,s,i)=>vy(n,typeof s!="symbol"?s+"":s,i);function yy(n,s){for(var i=0;i<s.length;i++){const l=s[i];if(typeof l!="string"&&!Array.isArray(l)){for(const c in l)if(c!=="default"&&!(c in n)){const u=Object.getOwnPropertyDescriptor(l,c);u&&Object.defineProperty(n,c,u.get?u:{enumerable:!0,get:()=>l[c]})}}}return Object.freeze(Object.defineProperty(n,Symbol.toStringTag,{value:"Module"}))}(function(){const s=document.createElement("link").relList;if(s&&s.supports&&s.supports("modulepreload"))return;for(const c of document.querySelectorAll('link[rel="modulepreload"]'))l(c);new MutationObserver(c=>{for(const u of c)if(u.type==="childList")for(const p of u.addedNodes)p.tagName==="LINK"&&p.rel==="modulepreload"&&l(p)}).observe(document,{childList:!0,subtree:!0});function i(c){const u={};return c.integrity&&(u.integrity=c.integrity),c.referrerPolicy&&(u.referrerPolicy=c.referrerPolicy),c.crossOrigin==="use-credentials"?u.credentials="include":c.crossOrigin==="anonymous"?u.credentials="omit":u.credentials="same-origin",u}function l(c){if(c.ep)return;c.ep=!0;const u=i(c);fetch(c.href,u)}})();var Qf=typeof globalThis<"u"?globalThis:typeof window<"u"?window:typeof global<"u"?global:typeof self<"u"?self:{};function aa(n){return n&&n.__esModule&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n}function xx(n){if(Object.prototype.hasOwnProperty.call(n,"__esModule"))return n;var s=n.default;if(typeof s=="function"){var i=function l(){return this instanceof l?Reflect.construct(s,arguments,this.constructor):s.apply(this,arguments)};i.prototype=s.prototype}else i={};return Object.defineProperty(i,"__esModule",{value:!0}),Object.keys(n).forEach(function(l){var c=Object.getOwnPropertyDescriptor(n,l);Object.defineProperty(i,l,c.get?c:{enumerable:!0,get:function(){return n[l]}})}),i}var Yf={exports:{}},el={},Xf={exports:{}},pt={};/**
* @license React
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Kp;function _y(){if(Kp)return pt;Kp=1;var n=Symbol.for("react.element"),s=Symbol.for("react.portal"),i=Symbol.for("react.fragment"),l=Symbol.for("react.strict_mode"),c=Symbol.for("react.profiler"),u=Symbol.for("react.provider"),p=Symbol.for("react.context"),d=Symbol.for("react.forward_ref"),g=Symbol.for("react.suspense"),m=Symbol.for("react.memo"),x=Symbol.for("react.lazy"),A=Symbol.iterator;function w(D){return D===null||typeof D!="object"?null:(D=A&&D[A]||D["@@iterator"],typeof D=="function"?D:null)}var k={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},N=Object.assign,C={};function b(D,z,q){this.props=D,this.context=z,this.refs=C,this.updater=q||k}b.prototype.isReactComponent={},b.prototype.setState=function(D,z){if(typeof D!="object"&&typeof D!="function"&&D!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,D,z,"setState")},b.prototype.forceUpdate=function(D){this.updater.enqueueForceUpdate(this,D,"forceUpdate")};function B(){}B.prototype=b.prototype;function S(D,z,q){this.props=D,this.context=z,this.refs=C,this.updater=q||k}var T=S.prototype=new B;T.constructor=S,N(T,b.prototype),T.isPureReactComponent=!0;var F=Array.isArray,M=Object.prototype.hasOwnProperty,H={current:null},V={key:!0,ref:!0,__self:!0,__source:!0};function j(D,z,q){var K,ce={},he=null,xe=null;if(z!=null)for(K in z.ref!==void 0&&(xe=z.ref),z.key!==void 0&&(he=""+z.key),z)M.call(z,K)&&!V.hasOwnProperty(K)&&(ce[K]=z[K]);var pe=arguments.length-2;if(pe===1)ce.children=q;else if(1<pe){for(var ge=Array(pe),Be=0;Be<pe;Be++)ge[Be]=arguments[Be+2];ce.children=ge}if(D&&D.defaultProps)for(K in pe=D.defaultProps,pe)ce[K]===void 0&&(ce[K]=pe[K]);return{$$typeof:n,type:D,key:he,ref:xe,props:ce,_owner:H.current}}function ee(D,z){return{$$typeof:n,type:D.type,key:z,ref:D.ref,props:D.props,_owner:D._owner}}function Z(D){return typeof D=="object"&&D!==null&&D.$$typeof===n}function Q(D){var z={"=":"=0",":":"=2"};return"$"+D.replace(/[=:]/g,function(q){return z[q]})}var J=/\/+/g;function $(D,z){return typeof D=="object"&&D!==null&&D.key!=null?Q(""+D.key):z.toString(36)}function oe(D,z,q,K,ce){var he=typeof D;(he==="undefined"||he==="boolean")&&(D=null);var xe=!1;if(D===null)xe=!0;else switch(he){case"string":case"number":xe=!0;break;case"object":switch(D.$$typeof){case n:case s:xe=!0}}if(xe)return xe=D,ce=ce(xe),D=K===""?"."+$(xe,0):K,F(ce)?(q="",D!=null&&(q=D.replace(J,"$&/")+"/"),oe(ce,z,q,"",function(Be){return Be})):ce!=null&&(Z(ce)&&(ce=ee(ce,q+(!ce.key||xe&&xe.key===ce.key?"":(""+ce.key).replace(J,"$&/")+"/")+D)),z.push(ce)),1;if(xe=0,K=K===""?".":K+":",F(D))for(var pe=0;pe<D.length;pe++){he=D[pe];var ge=K+$(he,pe);xe+=oe(he,z,q,ge,ce)}else if(ge=w(D),typeof ge=="function")for(D=ge.call(D),pe=0;!(he=D.next()).done;)he=he.value,ge=K+$(he,pe++),xe+=oe(he,z,q,ge,ce);else if(he==="object")throw z=String(D),Error("Objects are not valid as a React child (found: "+(z==="[object Object]"?"object with keys {"+Object.keys(D).join(", ")+"}":z)+"). If you meant to render a collection of children, use an array instead.");return xe}function me(D,z,q){if(D==null)return D;var K=[],ce=0;return oe(D,K,"","",function(he){return z.call(q,he,ce++)}),K}function G(D){if(D._status===-1){var z=D._result;z=z(),z.then(function(q){(D._status===0||D._status===-1)&&(D._status=1,D._result=q)},function(q){(D._status===0||D._status===-1)&&(D._status=2,D._result=q)}),D._status===-1&&(D._status=0,D._result=z)}if(D._status===1)return D._result.default;throw D._result}var se={current:null},W={transition:null},ne={ReactCurrentDispatcher:se,ReactCurrentBatchConfig:W,ReactCurrentOwner:H};function U(){throw Error("act(...) is not supported in production builds of React.")}return pt.Children={map:me,forEach:function(D,z,q){me(D,function(){z.apply(this,arguments)},q)},count:function(D){var z=0;return me(D,function(){z++}),z},toArray:function(D){return me(D,function(z){return z})||[]},only:function(D){if(!Z(D))throw Error("React.Children.only expected to receive a single React element child.");return D}},pt.Component=b,pt.Fragment=i,pt.Profiler=c,pt.PureComponent=S,pt.StrictMode=l,pt.Suspense=g,pt.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=ne,pt.act=U,pt.cloneElement=function(D,z,q){if(D==null)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+D+".");var K=N({},D.props),ce=D.key,he=D.ref,xe=D._owner;if(z!=null){if(z.ref!==void 0&&(he=z.ref,xe=H.current),z.key!==void 0&&(ce=""+z.key),D.type&&D.type.defaultProps)var pe=D.type.defaultProps;for(ge in z)M.call(z,ge)&&!V.hasOwnProperty(ge)&&(K[ge]=z[ge]===void 0&&pe!==void 0?pe[ge]:z[ge])}var ge=arguments.length-2;if(ge===1)K.children=q;else if(1<ge){pe=Array(ge);for(var Be=0;Be<ge;Be++)pe[Be]=arguments[Be+2];K.children=pe}return{$$typeof:n,type:D.type,key:ce,ref:he,props:K,_owner:xe}},pt.creatLine truncated
* @license React
* react-jsx-runtime.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Yp;function wy(){if(Yp)return el;Yp=1;var n=I0(),s=Symbol.for("react.element"),i=Symbol.for("react.fragment"),l=Object.prototype.hasOwnProperty,c=n.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,u={key:!0,ref:!0,__self:!0,__source:!0};function p(d,g,m){var x,A={},w=null,k=null;m!==void 0&&(w=""+m),g.key!==void 0&&(w=""+g.key),g.ref!==void 0&&(k=g.ref);for(x in g)l.call(g,x)&&!u.hasOwnProperty(x)&&(A[x]=g[x]);if(d&&d.defaultProps)for(x in g=d.defaultProps,g)A[x]===void 0&&(A[x]=g[x]);return{$$typeof:s,type:d,key:w,ref:k,props:A,_owner:c.current}}return el.Fragment=i,el.jsx=p,el.jsxs=p,el}var Xp;function by(){return Xp||(Xp=1,Yf.exports=wy()),Yf.exports}var _=by(),R=I0();const Pe=aa(R),O0=yy({__proto__:null,default:Pe},[R]);var Vc={},Jf={exports:{}},Kn={},e0={exports:{}},t0={};/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var Jp;function Cy(){return Jp||(Jp=1,(function(n){function s(W,ne){var U=W.length;W.push(ne);e:for(;0<U;){var D=U-1>>>1,z=W[D];if(0<c(z,ne))W[D]=ne,W[U]=z,U=D;else break e}}function i(W){return W.length===0?null:W[0]}function l(W){if(W.length===0)return null;var ne=W[0],U=W.pop();if(U!==ne){W[0]=U;e:for(var D=0,z=W.length,q=z>>>1;D<q;){var K=2*(D+1)-1,ce=W[K],he=K+1,xe=W[he];if(0>c(ce,U))he<z&&0>c(xe,ce)?(W[D]=xe,W[he]=U,D=he):(W[D]=ce,W[K]=U,D=K);else if(he<z&&0>c(xe,U))W[D]=xe,W[he]=U,D=he;else break e}}return ne}function c(W,ne){var U=W.sortIndex-ne.sortIndex;return U!==0?U:W.id-ne.id}if(typeof performance=="object"&&typeof performance.now=="function"){var u=performance;n.unstable_now=function(){return u.now()}}else{var p=Date,d=p.now();n.unstable_now=function(){return p.now()-d}}var g=[],m=[],x=1,A=null,w=3,k=!1,N=!1,C=!1,b=typeof setTimeout=="function"?setTimeout:null,B=typeof clearTimeout=="function"?clearTimeout:null,S=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function T(W){for(var ne=i(m);ne!==null;){if(ne.callback===null)l(m);else if(ne.startTime<=W)l(m),ne.sortIndex=ne.expirationTime,s(g,ne);else break;ne=i(m)}}function F(W){if(C=!1,T(W),!N)if(i(g)!==null)N=!0,G(M);else{var ne=i(m);ne!==null&&se(F,ne.startTime-W)}}function M(W,ne){N=!1,C&&(C=!1,B(j),j=-1),k=!0;var U=w;try{for(T(ne),A=i(g);A!==null&&(!(A.expirationTime>ne)||W&&!Q());){var D=A.callback;if(typeof D=="function"){A.callback=null,w=A.priorityLevel;var z=D(A.expirationTime<=ne);ne=n.unstable_now(),typeof z=="function"?A.callback=z:A===i(g)&&l(g),T(ne)}else l(g);A=i(g)}if(A!==null)var q=!0;else{var K=i(m);K!==null&&se(F,K.startTime-ne),q=!1}return q}finally{A=null,w=U,k=!1}}var H=!1,V=null,j=-1,ee=5,Z=-1;function Q(){return!(n.unstable_now()-Z<ee)}function J(){if(V!==null){var W=n.unstable_now();Z=W;var ne=!0;try{ne=V(!0,W)}finally{ne?$():(H=!1,V=null)}}else H=!1}var $;if(typeof S=="function")$=function(){S(J)};else if(typeof MessageChannel<"u"){var oe=new MessageChannel,me=oe.port2;oe.port1.onmessage=J,$=function(){me.postMessage(null)}}else $=function(){b(J,0)};function G(W){V=W,H||(H=!0,$())}function se(W,ne){j=b(function(){W(n.unstable_now())},ne)}n.unstable_IdlePriority=5,n.unstable_ImmediatePriority=1,n.unstable_LowPriority=4,n.unstable_NormalPriority=3,n.unstable_Profiling=null,n.unstable_UserBlockingPriority=2,n.unstable_cancelCallback=function(W){W.callback=null},n.unstable_continueExecution=function(){N||k||(N=!0,G(M))},n.unstable_forceFrameRate=function(W){0>W||125<W?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):ee=0<W?Math.floor(1e3/W):5},n.unstable_getCurrentPriorityLevel=function(){return w},n.unstable_getFirstCallbackNode=function(){return i(g)},n.unstable_next=function(W){switch(w){case 1:case 2:case 3:var ne=3;break;default:ne=w}var U=w;w=ne;try{return W()}finally{w=U}},n.unstable_pauseExecution=function(){},n.unstable_requestPaint=function(){},n.unstable_runWithPriority=function(W,ne){switch(W){case 1:case 2:case 3:case 4:case 5:break;default:W=3}var U=w;w=W;try{return ne()}finally{w=U}},n.unstable_scheduleCallback=function(W,ne,U){var D=n.unstable_now();switch(typeof U=="object"&&U!==null?(U=U.delay,U=typeof U=="number"&&0<U?D+U:D):U=D,W){case 1:var z=-1;break;case 2:z=250;break;case 5:z=1073741823;break;case 4:z=1e4;break;default:z=5e3}return z=U+z,W={id:x++,callback:ne,priorityLevel:W,startTime:U,expirationTime:z,sortIndex:-1},U>D?(W.sortIndex=U,s(m,W),i(g)===null&&W===i(m)&&(C?(B(j),j=-1):C=!0,se(F,U-D))):(W.sortIndex=z,s(g,W),N||k||(N=!0,G(M))),W},n.unstable_shouldYield=Q,n.unstable_wrapCallback=function(W){var ne=w;return function(){var U=w;w=ne;try{return W.apply(this,arguments)}finally{w=U}}}})(t0)),t0}var em;function Ey(){return em||(em=1,e0.exports=Cy()),e0.exports}/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/var tm;function ky(){if(tm)return Kn;tm=1;var n=I0(),s=Ey();function i(e){for(var r="https://reactjs.org/docs/error-decoder.html?invariant="+e,a=1;a<arguments.length;a++)r+="&args[]="+encodeURIComponent(arguments[a]);return"Minified React error #"+e+"; visit "+r+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var l=new Set,c={};function u(e,r){p(e,r),p(e+"Capture",r)}function p(e,r){for(c[e]=r,e=0;e<r.length;e++)l.add(r[e])}var d=!(typeof window>"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),g=Object.prototype.hasOwnProperty,m=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,x={},A={};function w(e){return g.call(A,e)?!0:g.call(x,e)?!1:m.test(e)?A[e]=!0:(x[e]=!0,!1)}function k(e,r,a,h){if(a!==null&&a.type===0)return!1;switch(typeof r){case"function":case"symbol":return!0;case"boolean":return h?!1:a!==null?!a.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function N(e,r,a,h){if(r===null||typeof r>"u"||k(e,r,a,h))return!0;if(h)return!1;if(a!==null)switch(a.type){case 3:return!r;case 4:return r===!1;case 5:return isNaN(r);case 6:return isNaN(r)||1>r}return!1}function C(e,r,a,h,y,E,I){this.acceptsBooleans=r===2||r===3||r===4,this.attributeName=h,this.attributeNamespace=y,this.mustUseProperty=a,this.propertyName=e,this.type=r,this.sanitizeURL=E,this.removeEmptyString=I}var b={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){b[e]=new C(e,0,!1,e,null,!1,!1)}),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var r=e[0];b[r]=new C(r,1,!1,e[1],null,!1,!1)}),["contentEditable","draggable","spellCheck","value"].forEach(function(e){b[e]=new C(e,2,!1,e.toLowerCase(),null,!1,!1)}),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){b[e]=new C(e,2,!1,e,null,!1,!1)}),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){b[e]=new C(e,3,!1,e.toLowerCase(),null,!1,!1)}),["checked","multiple","muted","selected"].forEach(function(e){b[e]=new C(e,3,!0,e,null,!1,!1)}),["capture","download"].forEach(function(e){b[e]=new C(e,4,!1,e,null,!1,!1)}),["cols","rows","size","span"].forEach(function(e){b[e]=new C(e,6,!1,e,null,!1,!1)}),["rowSpan","start"].forEach(function(e){b[e]=new C(e,5,!1,e.toLowerCase(),null,!1,!1)});var B=/[\-:]([a-z])/g;function S(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var r=e.replace(B,S);b[r]=new C(r,1,!1,e,null,!1,!1)}),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var r=e.replace(B,S);b[r]=new C(r,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)}),["xml:base","xml:lang","xml:space"].forEach(function(e){var r=e.replace(B,S);b[r]=new C(r,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)}),["tabIndex","crossOrigin"].forEach(function(e){b[e]=new C(e,1,!1,e.toLowerCase(),null,!1,!1)}),b.xlinkHref=new C("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1),["src","href","action","formAction"].forEach(function(e){b[e]=new C(e,1,!1,e.toLowerCase(),null,!0,!0)});function T(e,r,a,h){var y=b.hasOwnProperty(r)?b[r]:null;(y!==null?y.type!==0:h||!(2<r.length)||r[0]!=="o"&&r[0]!=="O"||r[1]!=="n"&&r[1]!= Line truncated
`+D+e}var q=!1;function K(e,r){if(!e||q)return"";q=!0;var a=Error.prepareStackTrace;Error.prepareStackTrace=void 0;try{if(r)if(r=function(){throw Error()},Object.defineProperty(r.prototype,"props",{set:function(){throw Error()}}),typeof Reflect=="object"&&Reflect.construct){try{Reflect.construct(r,[])}catch(fe){var h=fe}Reflect.construct(e,[],r)}else{try{r.call()}catch(fe){h=fe}e.call(r.prototype)}else{try{throw Error()}catch(fe){h=fe}e()}}catch(fe){if(fe&&h&&typeof fe.stack=="string"){for(var y=fe.stack.split(`
`),E=h.stack.split(`
`),I=y.length-1,Y=E.length-1;1<=I&&0<=Y&&y[I]!==E[Y];)Y--;for(;1<=I&&0<=Y;I--,Y--)if(y[I]!==E[Y]){if(I!==1||Y!==1)do if(I--,Y--,0>Y||y[I]!==E[Y]){var te=`
`+y[I].replace(" at new "," at ");return e.displayName&&te.includes("<anonymous>")&&(te=te.replace("<anonymous>",e.displayName)),te}while(1<=I&&0<=Y);break}}}finally{q=!1,Error.prepareStackTrace=a}return(e=e?e.displayName||e.name:"")?z(e):""}function ce(e){switch(e.tag){case 5:return z(e.type);case 16:return z("Lazy");case 13:return z("Suspense");case 19:return z("SuspenseList");case 0:case 2:case 15:return e=K(e.type,!1),e;case 11:return e=K(e.type.render,!1),e;case 1:return e=K(e.type,!0),e;default:return""}}function he(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case V:return"Fragment";case H:return"Portal";case ee:return"Profiler";case j:return"StrictMode";case $:return"Suspense";case oe:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case Q:return(e.displayName||"Context")+".Consumer";case Z:return(e._context.displayName||"Context")+".Provider";case J:var r=e.render;return e=e.displayName,e||(e=r.displayName||r.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case me:return r=e.displayName||null,r!==null?r:he(e.type)||"Memo";case G:r=e._payload,e=e._init;try{return he(e(r))}catch{}}return null}function xe(e){var r=e.type;switch(e.tag){case 24:return"Cache";case 9:return(r.displayName||"Context")+".Consumer";case 10:return(r._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=r.render,e=e.displayName||e.name||"",r.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return r;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return he(r);case 8:return r===j?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof r=="function")return r.displayName||r.name||null;if(typeof r=="string")return r}return null}function pe(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ge(e){var r=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(r==="checkbox"||r==="radio")}function Be(e){var r=ge(e)?"checked":"value",a=Object.getOwnPropertyDescriptor(e.constructor.prototype,r),h=""+e[r];if(!e.hasOwnProperty(r)&&typeof a<"u"&&typeof a.get=="function"&&typeof a.set=="function"){var y=a.get,E=a.set;return Object.defineProperty(e,r,{configurable:!0,get:function(){return y.call(this)},set:function(I){h=""+I,E.call(this,I)}}),Object.defineProperty(e,r,{enumerable:a.enumerable}),{getValue:function(){return h},setValue:function(I){h=""+I},stopTracking:function(){e._valueTracker=null,delete e[r]}}}}function We(e){e._valueTracker||(e._valueTracker=Be(e))}function $e(e){if(!e)return!1;var r=e._valueTracker;if(!r)return!0;var a=r.getValue(),h="";return e&&(h=ge(e)?e.checked?"true":"false":e.value),e=h,e!==a?(r.setValue(e),!0):!1}function Ce(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Ve(e,r){var a=r.checked;return U({},r,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:a??e._wrapperState.initialChecked})}function ot(e,r){var a=r.defaultValue==null?"":r.defaultValue,h=r.checked!=null?r.checked:r.defaultChecked;a=pe(r.value!=null?r.value:a),e._wrapperState={initialChecked:h,initialValue:a,controlled:r.type==="checkbox"||r.type==="radio"?r.checked!=null:r.value!=null}}function mt(e,r){r=r.checked,r!=null&&T(e,"checked",r,!1)}function ct(e,r){mt(e,r);var a=pe(r.value),h=r.type;if(a!=null)h==="number"?(a===0&&e.value===""||e.value!=a)&&(e.value=""+a):e.value!==""+a&&(e.value=""+a);else if(h==="submit"||h==="reset"){e.removeAttribute("value");return}r.hasOwnProperty("value")?Ke(e,r.type,a):r.hasOwnProperty("defaultValue")&&Ke(e,r.type,pe(r.defaultValue)),r.checked==null&&r.defaultChecked!=null&&(e.defaultChecked=!!r.defaultChecked)}function ht(e,r,a){if(r.hasOwnProperty("value")||r.hasOwnProperty("defaultValue")){var h=r.type;if(!(h!=="submit"&&h!=="reset"||r.value!==void 0&&r.value!==null))return;r=""+e._wrapperState.initialValue,a||r===e.value||(e.value=r),e.defaultValue=r}a=e.name,a!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,a!==""&&(e.name=a)}function Ke(e,r,a){(r!=="number"||Ce(e.ownerDocument)!==e)&&(a==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+a&&(e.defaultValue=""+a))}var Ge=Array.isArray;function Je(e,r,a,h){if(e=e.options,r){r={};for(var y=0;y<a.length;y++)r["$"+a[y]]=!0;for(a=0;a<e.length;a++)y=r.hasOwnProperty("$"+e[a].value),e[a].selected!==y&&(e[a].selected=y),y&&h&&(e[a].defaultSelected=!0)}else{for(a=""+pe(a),r=null,y=0;y<e.length;y++){if(e[y].value===a){e[y].selected=!0,h&&(e[y].defaultSelected=!0);return}r!==null||e[y].disabled||(r=e[y])}r!==null&&(r.selected=!0)}}function Ue(e,r){if(r.dangerouslySetInner Line truncated
`).replace(X,"")}function de(e,r,a){if(r=ae(r),ae(e)!==r&&a)throw Error(i(425))}function ye(){}var De=null,Qe=null;function at(e,r){return e==="textarea"||e==="noscript"||typeof r.children=="string"||typeof r.children=="number"||typeof r.dangerouslySetInnerHTML=="object"&&r.dangerouslySetInnerHTML!==null&&r.dangerouslySetInnerHTML.__html!=null}var an=typeof setTimeout=="function"?setTimeout:void 0,nn=typeof clearTimeout=="function"?clearTimeout:void 0,Ln=typeof Promise=="function"?Promise:void 0,kn=typeof queueMicrotask=="function"?queueMicrotask:typeof Ln<"u"?function(e){return Ln.resolve(null).then(e).catch(Xi)}:an;function Xi(e){setTimeout(function(){throw e})}function ja(e,r){var a=r,h=0;do{var y=a.nextSibling;if(e.removeChild(a),y&&y.nodeType===8)if(a=y.data,a==="/$"){if(h===0){e.removeChild(y),nr(r);return}h--}else a!=="$"&&a!=="$?"&&a!=="$!"||h++;a=y}while(a);nr(r)}function Yr(e){for(;e!=null;e=e.nextSibling){var r=e.nodeType;if(r===1||r===3)break;if(r===8){if(r=e.data,r==="$"||r==="$!"||r==="$?")break;if(r==="/$")return null}}return e}function rc(e){e=e.previousSibling;for(var r=0;e;){if(e.nodeType===8){var a=e.data;if(a==="$"||a==="$!"||a==="$?"){if(r===0)return e;r--}else a==="/$"&&r++}e=e.previousSibling}return null}var mi=Math.random().toString(36).slice(2),xr="__reactFiber$"+mi,Ji="__reactProps$"+mi,Bt="__reactContainer$"+mi,eo="__reactEvents$"+mi,Zd="__reactListeners$"+mi,Wd="__reactHandles$"+mi;function gi(e){var r=e[xr];if(r)return r;for(var a=e.parentNode;a;){if(r=a[Bt]||a[xr]){if(a=r.alternate,r.child!==null||a!==null&&a.child!==null)for(e=rc(e);e!==null;){if(a=e[xr])return a;e=rc(e)}return r}e=a,a=e.parentNode}return null}function xi(e){return e=e[xr]||e[Bt],!e||e.tag!==5&&e.tag!==6&&e.tag!==13&&e.tag!==3?null:e}function Ai(e){if(e.tag===5||e.tag===6)return e.stateNode;throw Error(i(33))}function Ns(e){return e[Ji]||null}var qd=[],Fs=-1;function to(e){return{current:e}}function zt(e){0>Fs||(e.current=qd[Fs],qd[Fs]=null,Fs--)}function Mt(e,r){Fs++,qd[Fs]=e.current,e.current=r}var no={},Sn=to(no),Zn=to(!1),Fo=no;function Ls(e,r){var a=e.type.contextTypes;if(!a)return no;var h=e.stateNode;if(h&&h.__reactInternalMemoizedUnmaskedChildContext===r)return h.__reactInternalMemoizedMaskedChildContext;var y={},E;for(E in a)y[E]=r[E];return h&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=r,e.__reactInternalMemoizedMaskedChildContext=y),y}function Wn(e){return e=e.childContextTypes,e!=null}function ic(){zt(Zn),zt(Sn)}function xh(e,r,a){if(Sn.current!==no)throw Error(i(168));Mt(Sn,r),Mt(Zn,a)}function Ah(e,r,a){var h=e.stateNode;if(r=r.childContextTypes,typeof h.getChildContext!="function")return a;h=h.getChildContext();for(var y in h)if(!(y in r))throw Error(i(108,xe(e)||"Unknown",y));return U({},a,h)}function oc(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||no,Fo=Sn.current,Mt(Sn,e),Mt(Zn,Zn.current),!0}function vh(e,r,a){var h=e.stateNode;if(!h)throw Error(i(169));a?(e=Ah(e,r,Fo),h.__reactInternalMemoizedMergedChildContext=e,zt(Zn),zt(Sn),Mt(Sn,e)):zt(Zn),Mt(Zn,a)}var vi=null,sc=!1,Gd=!1;function yh(e){vi===null?vi=[e]:vi.push(e)}function Iv(e){sc=!0,yh(e)}function ro(){if(!Gd&&vi!==null){Gd=!0;var e=0,r=_t;try{var a=vi;for(_t=1;e<a.length;e++){var h=a[e];do h=h(!0);while(h!==null)}vi=null,sc=!1}catch(y){throw vi!==null&&(vi=vi.slice(e+1)),Nl(pa,ro),y}finally{_t=r,Gd=!1}}return null}var Ms=[],Is=0,ac=null,lc=0,Ar=[],vr=0,Lo=null,yi=1,_i="";function Mo(e,r){Ms[Is++]=lc,Ms[Is++]=ac,ac=e,lc=r}function _h(e,r,a){Ar[vr++]=yi,Ar[vr++]=_i,Ar[vr++]=Lo,Lo=e;var h=yi;e=_i;var y=32-st(h)-1;h&=~(1<<y),a+=1;var E=32-st(r)+y;if(30<E){var I=y-y%5;E=(h&(1<<I)-1).toString(32),h>>=I,y-=I,yi=1<<32-st(r)+y|a<<y|h,_i=E+e}else yi=1<<E|a<<y|h,_i=e}function $d(e){e.return!==null&&(Mo(e,1),_h(e,1,0))}function Kd(e){for(;e===ac;)ac=Ms[--Is],Ms[Is]=null,lc=Ms[--Is],Ms[Is]=null;for(;e===Lo;)Lo=Ar[--vr],Ar[vr]=null,_i=Ar[--vr],Ar[vr]=null,yi=Ar[--vr],Ar[vr]=null}var ar=null,lr=null,Zt=!1,Nr=null;function wh(e,r){var a=br(5,null,null,0);a.elementType="DELETED",a.stateNode=r,a.return=e,r=e.deletions,r===null?(e.deletions=[a],e.flags|=16):r.push(a)}function bh(e,r){switch(e.tag){case 5:var a=e.type;return r=r.nodeType!==1||a.toLowerCase()!==r.nodeName.toLowerCase()?null:r,r!==null?(e.stateNode=r,ar=e,lr=Yr(r.firstChild),!0):!1;case 6:return r=e.pendingProps===""||r.nodeType!==3?null:r,r!==null?(e.stateNode=r,ar=e,lr=null,!0):!1;case 13:return r=r.nodeType!==8?null:r,r!==null?(a=Lo!==null?{id:yi,overflow:_i}:null,e.memoizedState={dehydrated:r,treeContext:a,retryLane:1073741824},a=br(18,null,null,0),a.stateNode=r,a.return=e,e.child=a,ar=e,lr=null,!0):!1;default:return!1}}function Qd(e){return(e.mode&1)!==0&&(e.flags&128)===0}function Yd(e){if(Zt){var r=lr;if(r){var a=r;if(!bh(e,r)){if(Qd(e))throw Error(i(418));r=Yr(a.nextSibling);var h=ar;r&&bh(e,r)?wh(h,a):(e.flags=e.flags&-4097|2,Zt=!1,ar=e)}}else{if(Qd(e))throw Error(i(418));e.flags=e.flags&-4097|2,Zt=!1,ar=e}}}function Ch(e){for(e=e.r Line truncated
Error generating stack: `+E.message+`
`+E.stack}return{value:e,source:r,stack:y,digest:null}}function yf(e,r,a){return{value:e,source:null,stack:a??null,digest:r??null}}function _f(e,r){try{console.error(r.value)}catch(a){setTimeout(function(){throw a})}}var qv=typeof WeakMap=="function"?WeakMap:Map;function ip(e,r,a){a=bi(-1,a),a.tag=3,a.payload={element:null};var h=r.value;return a.callback=function(){Bc||(Bc=!0,Mf=h),_f(e,r)},a}function op(e,r,a){a=bi(-1,a),a.tag=3;var h=e.type.getDerivedStateFromError;if(typeof h=="function"){var y=r.value;a.payload=function(){return h(y)},a.callback=function(){_f(e,r)}}var E=e.stateNode;return E!==null&&typeof E.componentDidCatch=="function"&&(a.callback=function(){_f(e,r),typeof h!="function"&&(ao===null?ao=new Set([this]):ao.add(this));var I=r.stack;this.componentDidCatch(r.value,{componentStack:I!==null?I:""})}),a}function sp(e,r,a){var h=e.pingCache;if(h===null){h=e.pingCache=new qv;var y=new Set;h.set(r,y)}else y=h.get(r),y===void 0&&(y=new Set,h.set(r,y));y.has(a)||(y.add(a),e=sy.bind(null,e,r,a),r.then(e,e))}function ap(e){do{var r;if((r=e.tag===13)&&(r=e.memoizedState,r=r!==null?r.dehydrated!==null:!0),r)return e;e=e.return}while(e!==null);return null}function lp(e,r,a,h,y){return(e.mode&1)===0?(e===r?e.flags|=65536:(e.flags|=128,a.flags|=131072,a.flags&=-52805,a.tag===1&&(a.alternate===null?a.tag=17:(r=bi(-1,1),r.tag=2,oo(a,r,1))),a.lanes|=1),e):(e.flags|=65536,e.lanes=y,e)}var Gv=F.ReactCurrentOwner,qn=!1;function Mn(e,r,a,h){r.child=e===null?Bh(r,null,a,h):js(r,e.child,a,h)}function cp(e,r,a,h,y){a=a.render;var E=r.ref;return Hs(r,y),h=ff(e,r,a,h,E,y),a=hf(),e!==null&&!qn?(r.updateQueue=e.updateQueue,r.flags&=-2053,e.lanes&=~y,Ci(e,r,y)):(Zt&&a&&$d(r),r.flags|=1,Mn(e,r,h,y),r.child)}function up(e,r,a,h,y){if(e===null){var E=a.type;return typeof E=="function"&&!Uf(E)&&E.defaultProps===void 0&&a.compare===null&&a.defaultProps===void 0?(r.tag=15,r.type=E,dp(e,r,E,h,y)):(e=Fc(a.type,null,h,r,r.mode,y),e.ref=r.ref,e.return=r,r.child=e)}if(E=e.child,(e.lanes&y)===0){var I=E.memoizedProps;if(a=a.compare,a=a!==null?a:$r,a(I,h)&&e.ref===r.ref)return Ci(e,r,y)}return r.flags|=1,e=fo(E,h),e.ref=r.ref,e.return=r,r.child=e}function dp(e,r,a,h,y){if(e!==null){var E=e.memoizedProps;if($r(E,h)&&e.ref===r.ref)if(qn=!1,r.pendingProps=h=E,(e.lanes&y)!==0)(e.flags&131072)!==0&&(qn=!0);else return r.lanes=e.lanes,Ci(e,r,y)}return wf(e,r,a,h,y)}function fp(e,r,a){var h=r.pendingProps,y=h.children,E=e!==null?e.memoizedState:null;if(h.mode==="hidden")if((r.mode&1)===0)r.memoizedState={baseLanes:0,cachePool:null,transitions:null},Mt(Ws,cr),cr|=a;else{if((a&1073741824)===0)return e=E!==null?E.baseLanes|a:a,r.lanes=r.childLanes=1073741824,r.memoizedState={baseLanes:e,cachePool:null,transitions:null},r.updateQueue=null,Mt(Ws,cr),cr|=e,null;r.memoizedState={baseLanes:0,cachePool:null,transitions:null},h=E!==null?E.baseLanes:a,Mt(Ws,cr),cr|=h}else E!==null?(h=E.baseLanes|a,r.memoizedState=null):h=a,Mt(Ws,cr),cr|=h;return Mn(e,r,y,a),r.child}function hp(e,r){var a=r.ref;(e===null&&a!==null||e!==null&&e.ref!==a)&&(r.flags|=512,r.flags|=2097152)}function wf(e,r,a,h,y){var E=Wn(a)?Fo:Sn.current;return E=Ls(r,E),Hs(r,y),a=ff(e,r,a,h,E,y),h=hf(),e!==null&&!qn?(r.updateQueue=e.updateQueue,r.flags&=-2053,e.lanes&=~y,Ci(e,r,y)):(Zt&&h&&$d(r),r.flags|=1,Mn(e,r,a,y),r.child)}function pp(e,r,a,h,y){if(Wn(a)){var E=!0;oc(r)}else E=!1;if(Hs(r,y),r.stateNode===null)bc(e,r),np(r,a,h),vf(r,a,h,y),h=!0;else if(e===null){var I=r.stateNode,Y=r.memoizedProps;I.props=Y;var te=I.context,fe=a.contextType;typeof fe=="object"&&fe!==null?fe=yr(fe):(fe=Wn(a)?Fo:Sn.current,fe=Ls(r,fe));var be=a.getDerivedStateFromProps,Ee=typeof be=="function"||typeof I.getSnapshotBeforeUpdate=="function";Ee||typeof I.UNSAFE_componentWillReceiveProps!="function"&&typeof I.componentWillReceiveProps!="function"||(Y!==h||te!==fe)&&rp(r,I,h,fe),io=!1;var _e=r.memoizedState;I.state=_e,pc(r,h,I,y),te=r.memoizedState,Y!==h||_e!==te||Zn.current||io?(typeof be=="function"&&(Af(r,a,be,h),te=r.memoizedState),(Y=io||tp(r,a,Y,h,_e,te,fe))?(Ee||typeof I.UNSAFE_componentWillMount!="function"&&typeof I.componentWillMount!="function"||(typeof I.componentWillMount=="function"&&I.componentWillMount(),typeof I.UNSAFE_componentWillMount=="function"&&I.UNSAFE_componentWillMount()),typeof I.componentDidMount=="function"&&(r.flags|=4194308)):(typeof I.componentDidMount=="function"&&(r.flags|=4194308),r.memoizedProps=h,r.memoizedState=te),I.props=h,I.state=te,I.context=fe,h=Y):(typeof I.componentDidMount=="function"&&(r.flags|=4194308),h=!1)}else{I=r.stateNode,Th(e,r),Y=r.memoizedProps,fe=r.type===r.elementType?Y:Fr(r.type,Y),I.props=fe,Ee=r.pendingProps,_e=I.context,te=a.contextType,typeof te=="object"&&te!==null?te=yr(te):(te=Wn(a)?Fo:Sn.current,te=Ls(r,te));var Me=a.getDerivedStateFromProps;(be=typeof Me=="function"||typeof I.getSnapshotBeforeUpdate=="function")||typeof I.UNSAFE_componentWillReceiveProps!="function"&&typeof I.componentWillReceiveProps!="function"||(Y!==Ee||_e!==te)&&rp(r,I, Line truncated
`)}function $s(n,s,i){const l=Math.floor(Date.now()/1e3);return{id:-Date.now(),type:"PRIV",conversation_key:n,text:s,sender_timestamp:l,received_at:l,paths:null,txt_type:0,signature:null,outgoing:i,acked:1}}function Ly(n){const s=R.useRef(null),i=R.useRef(null),l=R.useCallback(()=>{i.current!==null&&(clearInterval(i.current),i.current=null),s.current=null},[]),c=R.useCallback(async()=>{const p=s.current;if(!p)return;let d=null,g=null;for(let m=0;m<2;m++)try{d=await it.requestTelemetry(p.conversationId,"");break}catch(x){g=x instanceof Error?x:new Error("Unknown error"),m===0&&await new Promise(A=>setTimeout(A,2e3))}if(d){const m=$s(p.conversationId,Fy(p,d),!1);n(x=>[...x,m])}else{const m=$s(p.conversationId,`Duty cycle poll failed after retry: ${(g==null?void 0:g.message)??"Unknown error"}`,!1);n(x=>[...x,m])}},[n]),u=R.useCallback(async(p,d)=>{const g=p.trim().toLowerCase();if(g==="dutycycle_start"){l();let m=null,x=null;for(let k=0;k<2;k++)try{m=await it.requestTelemetry(d,"");break}catch(N){x=N instanceof Error?N:new Error("Unknown error"),k===0&&await new Promise(C=>setTimeout(C,2e3))}if(!m){const k=$s(d,`Failed to start duty cycle tracking after retry: ${(x==null?void 0:x.message)??"Unknown error"}`,!1);return n(N=>[...N,k]),!0}const A=Math.floor(Date.now()/1e3);s.current={startTime:A,uptime:m.uptime_seconds,txAirtime:m.airtime_seconds,rxAirtime:m.rx_airtime_seconds,sentFlood:m.sent_flood,sentDirect:m.sent_direct,recvFlood:m.recv_flood,recvDirect:m.recv_direct,conversationId:d};const w=$s(d,`Airtime/duty cycle statistics gathering begins at ${A}. Logs will follow every 5 minutes. To stop, run dutycycle_stop or navigate away from this conversation.`,!1);return n(k=>[...k,w]),i.current=window.setInterval(c,Ry),!0}if(g==="dutycycle_stop"){if(s.current&&s.current.conversationId===d){await c(),l();const m=$s(d,"Airtime/duty cycle statistics gathering stopped.",!1);n(x=>[...x,m])}else{const m=$s(d,"Duty cycle tracking is not active.",!1);n(x=>[...x,m])}return!0}return!1},[n,l,c]);return R.useEffect(()=>()=>{i.current!==null&&clearInterval(i.current)},[]),{handleAirtimeCommand:u,stopTracking:l}}function ru(n){if(n<60)return`${n}s`;const s=Math.floor(n/86400),i=Math.floor(n%86400/3600),l=Math.floor(n%3600/60);return s>0?i>0&&l>0?`${s}d${i}h${l}m`:i>0?`${s}d${i}h`:l>0?`${s}d${l}m`:`${s}d`:i>0?l>0?`${i}h${l}m`:`${i}h`:`${l}m`}function My(n){return["Telemetry",`Battery Voltage: ${n.battery_volts.toFixed(3)}V`,`Uptime: ${ru(n.uptime_seconds)}`,`TX Airtime: ${ru(n.airtime_seconds)}`,`RX Airtime: ${ru(n.rx_airtime_seconds)}`,"",`Noise Floor: ${n.noise_floor_dbm} dBm`,`Last RSSI: ${n.last_rssi_dbm} dBm`,`Last SNR: ${n.last_snr_db.toFixed(1)} dB`,"",`Packets: ${n.packets_received.toLocaleString()} rx / ${n.packets_sent.toLocaleString()} tx`,`Flood: ${n.recv_flood.toLocaleString()} rx / ${n.sent_flood.toLocaleString()} tx`,`Direct: ${n.recv_direct.toLocaleString()} rx / ${n.sent_direct.toLocaleString()} tx`,`Duplicates: ${n.flood_dups.toLocaleString()} flood / ${n.direct_dups.toLocaleString()} direct`,"",`TX Queue: ${n.tx_queue_len}`,`Debug Flags: ${n.full_events}`].join(`
`)}function Iy(n){if(n.length===0)return`Neighbors
No neighbors reported`;const s=[...n].sort((l,c)=>c.snr-l.snr),i=[`Neighbors (${s.length})`];for(const l of s){const c=l.name||l.pubkey_prefix,u=l.snr>=0?`+${l.snr.toFixed(1)}`:l.snr.toFixed(1);i.push(`${c}, ${u} dB [${ru(l.last_heard_seconds)} ago]`)}return i.join(`
`)}function Oy(n){if(n.length===0)return`ACL
No ACL entries`;const s=[`ACL (${n.length})`];for(const i of n){const l=i.name||i.pubkey_prefix;s.push(`${l}: ${i.permission_name}`)}return s.join(`
`)}function qo(n,s,i,l=0){const c=Math.floor(Date.now()/1e3);return{id:-Date.now()-l,type:"PRIV",conversation_key:n,text:s,sender_timestamp:c,received_at:c,paths:null,txt_type:0,signature:null,outgoing:i,acked:1}}function jy(n,s,i){const[l,c]=R.useState(!1),{handleAirtimeCommand:u,stopTracking:p}=Ly(i);R.useEffect(()=>{c(!1),p()},[n==null?void 0:n.id,p]);const d=R.useMemo(()=>{if(!n||n.type!=="contact")return!1;const x=s.find(A=>A.public_key===n.id);return(x==null?void 0:x.type)===id},[n,s]),g=R.useCallback(async x=>{if(!(!n||n.type!=="contact")&&d)try{const A=await it.requestTelemetry(n.id,x),w=qo(n.id,My(A),!1,0),k=qo(n.id,Iy(A.neighbors),!1,1),N=qo(n.id,Oy(A.acl),!1,2);i(C=>[...C,w,k,N]),c(!0)}catch(A){const w=qo(n.id,`Telemetry request failed: ${A instanceof Error?A.message:"Unknown error"}`,!1,0);i(k=>[...k,w])}},[n,d,i]),m=R.useCallback(async x=>{if(!n||n.type!=="contact"||!d||!l||await u(x,n.id))return;const w=qo(n.id,`> ${x}`,!0,0);i(k=>[...k,w]);try{const k=await it.sendRepeaterCommand(n.id,x),N=qo(n.id,k.response,!1,1);k.sender_timestamp&&(N.sender_timestamp=k.sender_timestamp),i(C=>[...C,N])}catch(k){const N=qo(n.id,`Command failed: ${k instanceof Error?k.message:"Unknown error"}`,!1,1);i(C=>[...C,N])}},[n,d,l,i,u]);return{repeaterLoggedIn:l,activeContactIsRepeater:d,handleTelemetryRequest:g,handleRepeaterCommand:m}}const vx="remoteterm-lastMessageTime",yx="remoteterm-sortOrder";let $u={};function om(n){$u={...n}}function sm(){return{...$u}}function n0(n,s){return $u[n]=s,{...$u}}function jr(n,s){return`${n}-${s}`}function zy(){try{const n=localStorage.getItem(vx);return n?JSON.parse(n):{}}catch{return{}}}function Hy(){try{return localStorage.getItem(yx)==="alpha"?"alpha":"recent"}catch{return"recent"}}function am(){try{localStorage.removeItem(vx),localStorage.removeItem(yx)}catch{}}function lm(n,s){if(!s)return!1;const i=s.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");return new RegExp(`@\\[${i}\\]`,"i").test(n)}function Vy(n,s,i,l=null){const[c,u]=R.useState({}),[p,d]=R.useState({}),[g,m]=R.useState(sm),x=R.useRef(l);R.useEffect(()=>{x.current=l},[l]);const A=R.useRef(new Set),w=R.useRef(new Set);R.useEffect(()=>{const B=n.filter(F=>!A.current.has(F.key)),S=s.filter(F=>F.public_key&&!w.current.has(F.public_key));if(B.length===0&&S.length===0)return;B.forEach(F=>A.current.add(F.key)),S.forEach(F=>w.current.add(F.public_key)),(async()=>{const F=[...B.map(M=>({type:"CHAN",conversation_key:M.key})),...S.map(M=>({type:"PRIV",conversation_key:M.public_key}))];if(F.length!==0)try{const H={};for(let Z=0;Z<F.length;Z+=200){const Q=F.slice(Z,Z+200),J=await it.getMessagesBulk(Q,j0);Object.assign(H,J)}const V={},j={},ee={};for(const Z of B){const Q=H[`CHAN:${Z.key}`]||[];if(Q.length>0){const J=jr("channel",Z.key),$=Z.last_read_at||0,oe=Q.filter(G=>!G.outgoing&&G.received_at>$);oe.length>0&&(V[J]=oe.length,oe.some(G=>lm(G.text,x.current))&&(j[J]=!0));const me=Math.max(...Q.map(G=>G.received_at));ee[J]=me,n0(J,me)}}for(const Z of S){const Q=H[`PRIV:${Z.public_key}`]||[];if(Q.length>0){const J=jr("contact",Z.public_key),$=Z.last_read_at||0,oe=Q.filter(G=>!G.outgoing&&G.received_at>$);oe.length>0&&(V[J]=oe.length,oe.some(G=>lm(G.text,x.current))&&(j[J]=!0));const me=Math.max(...Q.map(G=>G.received_at));ee[J]=me,n0(J,me)}}Object.keys(V).length>0&&u(Z=>({...Z,...V})),Object.keys(j).length>0&&d(Z=>({...Z,...j})),m(sm())}catch(M){console.error("Failed to fetch messages bulk:",M)}})()},[n,s]),R.useEffect(()=>{if(i&&i.type!=="raw"&&i.type!=="map"){const B=jr(i.type,i.id);u(S=>{if(S[B]){const T={...S};return delete T[B],T}return S}),d(S=>{if(S[B]){const T={...S};return delete T[B],T}return S}),i.type==="channel"?it.markChannelRead(i.id).catch(S=>{console.error("Failed to mark channel as read on server:",S)}):i.type==="contact"&&it.markContactRead(i.id).catch(S=>{console.error("Failed to mark contact as read on server:",S)})}},[i]);const k=R.useCallback((B,S)=>{u(T=>({...T,[B]:(T[B]||0)+1})),S&&d(T=>({...T,[B]:!0}))},[]),N=R.useCallback(()=>{u({}),d({}),it.markAllRead().catch(B=>{console.error("Failed to mark all as read on server:",B)})},[]),C=R.useCallback(B=>{if(B.type==="raw"||B.type==="map")return;const S=jr(B.type,B.id);u(T=>{if(T[S]){const F={...T};return delete F[S],F}return T}),d(T=>{if(T[S]){const F={...T};return delete F[S],F}return T}),B.type==="channel"?it.markChannelRead(B.id).catch(T=>{console.error("Failed to mark channel as read on server:",T)}):B.type==="contact"&&it.markContactRead(B.id).catch(T=>{console.error("Failed to mark contact as read on server:",T)})},[]),b=R.useCallback(B=>{let S=null;if(B.type==="CHAN"&&B.conversation_key?S=jr("channel",B.conversation_key):B.type==="PRIV"&&B.conversation_key&&(S=jr("contact",B.conversation_key)),S){const T=B.received_at||Math.floor(Date.now()/1e3),F=n0(S,T);m(F)}},[]);return{unreadCounts:c,mentions:p,lastMessageTimes:g,incrementUnread:k,markAllRead:N,markConversationRead:C,trackNewMessage:b}}var z0=Ax();const _x=aa(z0);function Uy(n){if(typeof document>"u")retur Line truncated
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const A_=n=>n.replace(/([a-z0-9])([A-Z])/g,"$1-$2").toLowerCase(),v_=n=>n.replace(/^([A-Z])|[\s-_]+(\w)/g,(s,i,l)=>l?l.toUpperCase():i.toLowerCase()),dm=n=>{const s=v_(n);return s.charAt(0).toUpperCase()+s.slice(1)},wx=(...n)=>n.filter((s,i,l)=>!!s&&s.trim()!==""&&l.indexOf(s)===i).join(" ").trim(),y_=n=>{for(const s in n)if(s.startsWith("aria-")||s==="role"||s==="title")return!0};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/var __={xmlns:"http://www.w3.org/2000/svg",width:24,height:24,viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:2,strokeLinecap:"round",strokeLinejoin:"round"};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const w_=R.forwardRef(({color:n="currentColor",size:s=24,strokeWidth:i=2,absoluteStrokeWidth:l,className:c="",children:u,iconNode:p,...d},g)=>R.createElement("svg",{ref:g,...__,width:s,height:s,stroke:n,strokeWidth:l?Number(i)*24/Number(s):i,className:wx("lucide",c),...!u&&!y_(d)&&{"aria-hidden":"true"},...d},[...p.map(([m,x])=>R.createElement(m,x)),...Array.isArray(u)?u:[u]]));/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const H0=(n,s)=>{const i=R.forwardRef(({className:l,...c},u)=>R.createElement(w_,{ref:u,iconNode:s,className:wx(`lucide-${A_(dm(n))}`,`lucide-${n}`,l),...c}));return i.displayName=dm(n),i};/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const b_=[["path",{d:"M20 6 9 17l-5-5",key:"1gmf2c"}]],C_=H0("check",b_);/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const E_=[["path",{d:"M4 5h16",key:"1tepv9"}],["path",{d:"M4 12h16",key:"1lakjw"}],["path",{d:"M4 19h16",key:"1djgab"}]],k_=H0("menu",E_);/**
* @license lucide-react v0.562.0 - ISC
*
* This source code is licensed under the ISC license.
* See the LICENSE file in the root directory of this source tree.
*/const S_=[["path",{d:"M18 6 6 18",key:"1bl5f8"}],["path",{d:"m6 6 12 12",key:"d8bk6v"}]],bx=H0("x",S_);function B_({health:n,config:s,onSettingsClick:i,onMenuClick:l}){const c=(n==null?void 0:n.radio_connected)??!1,[u,p]=R.useState(!1),d=async()=>{p(!0);try{const g=await it.reconnectRadio();g.connected&&vt.success("Reconnected",{description:g.message})}catch(g){vt.error("Reconnection failed",{description:g instanceof Error?g.message:"Check radio connection and power"})}finally{p(!1)}};return _.jsxs("div",{className:"flex items-center gap-4 px-4 py-2 bg-[#252525] border-b border-[#333] text-xs",children:[l&&_.jsx("button",{onClick:l,className:"md:hidden p-1 bg-transparent border-none text-[#e0e0e0] cursor-pointer","aria-label":"Open menu",children:_.jsx(k_,{className:"h-5 w-5"})}),_.jsx("h1",{className:"text-base font-semibold mr-auto",children:"RemoteTerm"}),_.jsxs("div",{className:"flex items-center gap-1 text-[#888]",children:[_.jsx("div",{className:`w-2 h-2 rounded-full ${c?"bg-[#4caf50]":"bg-[#666]"}`}),_.jsx("span",{className:"hidden lg:inline text-[#e0e0e0]",children:c?"Connected":"Disconnected"})]}),s&&_.jsxs("div",{className:"hidden lg:flex items-center gap-2 text-[#888]",children:[_.jsx("span",{className:"text-[#e0e0e0]",children:s.name||"Unnamed"}),_.jsx("span",{className:"font-mono text-[#888] cursor-pointer hover:text-[#4a9eff]",onClick:()=>{navigator.clipboard.writeText(s.public_key),vt.success("Public key copied!")},title:"Click to copy public key",children:s.public_key.toLowerCase()})]}),!c&&_.jsx("button",{onClick:d,disabled:u,className:"px-3 py-1 bg-[#4a3000] border border-[#6b4500] text-[#ffa500] rounded text-xs cursor-pointer hover:bg-[#5a3a00] disabled:opacity-50 disabled:cursor-not-allowed",children:u?"Reconnecting...":"Reconnect"}),_.jsxs("button",{onClick:i,className:"px-3 py-1 bg-[#333] border border-[#444] text-[#e0e0e0] rounded text-xs cursor-pointer hover:bg-[#444]",children:[_.jsx("span",{role:"img","aria-label":"Settings",children:"🔧"})," ","Radio & Config"]})]})}const P_=12;function T_(n){return n.slice(0,P_)}function Di(n,s){return n||T_(s)}const na=2,D_={text:"🛜",background:"#444444",textColor:"#ffffff"};function R_(n){let s=0;for(let i=0;i<n.length;i++){const l=n.charCodeAt(i);s=(s<<5)-s+l,s=s&s}return Math.abs(s)}const N_=/[\u{1F1E0}-\u{1F1FF}]{2}|[\u{1F300}-\u{1F9FF}]|[\u{2600}-\u{26FF}]|[\u{2700}-\u{27BF}]|[\u{1F600}-\u{1F64F}]|[\u{1F680}-\u{1F6FF}]/u;function F_(n,s){if(!n)return s.slice(0,2).toUpperCase();const i=n.match(N_);if(i)return i[0];const l=n.match(/[a-zA-Z]/g);if(!l||l.length===0)return s.slice(0,2).toUpperCase();const c=n.indexOf(" ");if(c!==-1){const u=l[0],p=n.slice(c+1).match(/[a-zA-Z]/);if(p)return(u+p[0]).toUpperCase()}return l[0].toUpperCase()}function L_(n){const s=R_(n),i=s%360,l=50+(s>>8)%30,c=35+(s>>16)%20,u=`hsl(${i}, ${l}%, ${c}%)`,p=c<45?"#ffffff":"#000000";return{background:u,text:p}}function M_(n,s,i){if(i===na)return D_;const l=F_(n,s),c=L_(s);return{text:l,background:c.background,textColor:c.text}}function y0({name:n,publicKey:s,size:i=28,contactType:l}){const c=M_(n,s,l);return _.jsx("div",{className:"flex items-center justify-center rounded-full font-semibold flex-shrink-0 select-none",style:{backgroundColor:c.background,color:c.textColor,width:i,height:i,fontSize:i*.45},children:c.text})}const Cx="remoteterm-favorites";function ts(n,s,i){return n.some(l=>l.type===s&&l.id===i)}function I_(){try{const n=localStorage.getItem(Cx);return n?JSON.parse(n):[]}catch{return[]}}function fm(){try{localStorage.removeItem(Cx)}catch{}}function Ex(n){var s,i,l="";if(typeof n=="string"||typeof n=="number")l+=n;else if(typeof n=="object")if(Array.isArray(n)){var c=n.length;for(s=0;s<c;s++)n[s]&&(i=Ex(n[s]))&&(l&&(l+=" "),l+=i)}else for(i in n)n[i]&&(l&&(l+=" "),l+=i);return l}function kx(){for(var n,s,i=0,l="",c=arguments.length;i<c;i++)(n=arguments[i])&&(s=Ex(n))&&(l&&(l+=" "),l+=s);return l}const O_=(n,s)=>{const i=new Array(n.length+s.length);for(let l=0;l<n.length;l++)i[l]=n[l];for(let l=0;l<s.length;l++)i[n.length+l]=s[l];return i},j_=(n,s)=>({classGroupId:n,validator:s}),Sx=(n=new Map,s=null,i)=>({nextPart:n,validators:s,classGroupId:i}),Ku="-",hm=[],z_="arbitrary..",H_=n=>{const s=U_(n),{conflictingClassGroups:i,conflictingClassGroupModifiers:l}=n;return{getClassGroupId:p=>{if(p.startsWith("[")&&p.endsWith("]"))return V_(p);const d=p.split(Ku),g=d[0]===""&&d.length>1?1:0;return Bx(d,g,s)},getConflictingClassGroupIds:(p,d)=>{if(d){const g=l[p],m=i[p];return g?m?O_(m,g):g:m||hm}return i[p]||hm}}},Bx=(n,s,i)=>{if(n.length-s===0)return i.classGroupId;const c=n[s],u=i.nextPart.get(c);if(u){const m=Bx(n,s+1,u);if(m)return m}const p=i.validators;if(p===null)return;const d=s===0?n.join(Ku):n.slice(s).join(Ku),g=p.length;for(let m=0;m<g;m++){const x=p[m];if(x.validator(d))return x.classGroupId}},V_=n=>n.slice(1,-1).indexOf(":")===-1?void 0:(()=>{const s=n.slice(1,-1),i=s.indexOf(":"),l=s.slice(0,i);return l?z_+l:void 0})(),U_=n=>{const{theme:s,classLine truncated
.`.concat(Ew,` {
overflow: hidden `).concat(l,`;
padding-right: `).concat(d,"px ").concat(l,`;
}
body[`).concat(ea,`] {
overflow: hidden `).concat(l,`;
overscroll-behavior: contain;
`).concat([s&&"position: relative ".concat(l,";"),i==="margin"&&`
padding-left: `.concat(c,`px;
padding-top: `).concat(u,`px;
padding-right: `).concat(p,`px;
margin-left:0;
margin-top:0;
margin-right: `).concat(d,"px ").concat(l,`;
`),i==="padding"&&"padding-right: ".concat(d,"px ").concat(l,";")].filter(Boolean).join(""),`
}
.`).concat(ou,` {
right: `).concat(d,"px ").concat(l,`;
}
.`).concat(su,` {
margin-right: `).concat(d,"px ").concat(l,`;
}
.`).concat(ou," .").concat(ou,` {
right: 0 `).concat(l,`;
}
.`).concat(su," .").concat(su,` {
margin-right: 0 `).concat(l,`;
}
body[`).concat(ea,`] {
`).concat(kw,": ").concat(d,`px;
}
`)},Tm=function(){var n=parseInt(document.body.getAttribute(ea)||"0",10);return isFinite(n)?n:0},Ww=function(){R.useEffect(function(){return document.body.setAttribute(ea,(Tm()+1).toString()),function(){var n=Tm()-1;n<=0?document.body.removeAttribute(ea):document.body.setAttribute(ea,n.toString())}},[])},qw=function(n){var s=n.noRelative,i=n.noImportant,l=n.gapMode,c=l===void 0?"margin":l;Ww();var u=R.useMemo(function(){return Vw(c)},[c]);return R.createElement(Uw,{styles:Zw(u,!s,c,i?"":"!important")})},b0=!1;if(typeof window<"u")try{var Qc=Object.defineProperty({},"passive",{get:function(){return b0=!0,!0}});window.addEventListener("test",Qc,Qc),window.removeEventListener("test",Qc,Qc)}catch{b0=!1}var Qs=b0?{passive:!1}:!1,Gw=function(n){return n.tagName==="TEXTAREA"},Qx=function(n,s){if(!(n instanceof Element))return!1;var i=window.getComputedStyle(n);return i[s]!=="hidden"&&!(i.overflowY===i.overflowX&&!Gw(n)&&i[s]==="visible")},$w=function(n){return Qx(n,"overflowY")},Kw=function(n){return Qx(n,"overflowX")},Dm=function(n,s){var i=s.ownerDocument,l=s;do{typeof ShadowRoot<"u"&&l instanceof ShadowRoot&&(l=l.host);var c=Yx(n,l);if(c){var u=Xx(n,l),p=u[1],d=u[2];if(p>d)return!0}l=l.parentNode}while(l&&l!==i.body);return!1},Qw=function(n){var s=n.scrollTop,i=n.scrollHeight,l=n.clientHeight;return[s,i,l]},Yw=function(n){var s=n.scrollLeft,i=n.scrollWidth,l=n.clientWidth;return[s,i,l]},Yx=function(n,s){return n==="v"?$w(s):Kw(s)},Xx=function(n,s){return n==="v"?Qw(s):Yw(s)},Xw=function(n,s){return n==="h"&&s==="rtl"?-1:1},Jw=function(n,s,i,l,c){var u=Xw(n,window.getComputedStyle(s).direction),p=u*l,d=i.target,g=s.contains(d),m=!1,x=p>0,A=0,w=0;do{if(!d)break;var k=Xx(n,d),N=k[0],C=k[1],b=k[2],B=C-b-u*N;(N||B)&&Yx(n,d)&&(A+=B,w+=N);var S=d.parentNode;d=S&&S.nodeType===Node.DOCUMENT_FRAGMENT_NODE?S.host:S}while(!g&&d!==document.body||g&&(s.contains(d)||s===d));return(x&&Math.abs(A)<1||!x&&Math.abs(w)<1)&&(m=!0),m},Yc=function(n){return"changedTouches"in n?[n.changedTouches[0].clientX,n.changedTouches[0].clientY]:[0,0]},Rm=function(n){return[n.deltaX,n.deltaY]},Nm=function(n){return n&&"current"in n?n.current:n},e2=function(n,s){return n[0]===s[0]&&n[1]===s[1]},t2=function(n){return`
.block-interactivity-`.concat(n,` {pointer-events: none;}
.allow-interactivity-`).concat(n,` {pointer-events: all;}
`)},n2=0,Ys=[];function r2(n){var s=R.useRef([]),i=R.useRef([0,0]),l=R.useRef(),c=R.useState(n2++)[0],u=R.useState(Kx)[0],p=R.useRef(n);R.useEffect(function(){p.current=n},[n]),R.useEffect(function(){if(n.inert){document.body.classList.add("block-interactivity-".concat(c));var C=Cw([n.lockRef.current],(n.shards||[]).map(Nm),!0).filter(Boolean);return C.forEach(function(b){return b.classList.add("allow-interactivity-".concat(c))}),function(){document.body.classList.remove("block-interactivity-".concat(c)),C.forEach(function(b){return b.classList.remove("allow-interactivity-".concat(c))})}}},[n.inert,n.lockRef.current,n.shards]);var d=R.useCallback(function(C,b){if("touches"in C&&C.touches.length===2||C.type==="wheel"&&C.ctrlKey)return!p.current.allowPinchZoom;var B=Yc(C),S=i.current,T="deltaX"in C?C.deltaX:S[0]-B[0],F="deltaY"in C?C.deltaY:S[1]-B[1],M,H=C.target,V=Math.abs(T)>Math.abs(F)?"h":"v";if("touches"in C&&V==="h"&&H.type==="range")return!1;var j=window.getSelection(),ee=j&&j.anchorNode,Z=ee?ee===H||ee.contains(H):!1;if(Z)return!1;var Q=Dm(V,H);if(!Q)return!0;if(Q?M=V:(M=V==="v"?"h":"v",Q=Dm(V,H)),!Q)return!1;if(!l.current&&"changedTouches"in C&&(T||F)&&(l.current=M),!M)return!0;var J=l.current||M;return Jw(J,b,C,J==="h"?T:F)},[]),g=R.useCallback(function(C){var b=C;if(!(!Ys.length||Ys[Ys.length-1]!==u)){var B="deltaY"in b?Rm(b):Yc(b),S=s.current.filter(function(M){return M.name===b.type&&(M.target===b.target||b.target===M.shadowParent)&&e2(M.delta,B)})[0];if(S&&S.should){b.cancelable&&b.preventDefault();return}if(!S){var T=(p.current.shards||[]).map(Nm).filter(Boolean).filter(function(M){return M.contains(b.target)}),F=T.length>0?d(b,T[0]):!p.current.noIsolation;F&&b.cancelable&&b.preventDefault()}}},[]),m=R.useCallback(function(C,b,B,S){var T={name:C,delta:b,target:B,should:S,shadowParent:i2(B)};s.current.push(T),setTimeout(function(){s.current=s.current.filter(function(F){return F!==T})},1)},[]),x=R.useCallback(function(C){i.current=Yc(C),l.current=void 0},[]),A=R.useCallback(function(C){m(C.type,Rm(C),C.target,d(C,n.lockRef.current))},[]),w=R.useCallback(function(C){m(C.type,Yc(C),C.target,d(C,n.lockRef.current))},[]);R.useEffect(function(){return Ys.push(u),n.setCallbacks({onScrollCapture:A,onWheelCapture:A,onTouchMoveCapture:w}),document.addEventListener("wheel",g,Qs),document.addEventListener("touchmove",g,Qs),document.addEventListener("touchstart",x,Qs),function(){Ys=Ys.filter(function(C){return C!==u}),document.removeEventListener("wheel",g,Qs),document.removeEventListener("touchmove",g,Qs),document.removeEventListener("touchstart",x,Qs)}},[]);var k=n.removeScrollBar,N=n.inert;return R.createElement(R.Fragment,null,N?R.createElement(u,{styles:t2(c)}):null,k?R.createElement(qw,{noRelative:n.noRelative,gapMode:n.gapMode}):null)}function i2(n){for(var s=null;n!==null;)n instanceof ShadowRoot&&(s=n.host,n=n.host),n=n.parentNode;return s}const o2=Nw($x,r2);var Jx=R.forwardRef(function(n,s){return R.createElement(sd,ii({},n,{ref:s,sideCar:o2}))});Jx.classNames=sd.classNames;var s2=function(n){if(typeof document>"u")return null;var s=Array.isArray(n)?n[0]:n;return s.ownerDocument.body},Xs=new WeakMap,Xc=new WeakMap,Jc={},d0=0,eA=function(n){return n&&(n.host||eA(n.parentNode))},a2=function(n,s){return s.map(function(i){if(n.contains(i))return i;var l=eA(i);return l&&n.contains(l)?l:(console.error("aria-hidden",i,"in not contained inside",n,". Doing nothing"),null)}).filter(function(i){return!!i})},l2=function(n,s,i,l){var c=a2(s,Array.isArray(n)?n:[n]);Jc[i]||(Jc[i]=new WeakMap);var u=Jc[i],p=[],d=new Set,g=new Set(c),m=function(A){!A||d.has(A)||(d.add(A),m(A.parentNode))};c.forEach(m);var x=function(A){!A||g.has(A)||Array.prototype.forEach.call(A.children,function(w){if(d.has(w))x(w);else try{var k=w.getAttribute(l),N=k!==null&&k!=="false",C=(Xs.get(w)||0)+1,b=(u.get(w)||0)+1;Xs.set(w,C),u.set(w,b),p.push(w),C===1&&N&&Xc.set(w,!0),b===1&&w.setAttribute(i,"true"),N||w.setAttribute(l,"true")}catch(B){console.error("aria-hidden: cannot operate on ",w,B)}})};return x(s),d.clear(),d0++,function(){p.forEach(function(A){var w=Xs.get(A)-1,k=u.get(A)-1;Xs.set(A,w),u.set(A,k),w||(Xc.has(A)||A.removeAttribute(l),Xc.delete(A)),k||A.removeAttribute(i)}),d0--,d0||(Xs=new WeakMap,Xs=new WeakMap,Xc=new WeakMap,Jc={})}},c2=function(n,s,i){i===void 0&&(i="data-aria-hidden");var l=Array.from(Array.isArray(n)?n:[n]),c=s2(n);return c?(l.push.apply(l,Array.from(c.querySelectorAll("[aria-live], script"))),l2(l,c,i,"aria-hidden")):function(){return null}};function u2(n){const s=d2(n),i=R.forwardRef((l,c)=>{const{children:u,...p}=l,d=R.Children.toArray(u),g=d.find(h2);if(g){const m=g.props.children,x=d.map(A=>A===g?R.Children.count(m)>1?R.Children.only(null):R.isValidElement(m)?m.props.children:null:A);return _.jsx(s,{...p,ref:c,children:R.isValidElement(m)?R.cloneElement(m,void 0,x):null})}return _.jsx(s,{...p,ref:c,children:u})});return i.displayName=`${n}.Slot`,i}function d2(n){const s=R.forwardRef((i,l)=>{const{childr Line truncated
If you want to hide the \`${s.titleName}\`, you can wrap it with our VisuallyHidden component.
For more information, see https://radix-ui.com/primitives/docs/components/${s.docsSlug}`;return R.useEffect(()=>{n&&(document.getElementById(n)||console.error(i))},[i,n]),null},C2="DialogDescriptionWarning",E2=({contentRef:n,descriptionId:s})=>{const l=`Warning: Missing \`Description\` or \`aria-describedby={undefined}\` for {${mA(C2).contentName}}.`;return R.useEffect(()=>{var u;const c=(u=n.current)==null?void 0:u.getAttribute("aria-describedby");s&&c&&(document.getElementById(s)||console.warn(l))},[l,n,s]),null},gA=nA,xA=oA,ld=sA,cd=aA,ud=cA,dd=dA,AA=hA;const $0=gA,k2=xA,vA=R.forwardRef(({className:n,...s},i)=>_.jsx(ld,{ref:i,className:lt("fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",n),...s}));vA.displayName=ld.displayName;const fd=R.forwardRef(({className:n,children:s,...i},l)=>_.jsxs(k2,{children:[_.jsx(vA,{}),_.jsxs(cd,{ref:l,className:lt("fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",n),...i,children:[s,_.jsxs(AA,{className:"absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground",children:[_.jsx(bx,{className:"h-4 w-4"}),_.jsx("span",{className:"sr-only",children:"Close"})]})]})]}));fd.displayName=cd.displayName;const hd=({className:n,...s})=>_.jsx("div",{className:lt("flex flex-col space-y-1.5 text-center sm:text-left",n),...s});hd.displayName="DialogHeader";const K0=({className:n,...s})=>_.jsx("div",{className:lt("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",n),...s});K0.displayName="DialogFooter";const pd=R.forwardRef(({className:n,...s},i)=>_.jsx(ud,{ref:i,className:lt("text-lg font-semibold leading-none tracking-tight",n),...s}));pd.displayName=ud.displayName;const md=R.forwardRef(({className:n,...s},i)=>_.jsx(dd,{ref:i,className:lt("text-sm text-muted-foreground",n),...s}));md.displayName=dd.displayName;function S2(){const n=window.location.hash.slice(1);if(!n)return null;if(n==="raw")return{type:"raw",name:"raw"};if(n==="map")return{type:"map",name:"map"};if(n==="visualizer")return{type:"visualizer",name:"visualizer"};if(n.startsWith("map/focus/")){const c=n.slice(10);return c?{type:"map",name:"map",mapFocusKey:decodeURIComponent(c)}:{type:"map",name:"map"}}const s=n.indexOf("/");if(s===-1)return null;const i=n.slice(0,s),l=decodeURIComponent(n.slice(s+1));return(i==="channel"||i==="contact")&&l?{type:i,name:l}:null}function yA(n){return`#map/focus/${encodeURIComponent(n)}`}function B2(n){if(!n)return"";if(n.type==="raw")return"#raw";if(n.type==="map")return"#map";if(n.type==="visualizer")return"#visualizer";const s=n.type==="channel"&&n.name.startsWith("#")?n.name.slice(1):n.name;return`#${n.type}/${encodeURIComponent(s)}`}function P2(n){const s=B2(n);s!==window.location.hash&&window.history.replaceState(null,"",s||window.location.pathname)}function T2({open:n,onClose:s,paths:i,senderInfo:l,contacts:c,config:u}){const p=i.map(g=>({...g,resolved:H1(g.path,l,c,u)})),d=i.length===1;return _.jsx($0,{open:n,onOpenChange:g=>!g&&s(),children:_.jsxs(fd,{className:"max-w-md max-h-[80vh] flex flex-col",children:[_.jsxs(hd,{children:[_.jsxs(pd,{children:["Message Path",!d&&`s (${i.length})`]}),_.jsx(md,{children:d?_.jsxs(_.Fragment,{children:["This shows ",_.jsx("em",{children:"one route"})," that this message traveled through the mesh network. Routers may be incorrectly identified due to prefix collisions between heard and non-heard router advertisements."]}):_.jsxs(_.Fragment,{children:["This message was received via ",_.jsxs("strong",{children:[i.length," different routes"]}),". Routers may be incorrectly identified due to prefix collisions."]})})]}),_.jsxs("div",{className:"flex-1 overflow-y-auto py-2 space-y-4",children:[p.map((g,m)=>_.jsxs("div",{children:[!d&&_.jsxs("div",{className:"text-xs text-muted-foreground font-medium mb-2 pb-1 border-b border-border",children:["Path ",m+1," — received ",ra(g.received_at)]}),_.jsx(D2,{resolved:g.resolved,senderInfo:l,hideStraightLine:!d})]},m)),!d&&p.length>0&&(()=>{const g=p[0].resolved;return Tt(g.sender.lat,g.sender.lon)&&Tt(g.receiver.lat,g.receiver.lon)?_.jsxs("div",{className:"pt-3 mt-1 border-t border-border",children:[_.jsx("span",{className:"text-sm text-muted-foreground",children:"Straight-line distance: "}),_.jsx("span",{className:"text-sm font-medium",c Line truncated
`).map((K,ce,he)=>_.jsxs("span",{children:[F2(K,d),ce<he.length-1&&_.jsx("br",{})]},ce)),!ne&&_.jsxs(_.Fragment,{children:[_.jsx("span",{className:"text-[10px] text-muted-foreground/50 ml-2",children:ra(j.sender_timestamp||j.received_at)}),!j.outgoing&&j.paths&&j.paths.length>0&&_.jsx(Lm,{paths:j.paths,variant:"inline",onClick:()=>C({paths:j.paths,senderInfo:M(j,Z,J)})})]}),j.outgoing&&(j.acked>0?` ✓${j.acked>1?j.acked:""}`:" ?")]})]})]},j.id)})]}),w&&_.jsx("button",{onClick:S,className:"absolute bottom-4 right-4 w-10 h-10 rounded-full bg-muted hover:bg-accent border border-border flex items-center justify-center shadow-lg transition-opacity",title:"Scroll to bottom",children:_.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",width:"20",height:"20",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",className:"text-muted-foreground",children:_.jsx("polyline",{points:"6 9 12 15 18 9"})})}),N&&_.jsx(T2,{open:!0,onClose:()=>C(null),paths:N.paths,senderInfo:N.senderInfo,contacts:s,config:g??null})]})}const Mm=156,M2=140,I2=156,O2=120,j2=8,z2=R.forwardRef(function({onSend:s,disabled:i,placeholder:l,isRepeaterMode:c,conversationType:u,senderName:p},d){const[g,m]=R.useState(""),[x,A]=R.useState(!1),w=R.useRef(null);R.useImperativeHandle(d,()=>({appendText:M=>{var H;m(V=>V+M),(H=w.current)==null||H.focus()}}));const k=R.useMemo(()=>{if(u==="contact")return{warningAt:M2,dangerAt:Mm,hardLimit:Mm};if(u==="channel"){const M=(p==null?void 0:p.length)??10,H=Math.max(1,I2-M-2);return{warningAt:O2,dangerAt:Math.max(1,H-j2),hardLimit:H}}return null},[u,p]),{limitState:N,warningMessage:C}=R.useMemo(()=>{if(!k)return{limitState:"normal",warningMessage:null};const M=g.length;return M>=k.hardLimit?{limitState:"error",warningMessage:"likely truncated by radio"}:M>=k.dangerAt?{limitState:"danger",warningMessage:"may impact multi-repeater hop delivery"}:M>=k.warningAt?{limitState:"warning",warningMessage:"may impact multi-repeater hop delivery"}:{limitState:"normal",warningMessage:null}},[g.length,k]),b=k?k.hardLimit-g.length:0,B=R.useCallback(async M=>{M.preventDefault();const H=g.trim();if(c){if(x||i)return;A(!0);try{await s(H),m("")}catch(V){console.error("Failed to request telemetry:",V),vt.error("Failed to request telemetry",{description:V instanceof Error?V.message:"Check radio connection"});return}finally{A(!1)}setTimeout(()=>{var V;return(V=w.current)==null?void 0:V.focus()},0)}else{if(!H||x||i)return;A(!0);try{await s(H),m("")}catch(V){console.error("Failed to send message:",V),vt.error("Failed to send message",{description:V instanceof Error?V.message:"Check radio connection"});return}finally{A(!1)}setTimeout(()=>{var V;return(V=w.current)==null?void 0:V.focus()},0)}},[g,x,i,s,c]),S=R.useCallback(M=>{M.key==="Enter"&&!M.shiftKey&&(M.preventDefault(),B(M))},[B]),T=c?!0:g.trim().length>0,F=!c&&k!==null;return _.jsxs("form",{className:"px-4 py-3 border-t border-border flex flex-col gap-1",onSubmit:B,children:[_.jsxs("div",{className:"flex gap-2",children:[_.jsx(en,{ref:w,type:c?"password":"text",autoComplete:c?"off":void 0,value:g,onChange:M=>m(M.target.value),onKeyDown:S,placeholder:l||(c?"Enter password for admin login...":"Type a message..."),disabled:i||x,className:"flex-1 min-w-0"}),_.jsx(_n,{type:"submit",disabled:i||x||!T,className:"flex-shrink-0",children:x?c?"Logging in...":"Sending...":c?g.trim()?"Log in with password":"Log in as guest/use repeater ACLs":"Send"})]}),F&&_.jsxs("div",{className:"flex items-center justify-end gap-2 text-xs",children:[_.jsxs("span",{className:lt("tabular-nums",N==="error"||N==="danger"?"text-red-500 font-medium":N==="warning"?"text-yellow-500":"text-muted-foreground"),children:[g.length,"/",k.hardLimit,b<0&&` (${b})`]}),C&&_.jsxs("span",{className:lt(N==="error"?"text-red-500":"text-yellow-500"),children:["— ",C]})]})]})});function Im(n){const s=H2(n),i=R.forwardRef((l,c)=>{const{children:u,...p}=l,d=R.Children.toArray(u),g=d.find(U2);if(g){const m=g.props.children,x=d.map(A=>A===g?R.Children.count(m)>1?R.Children.only(null):R.isValidElement(m)?m.props.children:null:A);return _.jsx(s,{...p,ref:c,children:R.isValidElement(m)?R.cloneElement(m,void 0,x):null})}return _.jsx(s,{...p,ref:c,children:u})});return i.displayName=`${n}.Slot`,i}function H2(n){const s=R.forwardRef((i,l)=>{const{children:c,...u}=i;if(R.isValidElement(c)){const p=W2(c),d=Z2(u,c.props);return c.type!==R.Fragment&&(d.ref=l?El(l,p):p),R.cloneElement(c,d)}return R.Children.count(c)>1?R.Children.only(null):null});return s.displayName=`${n}.SlotClone`,s}var V2=Symbol("radix.slottable");function U2(n){return R.isValidElement(n)&&typeof n.type=="function"&&"__radixId"in n.type&&n.type.__radixId===V2}function Z2(n,s){const i={...s};for(const l in s){const c=n[l],u=s[l];/^on[A-Z]/.test(l)?c&&u?i[l]=(...d)=>{const g=u(...d);return c(...d),g}:c&&(i[l]=c):l==="style"?i[l]={...c,...u}:l==="className"&&(i[l]=[c,u].filter(Boolean).join(" "))}return{...n,...i}}function Line truncated
(c) 2012 by Cédric Mesnil. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/return(function(l){var c=i,u=c.lib,p=u.WordArray,d=u.Hasher,g=c.algo,m=p.create([0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,7,4,13,1,10,6,15,3,12,0,9,5,2,14,11,8,3,10,14,4,9,15,8,1,2,7,0,6,13,11,5,12,1,9,11,10,0,8,12,4,13,3,7,15,14,5,6,2,4,0,5,9,7,12,2,10,14,1,3,8,11,6,15,13]),x=p.create([5,14,7,0,9,2,11,4,13,6,15,8,1,10,3,12,6,11,3,7,0,13,5,10,14,15,8,12,4,9,1,2,15,5,1,3,7,14,6,9,11,8,12,2,10,0,4,13,8,6,4,1,3,11,15,0,5,12,2,13,9,7,10,14,12,15,10,4,1,5,8,7,6,2,13,14,0,3,9,11]),A=p.create([11,14,15,12,5,8,7,9,11,13,14,15,6,7,9,8,7,6,8,13,11,9,7,15,7,12,15,9,11,7,13,12,11,13,6,7,14,9,13,15,14,8,13,6,5,12,7,5,11,12,14,15,14,15,9,8,9,14,5,6,8,6,5,12,9,15,5,11,6,8,13,12,5,12,13,14,11,8,5,6]),w=p.create([8,9,9,11,13,15,15,5,7,7,8,11,14,14,12,6,9,13,15,7,12,8,9,11,7,7,12,7,6,15,13,11,9,7,15,11,8,6,6,14,12,13,5,14,13,13,7,5,15,5,8,11,14,14,6,14,6,9,12,9,12,5,15,8,8,5,12,9,12,5,14,6,8,13,6,5,15,13,11,11]),k=p.create([0,1518500249,1859775393,2400959708,2840853838]),N=p.create([1352829926,1548603684,1836072691,2053994217,0]),C=g.RIPEMD160=d.extend({_doReset:function(){this._hash=p.create([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(H,V){for(var j=0;j<16;j++){var ee=V+j,Z=H[ee];H[ee]=(Z<<8|Z>>>24)&16711935|(Z<<24|Z>>>8)&4278255360}var Q=this._hash.words,J=k.words,$=N.words,oe=m.words,me=x.words,G=A.words,se=w.words,W,ne,U,D,z,q,K,ce,he,xe;q=W=Q[0],K=ne=Q[1],ce=U=Q[2],he=D=Q[3],xe=z=Q[4];for(var pe,j=0;j<80;j+=1)pe=W+H[V+oe[j]]|0,j<16?pe+=b(ne,U,D)+J[0]:j<32?pe+=B(ne,U,D)+J[1]:j<48?pe+=S(ne,U,D)+J[2]:j<64?pe+=T(ne,U,D)+J[3]:pe+=F(ne,U,D)+J[4],pe=pe|0,pe=M(pe,G[j]),pe=pe+z|0,W=z,z=D,D=M(U,10),U=ne,ne=pe,pe=q+H[V+me[j]]|0,j<16?pe+=F(K,ce,he)+$[0]:j<32?pe+=T(K,ce,he)+$[1]:j<48?pe+=S(K,ce,he)+$[2]:j<64?pe+=B(K,ce,he)+$[3]:pe+=b(K,ce,he)+$[4],pe=pe|0,pe=M(pe,se[j]),pe=pe+xe|0,q=xe,xe=he,he=M(ce,10),ce=K,K=pe;pe=Q[1]+U+he|0,Q[1]=Q[2]+D+xe|0,Q[2]=Q[3]+z+q|0,Q[3]=Q[4]+W+K|0,Q[4]=Q[0]+ne+ce|0,Q[0]=pe},_doFinalize:function(){var H=this._data,V=H.words,j=this._nDataBytes*8,ee=H.sigBytes*8;V[ee>>>5]|=128<<24-ee%32,V[(ee+64>>>9<<4)+14]=(j<<8|j>>>24)&16711935|(j<<24|j>>>8)&4278255360,H.sigBytes=(V.length+1)*4,this._process();for(var Z=this._hash,Q=Z.words,J=0;J<5;J++){var $=Q[J];Q[J]=($<<8|$>>>24)&16711935|($<<24|$>>>8)&4278255360}return Z},clone:function(){var H=d.clone.call(this);return H._hash=this._hash.clone(),H}});function b(H,V,j){return H^V^j}function B(H,V,j){return H&V|~H&j}function S(H,V,j){return(H|~V)^j}function T(H,V,j){return H&j|V&~j}function F(H,V,j){return H^(V|~j)}function M(H,V){return H<<V|H>>>32-V}c.RIPEMD160=d._createHelper(C),c.HmacRIPEMD160=d._createHmacHelper(C)})(),i.RIPEMD160})})(_u)),_u.exports}var wu={exports:{}},Kb=wu.exports,ng;function yd(){return ng||(ng=1,(function(n,s){(function(i,l){n.exports=l(xt())})(Kb,function(i){(function(){var l=i,c=l.lib,u=c.Base,p=l.enc,d=p.Utf8,g=l.algo;g.HMAC=u.extend({init:function(m,x){m=this._hasher=new m.init,typeof x=="string"&&(x=d.parse(x));var A=m.blockSize,w=A*4;x.sigBytes>w&&(x=m.finalize(x)),x.clamp();for(var k=this._oKey=x.clone(),N=this._iKey=x.clone(),C=k.words,b=N.words,B=0;B<A;B++)C[B]^=1549556828,b[B]^=909522486;k.sigBytes=N.sigBytes=w,this.reset()},reset:function(){var m=this._hasher;m.reset(),m.update(this._iKey)},update:function(m){return this._hasher.update(m),this},finalize:function(m){var x=this._hasher,A=x.finalize(m);x.reset();var w=x.finalize(this._oKey.clone().concat(A));return w}})})()})})(wu)),wu.exports}var bu={exports:{}},Qb=bu.exports,rg;function Yb(){return rg||(rg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),Bl(),yd())})(Qb,function(i){return(function(){var l=i,c=l.lib,u=c.Base,p=c.WordArray,d=l.algo,g=d.SHA256,m=d.HMAC,x=d.PBKDF2=u.extend({cfg:u.extend({keySize:128/32,hasher:g,iterations:25e4}),init:function(A){this.cfg=this.cfg.extend(A)},compute:function(A,w){for(var k=this.cfg,N=m.create(k.hasher,A),C=p.create(),b=p.create([1]),B=C.words,S=b.words,T=k.keySize,F=k.iterations;B.length<T;){var M=N.update(w).finalize(b);N.reset();for(var H=M.words,V=H.length,j=M,ee=1;ee<F;ee++){j=N.finalize(j),N.reset();for(var Z=j.words,Q=0;Q<V;Q++)H[Q]^=Z[Q]}C.concat(M),S[0]++}return C.sigBytes=T*4,C}});l.PBKDF2=function(A,w,k){return x.create(k).compute(A,w)}})(),i.PBKDF2})})(bu)),bu.exports}var Cu={exports:{}},Xb=Cu.exports,ig;function vo(){return ig||(ig=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),XA(),yd())})(Xb,function(i){return(function(){var l=i,c=l.lib,u=c.Base,p=c.WordArray,d=l.algo,g=d.MD5,m=d.EvpKDF=u.extend({cfg:u.extend({keySize:128/32,hasher:g,iterations:1}),init:function(x){this.cfg=this.cfg.extend(x)},compute:function(x,A){for(var w,k=this.cfg,N=k.hasher.create(),C=p.create(),b=C.words,B=k.keySize,S=k.iterations;b.length<B;){w&&N.update(w),w=N.update(x).finalize(A),N.reset();for(var T=1;T<S;T++)w=N.finalize(w),N.reset();C.concat(w)}return C.sigBytes=B*4,C}});l.EvpKDF=function(x,A,w){return m.create(w).compute(x,A)}})(),i.EvpKDF})})(Cu)),Cu.exports}var Eu={exports:{}},Jb=Eu.exports,og;Line truncated
* Counter block mode compatible with Dr Brian Gladman fileenc.c
* derived from CryptoJS.mode.CTR
* Jan Hruby jhruby.web@gmail.com
*/return i.mode.CTRGladman=(function(){var l=i.lib.BlockCipherMode.extend();function c(d){if((d>>24&255)===255){var g=d>>16&255,m=d>>8&255,x=d&255;g===255?(g=0,m===255?(m=0,x===255?x=0:++x):++m):++g,d=0,d+=g<<16,d+=m<<8,d+=x}else d+=1<<24;return d}function u(d){return(d[0]=c(d[0]))===0&&(d[1]=c(d[1])),d}var p=l.Encryptor=l.extend({processBlock:function(d,g){var m=this._cipher,x=m.blockSize,A=this._iv,w=this._counter;A&&(w=this._counter=A.slice(0),this._iv=void 0),u(w);var k=w.slice(0);m.encryptBlock(k,0);for(var N=0;N<x;N++)d[g+N]^=k[N]}});return l.Decryptor=p,l})(),i.mode.CTRGladman})})(Bu)),Bu.exports}var Pu={exports:{}},sC=Pu.exports,cg;function aC(){return cg||(cg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(sC,function(i){return i.mode.OFB=(function(){var l=i.lib.BlockCipherMode.extend(),c=l.Encryptor=l.extend({processBlock:function(u,p){var d=this._cipher,g=d.blockSize,m=this._iv,x=this._keystream;m&&(x=this._keystream=m.slice(0),this._iv=void 0),d.encryptBlock(x,0);for(var A=0;A<g;A++)u[p+A]^=x[A]}});return l.Decryptor=c,l})(),i.mode.OFB})})(Pu)),Pu.exports}var Tu={exports:{}},lC=Tu.exports,ug;function cC(){return ug||(ug=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(lC,function(i){return i.mode.ECB=(function(){var l=i.lib.BlockCipherMode.extend();return l.Encryptor=l.extend({processBlock:function(c,u){this._cipher.encryptBlock(c,u)}}),l.Decryptor=l.extend({processBlock:function(c,u){this._cipher.decryptBlock(c,u)}}),l})(),i.mode.ECB})})(Tu)),Tu.exports}var Du={exports:{}},uC=Du.exports,dg;function dC(){return dg||(dg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(uC,function(i){return i.pad.AnsiX923={pad:function(l,c){var u=l.sigBytes,p=c*4,d=p-u%p,g=u+d-1;l.clamp(),l.words[g>>>2]|=d<<24-g%4*8,l.sigBytes+=d},unpad:function(l){var c=l.words[l.sigBytes-1>>>2]&255;l.sigBytes-=c}},i.pad.Ansix923})})(Du)),Du.exports}var Ru={exports:{}},fC=Ru.exports,fg;function hC(){return fg||(fg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(fC,function(i){return i.pad.Iso10126={pad:function(l,c){var u=c*4,p=u-l.sigBytes%u;l.concat(i.lib.WordArray.random(p-1)).concat(i.lib.WordArray.create([p<<24],1))},unpad:function(l){var c=l.words[l.sigBytes-1>>>2]&255;l.sigBytes-=c}},i.pad.Iso10126})})(Ru)),Ru.exports}var Nu={exports:{}},pC=Nu.exports,hg;function mC(){return hg||(hg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(pC,function(i){return i.pad.Iso97971={pad:function(l,c){l.concat(i.lib.WordArray.create([2147483648],1)),i.pad.ZeroPadding.pad(l,c)},unpad:function(l){i.pad.ZeroPadding.unpad(l),l.sigBytes--}},i.pad.Iso97971})})(Nu)),Nu.exports}var Fu={exports:{}},gC=Fu.exports,pg;function xC(){return pg||(pg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(gC,function(i){return i.pad.ZeroPadding={pad:function(l,c){var u=c*4;l.clamp(),l.sigBytes+=u-(l.sigBytes%u||u)},unpad:function(l){for(var c=l.words,u=l.sigBytes-1,u=l.sigBytes-1;u>=0;u--)if(c[u>>>2]>>>24-u%4*8&255){l.sigBytes=u+1;break}}},i.pad.ZeroPadding})})(Fu)),Fu.exports}var Lu={exports:{}},AC=Lu.exports,mg;function vC(){return mg||(mg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(AC,function(i){return i.pad.NoPadding={pad:function(){},unpad:function(){}},i.pad.NoPadding})})(Lu)),Lu.exports}var Mu={exports:{}},yC=Mu.exports,gg;function _C(){return gg||(gg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),xn())})(yC,function(i){return(function(l){var c=i,u=c.lib,p=u.CipherParams,d=c.enc,g=d.Hex,m=c.format;m.Hex={stringify:function(x){return x.ciphertext.toString(g)},parse:function(x){var A=g.parse(x);return p.create({ciphertext:A})}}})(),i.format.Hex})})(Mu)),Mu.exports}var Iu={exports:{}},wC=Iu.exports,xg;function bC(){return xg||(xg=1,(function(n,s){(function(i,l,c){n.exports=l(xt(),ss(),as(),vo(),xn())})(wC,function(i){return(function(){var l=i,c=l.lib,u=c.BlockCipher,p=l.algo,d=[],g=[],m=[],x=[],A=[],w=[],k=[],N=[],C=[],b=[];(function(){for(var T=[],F=0;F<256;F++)F<128?T[F]=F<<1:T[F]=F<<1^283;for(var M=0,H=0,F=0;F<256;F++){var V=H^H<<1^H<<2^H<<3^H<<4;V=V>>>8^V&255^99,d[M]=V,g[V]=M;var j=T[M],ee=T[j],Z=T[ee],Q=T[V]*257^V*16843008;m[M]=Q<<24|Q>>>8,x[M]=Q<<16|Q>>>16,A[M]=Q<<8|Q>>>24,w[M]=Q;var Q=Z*16843009^ee*65537^j*257^M*16843008;k[V]=Q<<24|Q>>>8,N[V]=Q<<16|Q>>>16,C[V]=Q<<8|Q>>>24,b[V]=Q,M?(M=j^T[T[T[Z^j]]],H^=T[T[H]]):M=H=1}})();var B=[0,1,2,4,8,16,32,64,128,27,54],S=p.AES=u.extend({_doReset:function(){var T;if(!(this._nRounds&&this._keyPriorReset===this._key)){for(var F=this._keyPriorReset=this._key,M=F.words,H=F.sigBytes/4,V=this._nRounds=H+6,j=(V+1)*4,ee=this._keySchedule=[],Z=0;Z<j;Z++)Z<H?ee[Z]=M[Z]:(T=ee[Z-1],Z%H?H>6&&Z%H==4&&(T=d[T>>>24]<<24|d[T>>>16&255]<<16|d[T>>>8&255]<<8|d[T&255]):(T=T<<8|T>>>24,T=d[T>>>24]<<24|d[T>>>16&255]<<16|d[T>>>8&255]<<8|d[T&255],T^=B[Z/H|0]<<24),ee[Z]=ee[Z-H]^T);for(var Q=this._invKeySchedule=[],J=0;J<j;J++){var Z=j-J;if(J%4)var T=ee[Z];else var T=ee[Z-4];J<4||Z<=4?Q[J]=T:Q[J]=k[d[T>>>24]]^N[d[T>>>16&255]]^C[d[T>>>8&255]]^b[d[T&255]]}}},encLine truncated
• Timestamp (4 bytes) - send time as unix timestamp
• Request Type (1 byte) - type of request (GetStats, GetTelemetryData, etc.)
• Request Data (remaining bytes) - additional request-specific data`,startByte:d+g,endByte:d+c.length-1,value:w});const k={type:n.PayloadType.Request,version:n.PayloadVersion.Version1,isValid:!0,timestamp:0,requestType:n.RequestType.GetStats,requestData:"",destinationHash:m,sourceHash:x,cipherMac:A,ciphertext:w};return u!=null&&u.includeSegments&&(k.segments=p),k}catch(p){return{type:n.PayloadType.Request,version:n.PayloadVersion.Version1,isValid:!1,errors:[p instanceof Error?p.message:"Failed to decode request payload"],timestamp:0,requestType:n.RequestType.GetStats,requestData:"",destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:""}}}}return ll.RequestPayloadDecoder=i,ll}var cl={},zg;function oE(){if(zg)return cl;zg=1,Object.defineProperty(cl,"__esModule",{value:!0}),cl.ResponsePayloadDecoder=void 0;const n=dr(),s=wn();class i{static decode(c,u){try{if(c.length<4){const N={type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!1,errors:["Response payload too short (minimum 4 bytes: dest + source + MAC)"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return u!=null&&u.includeSegments&&(N.segments=[{name:"Invalid Response Data",description:"Response payload too short (minimum 4 bytes required)",startByte:u.segmentOffset||0,endByte:(u.segmentOffset||0)+c.length-1,value:(0,s.bytesToHex)(c)}]),N}const p=[],d=(u==null?void 0:u.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(c[g]);u!=null&&u.includeSegments&&p.push({name:"Destination Hash",description:"First byte of destination node public key",startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.byteToHex)(c[g]);u!=null&&u.includeSegments&&p.push({name:"Source Hash",description:"First byte of source node public key",startByte:d+g,endByte:d+g,value:x}),g+=1;const A=(0,s.bytesToHex)(c.subarray(g,g+2));u!=null&&u.includeSegments&&p.push({name:"Cipher MAC",description:"MAC for encrypted data in next field",startByte:d+g,endByte:d+g+1,value:A}),g+=2;const w=(0,s.bytesToHex)(c.subarray(g));u!=null&&u.includeSegments&&c.length>g&&p.push({name:"Ciphertext",description:"Encrypted response data (tag + content)",startByte:d+g,endByte:d+c.length-1,value:w});const k={type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,sourceHash:x,cipherMac:A,ciphertext:w,ciphertextLength:c.length-4};return u!=null&&u.includeSegments&&(k.segments=p),k}catch(p){return{type:n.PayloadType.Response,version:n.PayloadVersion.Version1,isValid:!1,errors:[p instanceof Error?p.message:"Failed to decode response payload"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0}}}}return cl.ResponsePayloadDecoder=i,cl}var ul={},Hg;function sE(){if(Hg)return ul;Hg=1,Object.defineProperty(ul,"__esModule",{value:!0}),ul.AnonRequestPayloadDecoder=void 0;const n=dr(),s=wn();class i{static decode(c,u){try{if(c.length<35){const N={type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!1,errors:["AnonRequest payload too short (minimum 35 bytes: dest + public key + MAC)"],destinationHash:"",senderPublicKey:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return u!=null&&u.includeSegments&&(N.segments=[{name:"Invalid AnonRequest Data",description:"AnonRequest payload too short (minimum 35 bytes required: 1 for dest hash + 32 for public key + 2 for MAC)",startByte:u.segmentOffset||0,endByte:(u.segmentOffset||0)+c.length-1,value:(0,s.bytesToHex)(c)}]),N}const p=[],d=(u==null?void 0:u.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(c[0]);u!=null&&u.includeSegments&&p.push({name:"Destination Hash",description:`First byte of destination node public key: 0x${m}`,startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.bytesToHex)(c.subarray(1,33));u!=null&&u.includeSegments&&p.push({name:"Sender Public Key",description:"Ed25519 public key of the sender (32 bytes)",startByte:d+g,endByte:d+g+31,value:x}),g+=32;const A=(0,s.bytesToHex)(c.subarray(33,35));u!=null&&u.includeSegments&&p.push({name:"Cipher MAC",description:"MAC for encrypted data verification (2 bytes)",startByte:d+g,endByte:d+g+1,value:A}),g+=2;const w=(0,s.bytesToHex)(c.subarray(35));u!=null&&u.includeSegments&&c.length>35&&p.push({name:"Ciphertext",description:`Encrypted message data (${c.length-35} bytes). Contains encrypted plaintext with this structure:
• Timestamp (4 bytes) - send time as unix timestamp
• Sync Timestamp (4 bytes) - room server only, sender's "sync messages SINCE x" timestamp
• Password (remaining bytes) - password for repeater/room`,startByte:d+g,endByte:d+c.length-1,value:w});const k={type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,senderPublicKey:x,cipherMac:A,ciphertext:w,ciphertextLength:c.length-35};return u!=null&&u.includeSegments&&(k.segments=p),k}catch(p){return{type:n.PayloadType.AnonRequest,version:n.PayloadVersion.Version1,isValid:!1,errors:[p instanceof Error?p.message:"Failed to decode AnonRequest payload"],destinationHash:"",senderPublicKey:"",cipherMac:"",ciphertext:"",ciphertextLength:0}}}}return ul.AnonRequestPayloadDecoder=i,ul}var dl={},Vg;function aE(){if(Vg)return dl;Vg=1,Object.defineProperty(dl,"__esModule",{value:!0}),dl.AckPayloadDecoder=void 0;const n=dr(),s=wn();class i{static decode(c,u){try{if(c.length<4){const x={type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!1,errors:["Ack payload too short (minimum 4 bytes for checksum)"],checksum:""};return u!=null&&u.includeSegments&&(x.segments=[{name:"Invalid Ack Data",description:"Ack payload too short (minimum 4 bytes required for checksum)",startByte:u.segmentOffset||0,endByte:(u.segmentOffset||0)+c.length-1,value:(0,s.bytesToHex)(c)}]),x}const p=[],d=(u==null?void 0:u.segmentOffset)||0,g=(0,s.bytesToHex)(c.subarray(0,4));u!=null&&u.includeSegments&&p.push({name:"Checksum",description:`CRC checksum of message timestamp, text, and sender pubkey: 0x${g}`,startByte:d,endByte:d+3,value:g}),u!=null&&u.includeSegments&&c.length>4&&p.push({name:"Additional Data",description:"Extra data in Ack payload",startByte:d+4,endByte:d+c.length-1,value:(0,s.bytesToHex)(c.subarray(4))});const m={type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!0,checksum:g};return u!=null&&u.includeSegments&&(m.segments=p),m}catch(p){return{type:n.PayloadType.Ack,version:n.PayloadVersion.Version1,isValid:!1,errors:[p instanceof Error?p.message:"Failed to decode Ack payload"],checksum:""}}}}return dl.AckPayloadDecoder=i,dl}var fl={},Ug;function lE(){if(Ug)return fl;Ug=1,Object.defineProperty(fl,"__esModule",{value:!0}),fl.PathPayloadDecoder=void 0;const n=dr(),s=wn();class i{static decode(c){try{if(c.length<2)return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:["Path payload too short (minimum 2 bytes: path length + extra type)"],pathLength:0,pathHashes:[],extraType:0,extraData:""};const u=c[0];if(c.length<1+u+1)return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:[`Path payload too short (need ${1+u+1} bytes for path length + path + extra type)`],pathLength:u,pathHashes:[],extraType:0,extraData:""};const p=[];for(let m=0;m<u;m++)p.push((0,s.byteToHex)(c[1+m]));const d=c[1+u];let g="";return c.length>1+u+1&&(g=(0,s.bytesToHex)(c.subarray(1+u+1))),{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!0,pathLength:u,pathHashes:p,extraType:d,extraData:g}}catch(u){return{type:n.PayloadType.Path,version:n.PayloadVersion.Version1,isValid:!1,errors:[u instanceof Error?u.message:"Failed to decode Path payload"],pathLength:0,pathHashes:[],extraType:0,extraData:""}}}}return fl.PathPayloadDecoder=i,fl}var hl={},Zg;function cE(){if(Zg)return hl;Zg=1,Object.defineProperty(hl,"__esModule",{value:!0}),hl.TextMessagePayloadDecoder=void 0;const n=dr(),s=wn();class i{static decode(c,u){try{if(c.length<4){const N={type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,isValid:!1,errors:["TextMessage payload too short (minimum 4 bytes: dest + source + MAC)"],destinationHash:"",sourceHash:"",cipherMac:"",ciphertext:"",ciphertextLength:0};return u!=null&&u.includeSegments&&(N.segments=[{name:"Invalid TextMessage Data",description:"TextMessage payload too short (minimum 4 bytes required)",startByte:u.segmentOffset||0,endByte:(u.segmentOffset||0)+c.length-1,value:(0,s.bytesToHex)(c)}]),N}const p=[],d=(u==null?void 0:u.segmentOffset)||0;let g=0;const m=(0,s.byteToHex)(c[g]);u!=null&&u.includeSegments&&p.push({name:"Destination Hash",description:"First byte of destination node public key",startByte:d+g,endByte:d+g,value:m}),g+=1;const x=(0,s.byteToHex)(c[g]);u!=null&&u.includeSegments&&p.push({name:"Source Hash",description:"First byte of source node public key",startByte:d+g,endByte:d+g,value:x}),g+=1;const A=(0,s.bytesToHex)(c.subarray(g,g+2));u!=null&&u.includeSegments&&p.push({name:"Cipher MAC",description:"MAC for encrypted data in next field",startByte:d+g,endByte:d+g+1,value:A}),g+=2;const w=(0,s.bytesToHex)(c.subarray(g));u!=null&&u.includeSegments&&c.length>g&&p.push({name:"Ciphertext",description:"Encrypted message data (timestamp + message text)",startByte:d+g,endByte:d+c.length-1,value:w});const k={type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,isValid:!0,destinationHash:m,sourceHash:x,cipherMac:A,ciphertext:w,ciphertextLength:c.length-4};return u!=null&&u.includeSegments&&(k.segments=p),k}catch(p){return{type:n.PayloadType.TextMessage,version:n.PayloadVersion.Version1,i Line truncated
* Leaflet 1.9.4, a JS library for interactive maps. https://leafletjs.com
* (c) 2010-2023 Vladimir Agafonkin, (c) 2010-2011 CloudMade
*/var EE=gl.exports,Yg;function kE(){return Yg||(Yg=1,(function(n,s){(function(i,l){l(s)})(EE,(function(i){var l="1.9.4";function c(t){var o,f,v,P;for(f=1,v=arguments.length;f<v;f++){P=arguments[f];for(o in P)t[o]=P[o]}return t}var u=Object.create||(function(){function t(){}return function(o){return t.prototype=o,new t}})();function p(t,o){var f=Array.prototype.slice;if(t.bind)return t.bind.apply(t,f.call(arguments,1));var v=f.call(arguments,2);return function(){return t.apply(o,v.length?v.concat(f.call(arguments)):arguments)}}var d=0;function g(t){return"_leaflet_id"in t||(t._leaflet_id=++d),t._leaflet_id}function m(t,o,f){var v,P,O,X;return X=function(){v=!1,P&&(O.apply(f,P),P=!1)},O=function(){v?P=arguments:(t.apply(f,arguments),setTimeout(X,o),v=!0)},O}function x(t,o,f){var v=o[1],P=o[0],O=v-P;return t===v&&f?t:((t-P)%O+O)%O+P}function A(){return!1}function w(t,o){if(o===!1)return t;var f=Math.pow(10,o===void 0?6:o);return Math.round(t*f)/f}function k(t){return t.trim?t.trim():t.replace(/^\s+|\s+$/g,"")}function N(t){return k(t).split(/\s+/)}function C(t,o){Object.prototype.hasOwnProperty.call(t,"options")||(t.options=t.options?u(t.options):{});for(var f in o)t.options[f]=o[f];return t.options}function b(t,o,f){var v=[];for(var P in t)v.push(encodeURIComponent(f?P.toUpperCase():P)+"="+encodeURIComponent(t[P]));return(!o||o.indexOf("?")===-1?"?":"&")+v.join("&")}var B=/\{ *([\w_ -]+) *\}/g;function S(t,o){return t.replace(B,function(f,v){var P=o[v];if(P===void 0)throw new Error("No value provided for variable "+f);return typeof P=="function"&&(P=P(o)),P})}var T=Array.isArray||function(t){return Object.prototype.toString.call(t)==="[object Array]"};function F(t,o){for(var f=0;f<t.length;f++)if(t[f]===o)return f;return-1}var M="data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=";function H(t){return window["webkit"+t]||window["moz"+t]||window["ms"+t]}var V=0;function j(t){var o=+new Date,f=Math.max(0,16-(o-V));return V=o+f,window.setTimeout(t,f)}var ee=window.requestAnimationFrame||H("RequestAnimationFrame")||j,Z=window.cancelAnimationFrame||H("CancelAnimationFrame")||H("CancelRequestAnimationFrame")||function(t){window.clearTimeout(t)};function Q(t,o,f){if(f&&ee===j)t.call(o);else return ee.call(window,p(t,o))}function J(t){t&&Z.call(window,t)}var $={__proto__:null,extend:c,create:u,bind:p,get lastId(){return d},stamp:g,throttle:m,wrapNum:x,falseFn:A,formatNum:w,trim:k,splitWords:N,setOptions:C,getParamString:b,template:S,isArray:T,indexOf:F,emptyImageUrl:M,requestFn:ee,cancelFn:Z,requestAnimFrame:Q,cancelAnimFrame:J};function oe(){}oe.extend=function(t){var o=function(){C(this),this.initialize&&this.initialize.apply(this,arguments),this.callInitHooks()},f=o.__super__=this.prototype,v=u(f);v.constructor=o,o.prototype=v;for(var P in this)Object.prototype.hasOwnProperty.call(this,P)&&P!=="prototype"&&P!=="__super__"&&(o[P]=this[P]);return t.statics&&c(o,t.statics),t.includes&&(me(t.includes),c.apply(null,[v].concat(t.includes))),c(v,t),delete v.statics,delete v.includes,v.options&&(v.options=f.options?u(f.options):{},c(v.options,t.options)),v._initHooks=[],v.callInitHooks=function(){if(!this._initHooksCalled){f.callInitHooks&&f.callInitHooks.call(this),this._initHooksCalled=!0;for(var O=0,X=v._initHooks.length;O<X;O++)v._initHooks[O].call(this)}},o},oe.include=function(t){var o=this.prototype.options;return c(this.prototype,t),t.options&&(this.prototype.options=o,this.mergeOptions(t.options)),this},oe.mergeOptions=function(t){return c(this.prototype.options,t),this},oe.addInitHook=function(t){var o=Array.prototype.slice.call(arguments,1),f=typeof t=="function"?t:function(){this[t].apply(this,o)};return this.prototype._initHooks=this.prototype._initHooks||[],this.prototype._initHooks.push(f),this};function me(t){if(!(typeof L>"u"||!L||!L.Mixin)){t=T(t)?t:[t];for(var o=0;o<t.length;o++)t[o]===L.Mixin.Events&&console.warn("Deprecated include of L.Mixin.Events: this property will be removed in future releases, please inherit from L.Evented instead.",new Error().stack)}}var G={on:function(t,o,f){if(typeof t=="object")for(var v in t)this._on(v,t[v],o);else{t=N(t);for(var P=0,O=t.length;P<O;P++)this._on(t[P],o,f)}return this},off:function(t,o,f){if(!arguments.length)delete this._events;else if(typeof t=="object")for(var v in t)this._off(v,t[v],o);else{t=N(t);for(var P=arguments.length===1,O=0,X=t.length;O<X;O++)P?this._off(t[O]):this._off(t[O],o,f)}return this},_on:function(t,o,f,v){if(typeof o!="function"){console.warn("wrong listener type: "+typeof o);return}if(this._listens(t,o,f)===!1){f===this&&(f=void 0);var P={fn:o,ctx:f};v&&(P.once=!0),this._events=this._events||{},this._events[t]=this._events[t]||[],this._events[t].push(P)}},_off:function(t,o,f){var v,P,O;if(this._events&&(v=this._events[t],!!v)){if(arguments.length===1){if(this._firingCount)for(P=0,O=v.length;P<O;P++)v[P].fn=A;delete this._events[t];return}if(typeof o!="function"){console.warn("wrong listener type: "+typeof o);return}var X=thisLine truncated
// SHA256 round constants
const K: array<u32, 64> = array<u32, 64>(
0x428a2f98u, 0x71374491u, 0xb5c0fbcfu, 0xe9b5dba5u, 0x3956c25bu, 0x59f111f1u, 0x923f82a4u, 0xab1c5ed5u,
0xd807aa98u, 0x12835b01u, 0x243185beu, 0x550c7dc3u, 0x72be5d74u, 0x80deb1feu, 0x9bdc06a7u, 0xc19bf174u,
0xe49b69c1u, 0xefbe4786u, 0x0fc19dc6u, 0x240ca1ccu, 0x2de92c6fu, 0x4a7484aau, 0x5cb0a9dcu, 0x76f988dau,
0x983e5152u, 0xa831c66du, 0xb00327c8u, 0xbf597fc7u, 0xc6e00bf3u, 0xd5a79147u, 0x06ca6351u, 0x14292967u,
0x27b70a85u, 0x2e1b2138u, 0x4d2c6dfcu, 0x53380d13u, 0x650a7354u, 0x766a0abbu, 0x81c2c92eu, 0x92722c85u,
0xa2bfe8a1u, 0xa81a664bu, 0xc24b8b70u, 0xc76c51a3u, 0xd192e819u, 0xd6990624u, 0xf40e3585u, 0x106aa070u,
0x19a4c116u, 0x1e376c08u, 0x2748774cu, 0x34b0bcb5u, 0x391c0cb3u, 0x4ed8aa4au, 0x5b9cca4fu, 0x682e6ff3u,
0x748f82eeu, 0x78a5636fu, 0x84c87814u, 0x8cc70208u, 0x90befffau, 0xa4506cebu, 0xbef9a3f7u, 0xc67178f2u
);
// Character lookup table (a-z = 0-25, 0-9 = 26-35, dash = 36)
const CHARS: array<u32, 37> = array<u32, 37>(
0x61u, 0x62u, 0x63u, 0x64u, 0x65u, 0x66u, 0x67u, 0x68u, 0x69u, 0x6au, // a-j
0x6bu, 0x6cu, 0x6du, 0x6eu, 0x6fu, 0x70u, 0x71u, 0x72u, 0x73u, 0x74u, // k-t
0x75u, 0x76u, 0x77u, 0x78u, 0x79u, 0x7au, // u-z
0x30u, 0x31u, 0x32u, 0x33u, 0x34u, 0x35u, 0x36u, 0x37u, 0x38u, 0x39u, // 0-9
0x2du // dash
);
struct Params {
target_channel_hash: u32,
batch_offset: u32,
name_length: u32,
batch_size: u32,
target_mac: u32, // First 2 bytes of target MAC (in high 16 bits)
ciphertext_words: u32, // Number of 32-bit words in ciphertext
ciphertext_len_bits: u32, // Length of ciphertext in bits
verify_mac: u32, // 1 to verify MAC, 0 to skip
}
@group(0) @binding(0) var<uniform> params: Params;
@group(0) @binding(1) var<storage, read_write> match_count: atomic<u32>;
@group(0) @binding(2) var<storage, read_write> match_indices: array<u32>;
@group(0) @binding(3) var<storage, read> ciphertext: array<u32>; // Ciphertext data
fn rotr(x: u32, n: u32) -> u32 {
return (x >> n) | (x << (32u - n));
}
fn ch(x: u32, y: u32, z: u32) -> u32 {
return (x & y) ^ (~x & z);
}
fn maj(x: u32, y: u32, z: u32) -> u32 {
return (x & y) ^ (x & z) ^ (y & z);
}
fn sigma0(x: u32) -> u32 {
return rotr(x, 2u) ^ rotr(x, 13u) ^ rotr(x, 22u);
}
fn sigma1(x: u32) -> u32 {
return rotr(x, 6u) ^ rotr(x, 11u) ^ rotr(x, 25u);
}
fn gamma0(x: u32) -> u32 {
return rotr(x, 7u) ^ rotr(x, 18u) ^ (x >> 3u);
}
fn gamma1(x: u32) -> u32 {
return rotr(x, 17u) ^ rotr(x, 19u) ^ (x >> 10u);
}
// Convert index to room name bytes, returns the hash as a u32 for the first byte check
fn index_to_room_name(idx: u32, length: u32, msg: ptr<function, array<u32, 16>>) -> bool {
// Message starts with '#' (0x23)
var byte_pos = 0u;
var word_idx = 0u;
var current_word = 0x23000000u; // '#' in big-endian position 0
byte_pos = 1u;
var remaining = idx;
var prev_was_dash = false;
// Generate room name from index
for (var i = 0u; i < length; i++) {
let char_count = select(37u, 36u, i == 0u || i == length - 1u); // no dash at start/end
var char_idx = remaining % char_count;
remaining = remaining / char_count;
// Check for consecutive dashes (invalid)
let is_dash = char_idx == 36u && i > 0u && i < length - 1u;
if (is_dash && prev_was_dash) {
return false; // Invalid: consecutive dashes
}
prev_was_dash = is_dash;
// Map char index to actual character
let c = CHARS[char_idx];
// Pack byte into current word (big-endian)
let shift = (3u - byte_pos % 4u) * 8u;
if (byte_pos % 4u == 0u && byte_pos > 0u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
current_word = 0u;
}
current_word = current_word | (c << shift);
byte_pos = byte_pos + 1u;
}
// Add padding: 0x80 followed by zeros, then length in bits
let msg_len_bits = (length + 1u) * 8u; // +1 for '#'
// Add 0x80 padding byte
let shift = (3u - byte_pos % 4u) * 8u;
if (byte_pos % 4u == 0u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
current_word = 0x80000000u;
} else {
current_word = current_word | (0x80u << shift);
}
byte_pos = byte_pos + 1u;
// Store current word
if (byte_pos % 4u == 0u || word_idx < 14u) {
(*msg)[word_idx] = current_word;
word_idx = word_idx + 1u;
}
// Zero-fill until word 14
for (var i = word_idx; i < 14u; i++) {
(*msg)[i] = 0u;
}
// Length in bits (64-bit, but we only use lower 32 bits for short messages)
(*msg)[14u] = 0u;
(*msg)[15u] = msg_len_bits;
return true;
}
fn sha256_block(msg: ptr<function, array<u32, 16>>) -> array<u32, 8> {
// Initialize hash values
var h: array<u32, 8> = array<u32, 8>(
0x6a09e667u, 0xbb67ae85u, 0x3c6ef372u, 0xa54ff53au,
0x510e527fu, 0x9b05688cu, 0x1f83d9abu, 0x5be0cd19u
);
// Message schedule
var w: array<u32, 64>;
for (var i = 0u; i < 16u; i++) {
w[i] = (*msg)[i];
}
for (var i = 16u; i < 64u; i++) {
w[i] = gamma1(w[i-2u]) + w[i-7u] + gamma0(w[i-15u]) + w[i-16u];
}
// Compression
var a = h[0]; var b = h[1]; var c = h[2]; var d = h[3];
var e = h[4]; var f = h[5]; var g = h[6]; var hh = h[7];
for (var i = 0u; i < 64u; i++) {
let t1 = hh + sigma1(e) + ch(e, f, g) + K[i] + w[i];
let t2 = sigma0(a) + maj(a, b, c);
hh = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
h[0] = h[0] + a; h[1] = h[1] + b; h[2] = h[2] + c; h[3] = h[3] + d;
h[4] = h[4] + e; h[5] = h[5] + f; h[6] = h[6] + g; h[7] = h[7] + hh;
return h;
}
// Compute SHA256 of the key (16 bytes) to get channel hash
fn sha256_key(key: array<u32, 4>) -> u32 {
var msg: array<u32, 16>;
// Key bytes (16 bytes = 4 words)
msg[0] = key[0];
msg[1] = key[1];
msg[2] = key[2];
msg[3] = key[3];
// Padding: 0x80 followed by zeros
msg[4] = 0x80000000u;
for (var i = 5u; i < 14u; i++) {
msg[i] = 0u;
}
// Length: 128 bits
msg[14] = 0u;
msg[15] = 128u;
let hash = sha256_block(&msg);
// Return first byte of hash (big-endian)
return hash[0] >> 24u;
}
// HMAC-SHA256 for MAC verification
// Key is 16 bytes (4 words), padded to 32 bytes with zeros for MeshCore
// Returns first 2 bytes of HMAC (as u32 in high 16 bits)
fn hmac_sha256_mac(key: array<u32, 4>, ciphertext_len: u32) -> u32 {
// HMAC: H((K' ^ opad) || H((K' ^ ipad) || message))
// K' is 64 bytes (32 bytes key + 32 bytes zero padding for MeshCore, then padded to 64)
// ipad = 0x36 repeated, opad = 0x5c repeated
// Build padded key (64 bytes = 16 words)
// MeshCore uses 32-byte secret: 16-byte key + 16 zero bytes
var k_pad: array<u32, 16>;
k_pad[0] = key[0];
k_pad[1] = key[1];
k_pad[2] = key[2];
k_pad[3] = key[3];
for (var i = 4u; i < 16u; i++) {
k_pad[i] = 0u;
}
// Inner hash: SHA256((K' ^ ipad) || message)
// First block: K' ^ ipad (64 bytes)
var inner_block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
inner_block[i] = k_pad[i] ^ 0x36363636u;
}
// Initialize hash state with first block
var h: array<u32, 8> = sha256_block(&inner_block);
// Process ciphertext blocks (continuing from h state)
let ciphertext_words = params.ciphertext_words;
var word_idx = 0u;
// Process full 64-byte blocks of ciphertext
while (word_idx + 16u <= ciphertext_words) {
var block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
block[i] = ciphertext[word_idx + i];
}
h = sha256_block_continue(&block, h);
word_idx = word_idx + 16u;
}
// Final block with remaining ciphertext + padding
var final_block: array<u32, 16>;
var remaining = ciphertext_words - word_idx;
for (var i = 0u; i < 16u; i++) {
if (i < remaining) {
final_block[i] = ciphertext[word_idx + i];
} else if (i == remaining) {
// Add 0x80 padding
final_block[i] = 0x80000000u;
} else {
final_block[i] = 0u;
}
}
// Add length (64 bytes of ipad + ciphertext length)
let total_bits = 512u + params.ciphertext_len_bits;
if (remaining < 14u) {
final_block[14] = 0u;
final_block[15] = total_bits;
h = sha256_block_continue(&final_block, h);
} else {
// Need extra block for length
h = sha256_block_continue(&final_block, h);
var len_block: array<u32, 16>;
for (var i = 0u; i < 14u; i++) {
len_block[i] = 0u;
}
len_block[14] = 0u;
len_block[15] = total_bits;
h = sha256_block_continue(&len_block, h);
}
let inner_hash = h;
// Outer hash: SHA256((K' ^ opad) || inner_hash)
var outer_block: array<u32, 16>;
for (var i = 0u; i < 16u; i++) {
outer_block[i] = k_pad[i] ^ 0x5c5c5c5cu;
}
h = sha256_block(&outer_block);
// Second block: inner_hash (32 bytes) + padding
var hash_block: array<u32, 16>;
for (var i = 0u; i < 8u; i++) {
hash_block[i] = inner_hash[i];
}
hash_block[8] = 0x80000000u;
for (var i = 9u; i < 14u; i++) {
hash_block[i] = 0u;
}
hash_block[14] = 0u;
hash_block[15] = 512u + 256u; // 64 bytes opad + 32 bytes inner hash
h = sha256_block_continue(&hash_block, h);
// Return first 2 bytes (high 16 bits of first word)
return h[0] & 0xFFFF0000u;
}
// SHA256 block computation continuing from existing state
fn sha256_block_continue(msg: ptr<function, array<u32, 16>>, h_in: array<u32, 8>) -> array<u32, 8> {
var h = h_in;
// Message schedule
var w: array<u32, 64>;
for (var i = 0u; i < 16u; i++) {
w[i] = (*msg)[i];
}
for (var i = 16u; i < 64u; i++) {
w[i] = gamma1(w[i-2u]) + w[i-7u] + gamma0(w[i-15u]) + w[i-16u];
}
// Compression
var a = h[0]; var b = h[1]; var c = h[2]; var d = h[3];
var e = h[4]; var f = h[5]; var g = h[6]; var hh = h[7];
for (var i = 0u; i < 64u; i++) {
let t1 = hh + sigma1(e) + ch(e, f, g) + K[i] + w[i];
let t2 = sigma0(a) + maj(a, b, c);
hh = g; g = f; f = e; e = d + t1;
d = c; c = b; b = a; a = t1 + t2;
}
h[0] = h[0] + a; h[1] = h[1] + b; h[2] = h[2] + c; h[3] = h[3] + d;
h[4] = h[4] + e; h[5] = h[5] + f; h[6] = h[6] + g; h[7] = h[7] + hh;
return h;
}
// Process a single candidate and record match if found
fn process_candidate(name_idx: u32) {
// Generate message for this room name
var msg: array<u32, 16>;
let valid = index_to_room_name(name_idx, params.name_length, &msg);
if (!valid) {
return;
}
// Compute SHA256("#roomname") - this gives us the key
let key_hash = sha256_block(&msg);
// Take first 16 bytes (4 words) as the key
var key: array<u32, 4>;
key[0] = key_hash[0];
key[1] = key_hash[1];
key[2] = key_hash[2];
key[3] = key_hash[3];
// Compute SHA256(key) to get channel hash
let channel_hash = sha256_key(key);
// Check if channel hash matches target
if (channel_hash != params.target_channel_hash) {
return;
}
// Channel hash matches - verify MAC if enabled
if (params.verify_mac == 1u) {
let computed_mac = hmac_sha256_mac(key, params.ciphertext_len_bits);
if (computed_mac != params.target_mac) {
return;
}
}
// Found a match - record the index
let match_idx = atomicAdd(&match_count, 1u);
if (match_idx < 1024u) { // Limit stored matches
match_indices[match_idx] = name_idx;
}
}
// Each thread processes 32 candidates to amortize thread overhead
const CANDIDATES_PER_THREAD: u32 = 32u;
@compute @workgroup_size(256)
fn main(@builtin(global_invocation_id) global_id: vec3<u32>) {
let base_idx = global_id.x * CANDIDATES_PER_THREAD;
for (var i = 0u; i < CANDIDATES_PER_THREAD; i++) {
let idx = base_idx + i;
if (idx >= params.batch_size) {
return;
}
let name_idx = params.batch_offset + idx;
process_candidate(name_idx);
}
}
`}async init(){if(!navigator.gpu)return console.warn("WebGPU not supported"),!1;try{const s=await navigator.gpu.requestAdapter();if(!s)return console.warn("No GPU adapter found"),!1;this.device=await s.requestDevice(),this.bindGroupLayout=this.device.createBindGroupLayout({entries:[{binding:0,visibility:GPUShaderStage.COMPUTE,buffer:{type:"uniform"}},{binding:1,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:2,visibility:GPUShaderStage.COMPUTE,buffer:{type:"storage"}},{binding:3,visibility:GPUShaderStage.COMPUTE,buffer:{type:"read-only-storage"}}]}),this.paramsBuffer=this.device.createBuffer({size:32,usage:GPUBufferUsage.UNIFORM|GPUBufferUsage.COPY_DST}),this.matchCountBuffer=this.device.createBuffer({size:4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST}),this.matchIndicesBuffer=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_SRC});for(let c=0;c<2;c++)this.matchCountReadBuffers[c]=this.device.createBuffer({size:4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST}),this.matchIndicesReadBuffers[c]=this.device.createBuffer({size:1024*4,usage:GPUBufferUsage.MAP_READ|GPUBufferUsage.COPY_DST});const i=this.device.createShaderModule({code:this.shaderCode}),l=this.device.createPipelineLayout({bindGroupLayouts:[this.bindGroupLayout]});return this.pipeline=this.device.createComputePipeline({layout:l,compute:{module:i,entryPoint:"main"}}),!0}catch(s){return console.error("WebGPU initialization failed:",s),!1}}isAvailable(){return this.device!==null&&this.pipeline!==null}indexToRoomName(s,i){return es(i,s)}countNamesForLength(s){return vl(s)}async runBatch(s,i,l,c,u,p){if(!this.device||!this.pipeline||!this.bindGroupLayout||!this.paramsBuffer||!this.matchCountBuffer||!this.matchIndicesBuffer||!this.matchCountReadBuffers[0]||!this.matchCountReadBuffers[1]||!this.matchIndicesReadBuffers[0]||!this.matchIndicesReadBuffers[1])throw new Error("GPU not initialized");const d=this.currentReadBufferIndex;this.currentReadBufferIndex=1-this.currentReadBufferIndex;const g=this.matchCountReadBuffers[d],m=this.matchIndicesReadBuffers[d],x=u&&p?1:0;let A,w=0,k=0;if(x){const M=new Uint8Array(u.length/2);for(let Z=0;Z<M.length;Z++)M[Z]=parseInt(u.substr(Z*2,2),16);w=M.length*8;const H=Math.ceil(M.length/4)*4,V=new Uint8Array(H);V.set(M),A=new Uint32Array(H/4);for(let Z=0;Z<A.length;Z++)A[Z]=V[Z*4]<<24|V[Z*4+1]<<16|V[Z*4+2]<<8|V[Z*4+3];const j=parseInt(p.substr(0,2),16),ee=parseInt(p.substr(2,2),16);k=j<<24|ee<<16}else A=new Uint32Array([0]);const N=Math.max(A.length*4,4);(!this.ciphertextBuffer||this.ciphertextBufferSize<N)&&(this.ciphertextBuffer&&this.ciphertextBuffer.destroy(),this.ciphertextBuffer=this.device.createBuffer({size:N,usage:GPUBufferUsage.STORAGE|GPUBufferUsage.COPY_DST}),this.ciphertextBufferSize=N,this.bindGroupDirty=!0);const C=new Uint32Array([s,l,i,c,k,A.length,w,x]);this.device.queue.writeBuffer(this.paramsBuffer,0,C),this.device.queue.writeBuffer(this.ciphertextBuffer,0,A),this.device.queue.writeBuffer(this.matchCountBuffer,0,kd.ZERO_DATA),(this.bindGroupDirty||!this.bindGroup)&&(this.bindGroup=this.device.createBindGroup({layout:this.bindGroupLayout,entries:[{binding:0,resource:{buffer:this.paramsBuffer}},{binding:1,resource:{buffer:this.matchCountBuffer}},{binding:2,resource:{buffer:this.matchIndicesBuffer}},{binding:3,resource:{buffer:this.ciphertextBuffer}}]}),this.bindGroupDirty=!1);const b=this.device.createCommandEncoder(),B=b.beginComputePass();B.setPipeline(this.pipeline),B.setBindGroup(0,this.bindGroup),B.dispatchWorkgroups(Math.ceil(c/(256*32))),B.end(),b.copyBufferToBuffer(this.matchCountBuffer,0,g,0,4),b.copyBufferToBuffer(this.matchIndicesBuffer,0,m,0,1024*4),this.device.queue.submit([b.finish()]),await g.mapAsync(GPUMapMode.READ);const T=new Uint32Array(g.getMappedRange())[0];g.unmap();const F=[];if(T>0){await m.mapAsync(GPUMapMode.READ);const M=new Uint32Array(m.getMappedRange());for(let H=0;H<Math.min(T,1024);H++)F.push(M[H]);m.unmap()}return F}destroy(){var s,i,l,c,u,p,d,g;(s=this.paramsBuffer)==null||s.destroy(),(i=this.matchCountBuffer)==null||i.destroy(),(l=this.matchIndicesBuffer)==null||l.destroy(),(c=this.ciphertextBuffer)==null||c.destroy(),(u=this.matchCountReadBuffers[0])==null||u.destroy(),(p=this.matchCountReadBuffers[1])==null||p.destroy(),(d=this.matchIndicesReadBuffers[0])==null||d.destroy(),(g=this.matchIndicesReadBuffers[1])==null||g.destroy(),this.paramsBuffer=null,this.matchCountBuffer=null,this.matchIndicesBuffer=null,this.ciphertextBuffer=null,this.ciphertextBufferSize=0,this.matchCountReadBuffers=[null,null],this.matchIndicesReadBuffers=[null,null],this.currentReadBufferIndex=0,this.bindGroup=null,this.bindGroupDirty=!0,this.device&&(this.device.destroy(),this.device=null),this.pipeline=null,this.bindGroupLayout=null}}kd.ZERO_DATA=new Uint32Array([0]);function oS(){return typeof navigator<"u"&&"gpu"in navigator}class fx{runBatch(s,i,l,c,u,p){const d=[],g=s.toString(16).padStart(2,"0 Line truncated
`).map(u=>u.trim().toLowerCase()).filter(u=>u.length>0);this.wordlist=c.filter(hx)}setWordlist(s){this.wordlist=s.map(i=>i.trim().toLowerCase()).filter(hx)}abort(){this.abortFlag=!0}isGpuAvailable(){return oS()}async decodePacket(s){var l;const i=s.trim().replace(/\s+/g,"").replace(/^0x/i,"");if(!i||!/^[0-9a-fA-F]+$/.test(i))return null;try{const u=(l=(await yt.MeshCorePacketDecoder.decodeWithVerification(i,{})).payload)==null?void 0:l.decoded;return!(u!=null&&u.channelHash)||!(u!=null&&u.ciphertext)||!(u!=null&&u.cipherMac)?null:{channelHash:u.channelHash,ciphertext:u.ciphertext,cipherMac:u.cipherMac,isGroupText:!0}}catch{return null}}async crack(s,i,l){this.abortFlag=!1,this.useTimestampFilter=(i==null?void 0:i.useTimestampFilter)??!0,this.useUtf8Filter=(i==null?void 0:i.useUtf8Filter)??!0,this.useSenderFilter=(i==null?void 0:i.useSenderFilter)??!0,this.validSeconds=(i==null?void 0:i.validSeconds)??F0,this.useCpu=(i==null?void 0:i.forceCpu)??!1;const c=(i==null?void 0:i.maxLength)??8,u=(i==null?void 0:i.startingLength)??1,p=(i==null?void 0:i.useDictionary)??!0,d=(i==null?void 0:i.startFromType)??"bruteforce",g=s.toLowerCase(),m=await this.decodePacket(g);if(!m)return{found:!1,error:"Invalid packet or not a GroupText packet"};const{channelHash:x,ciphertext:A,cipherMac:w}=m,k=parseInt(x,16);this.useCpu?this.cpuInstance||(this.cpuInstance=new fx):this.gpuInstance||(this.gpuInstance=new kd,await this.gpuInstance.init()||(this.useCpu=!0,this.cpuInstance=new fx));const N=performance.now();let C=0,b=performance.now(),B=u,S=0,T=0,F=!1;if(i!=null&&i.startFrom){const $=i.startFrom.toLowerCase();if(d==="dictionary"){const oe=this.wordlist.indexOf($);oe>=0&&(T=oe+1)}else{F=!0;const oe=nS($);oe&&(B=Math.max(u,oe.length),S=oe.index+1,S>=vl(B)&&(B++,S=0))}}let M=0;p&&!F&&this.wordlist.length>0&&(M+=this.wordlist.length-T);for(let $=B;$<=c;$++)M+=vl($);M-=S;const H=($,oe,me)=>{if(!l)return;const se=(performance.now()-N)/1e3,W=se>0?Math.round(C/se):0,ne=M-C,U=W>0?ne/W:0;l({checked:C,total:M,percent:M>0?Math.min(100,C/M*100):0,rateKeysPerSec:W,etaSeconds:U,elapsedSeconds:se,currentLength:oe,currentPosition:me,phase:$})},V=$=>{if(!Rv(A,w,$))return{valid:!1};const oe=yt.ChannelCrypto.decryptGroupTextMessage(A,w,$);return!oe.success||!oe.data?{valid:!1}:this.useTimestampFilter&&!rS(oe.data.timestamp,this.validSeconds)?{valid:!1}:this.useUtf8Filter&&!iS(oe.data.message)?{valid:!1}:this.useSenderFilter&&!oe.data.sender?{valid:!1}:{valid:!0,message:oe.data.sender?`${oe.data.sender}: ${oe.data.message}`:oe.data.message}};if(!F&&T===0&&B===u&&S===0){H("public-key",0,N0);const $=M0(Gu);if(x===$){const oe=V(Gu);if(oe.valid)return{found:!0,roomName:N0,key:Gu,decryptedMessage:oe.message}}}if(p&&!F&&this.wordlist.length>0)for(let $=T;$<this.wordlist.length;$++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:this.wordlist[$],resumeType:"dictionary"};const oe=this.wordlist[$],me=L0("#"+oe),G=M0(me);if(parseInt(G,16)===k){const W=V(me);if(W.valid)return{found:!0,roomName:oe,key:me,decryptedMessage:W.message,resumeFrom:oe,resumeType:"dictionary"}}C++;const se=performance.now();se-b>=200&&(H("wordlist",oe.length,oe),b=se,await new Promise(W=>setTimeout(W,0)))}const j=this.useCpu?1024:32768,ee=(i==null?void 0:i.gpuDispatchMs)??1e3;let Z=j,Q=!1;for(let $=B;$<=c;$++){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:es($,0)||void 0,resumeType:"bruteforce"};const oe=vl($);let me=$===B?S:0;for(;me<oe;){if(this.abortFlag)return{found:!1,aborted:!0,resumeFrom:es($,me)||void 0,resumeType:"bruteforce"};const G=Math.min(Z,oe-me),se=performance.now();let W;this.useCpu?W=this.cpuInstance.runBatch(k,$,me,G,A,w):W=await this.gpuInstance.runBatch(k,$,me,G,A,w);const ne=performance.now()-se;if(C+=G,!this.useCpu&&!Q&&G>=j&&ne>0){const D=ee/ne,z=Math.round(G*D),q=Math.pow(2,Math.round(Math.log2(Math.max(j,z))));Z=Math.max(j,q),Q=!0}for(const D of W){const z=es($,D);if(!z)continue;const q=L0("#"+z),K=V(q);if(K.valid)return{found:!0,roomName:z,key:q,decryptedMessage:K.message,resumeFrom:z,resumeType:"bruteforce"}}me+=G;const U=performance.now();if(U-b>=200){const D=es($,Math.min(me,oe-1))||"";H("bruteforce",$,D),b=U,await new Promise(z=>setTimeout(z,0))}}}return{found:!1,resumeFrom:es(c,vl(c)-1)||void 0,resumeType:"bruteforce"}}destroy(){this.gpuInstance&&(this.gpuInstance.destroy(),this.gpuInstance=null),this.cpuInstance&&(this.cpuInstance.destroy(),this.cpuInstance=null)}}var x0,px;function uS(){return px||(px=1,x0={webm:"data:video/webm;base64,GkXfowEAAAAAAAAfQoaBAUL3gQFC8oEEQvOBCEKChHdlYm1Ch4EEQoWBAhhTgGcBAAAAAAAVkhFNm3RALE27i1OrhBVJqWZTrIHfTbuMU6uEFlSua1OsggEwTbuMU6uEHFO7a1OsghV17AEAAAAAAACkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVSalmAQAAAAAAAEUq17GDD0JATYCNTGF2ZjU1LjMzLjEwMFdBjUxhdmY1NS4zMy4xMDBzpJBlrrXf3DCDVB8KcgbMpcr+RImIQJBgAAAAAAAWVK5rAQAAAAAAD++uAQAAAAAAADL Line truncated
NoSleep enabled for older iOS devices. This can interrupt
active or long-running network requests from completing successfully.
See https://github.com/richtr/NoSleep.js/issues/15 for more details.
`),this.noSleepTimer=window.setInterval(()=>{document.hidden||(window.location.href=window.location.href.split("#")[0],window.setTimeout(window.stop,0))},15e3),this.enabled=!0,Promise.resolve()):this.noSleepVideo.play().then(d=>(this.enabled=!0,d)).catch(d=>{throw this.enabled=!1,d})}disable(){l()?(this._wakeLock&&this._wakeLock.release(),this._wakeLock=null):i()?this.noSleepTimer&&(console.warn(`
NoSleep now disabled for older iOS devices.
`),window.clearInterval(this.noSleepTimer),this.noSleepTimer=null):this.noSleepVideo.pause(),this.enabled=!1}}return A0=c,A0}var fS=dS();const hS=aa(fS);function pS(n){if(n.length<4)return null;try{const i=parseInt(n.slice(0,2),16)&3;let l=2;if(i===0||i===3){if(n.length<l+8)return null;l+=8}if(n.length<l+2)return null;const c=parseInt(n.slice(l,l+2),16);l+=2;const u=c*2;return n.length<l+u?null:(l+=u,n.slice(l))}catch{return null}}function mS({packets:n,channels:s,onChannelCreate:i,onRunningChange:l,visible:c=!1}){const[u,p]=R.useState(!1),[d,g]=R.useState(6),[m,x]=R.useState(!1),[A,w]=R.useState(!0),[k,N]=R.useState(!1),[C,b]=R.useState(null),[B,S]=R.useState(new Map),[T,F]=R.useState([]),[M,H]=R.useState(!1),[V,j]=R.useState(null),[ee,Z]=R.useState(null),[Q,J]=R.useState(0),$=R.useRef(null),oe=R.useRef(null),me=R.useRef(!1),G=R.useRef(!1),se=R.useRef(!1),W=R.useRef(new Map),ne=R.useRef(!1),U=R.useRef(6),D=R.useRef(!0),z=R.useRef(!1),q=R.useRef(new Set),K=R.useRef(new Set);R.useEffect(()=>{const Ce=new cS;$.current=Ce,j(Ce.isGpuAvailable());const Ve=new hS;return oe.current=Ve,()=>{Ce.destroy(),$.current=null,Ve.disable(),oe.current=null}},[]),R.useEffect(()=>{!c||M||Gk(async()=>{const{ENGLISH_WORDLIST:Ce}=await import("./wordlist-BtmChKSf.js");return{ENGLISH_WORDLIST:Ce}},[]).then(({ENGLISH_WORDLIST:Ce})=>{$.current&&($.current.setWordlist(Ce),H(!0))}).catch(Ce=>{console.error("Failed to load wordlist:",Ce),vt.error("Failed to load wordlist",{description:"Cracking will not be available"})})},[c,M]),R.useEffect(()=>{const Ce=()=>{it.getUndecryptedPacketCount().then(({count:ot})=>Z(ot)).catch(()=>Z(null))};Ce();const Ve=setInterval(Ce,36e5);return()=>clearInterval(Ve)},[]);const ce=R.useMemo(()=>new Set(s.map(Ce=>Ce.key.toUpperCase())),[s]),he=n.filter(Ce=>Ce.payload_type==="GROUP_TEXT"&&!Ce.decrypted);R.useEffect(()=>{let Ce=0;S(Ve=>{const ot=new Map(Ve);let mt=!1;for(const ct of he)if(!ot.has(ct.id)){const ht=pS(ct.data);if(ht&&K.current.has(ht)){Ce++;continue}ht&&K.current.add(ht),ot.set(ct.id,{packet:ct,attempts:0,lastAttemptLength:0,status:"pending"}),mt=!0}return mt?(W.current=ot,ot):Ve}),Ce>0&&J(Ve=>Ve+Ce)},[he.length]),R.useEffect(()=>{W.current=B},[B]),R.useEffect(()=>{ne.current=m},[m]),R.useEffect(()=>{U.current=d},[d]),R.useEffect(()=>{D.current=A},[A]),R.useEffect(()=>{z.current=k},[k]),R.useEffect(()=>{q.current=new Set(he.map(Ce=>Ce.id))},[he]),R.useEffect(()=>{l==null||l(u)},[u,l]);const xe=Array.from(B.values()).filter(Ce=>Ce.status==="pending").length,pe=Array.from(B.values()).filter(Ce=>Ce.status==="cracked").length,ge=Array.from(B.values()).filter(Ce=>Ce.status==="failed").length,Be=R.useCallback(async()=>{if(se.current||!$.current||!me.current)return;const Ce=W.current;let Ve=null,ot=null;for(const[Ke,Ge]of Ce.entries())if(Ge.status==="pending"){Ve=Ge,ot=Ke;break}if(!Ve&&ne.current){const Ke=Array.from(Ce.entries()).filter(([,Ge])=>Ge.status==="failed"&&Ge.lastAttemptLength<10);Ke.length>0&&(Ke.sort((Ge,Je)=>Ge[1].lastAttemptLength-Je[1].lastAttemptLength),[ot,Ve]=Ke[0])}if(!Ve||ot===null){me.current&&setTimeout(()=>Be(),1e3);return}if(!q.current.has(ot)){S(Ke=>{const Ge=new Map(Ke);return Ge.delete(ot),Ge}),me.current&&setTimeout(()=>Be(),10);return}se.current=!0;const mt=U.current,ct=Ve.lastAttemptLength>0,ht=ct?Ve.lastAttemptLength+1:mt;try{const Ke=await $.current.crack(Ve.packet.data,{maxLength:ht,useSenderFilter:!0,useTimestampFilter:!0,useUtf8Filter:!0,...z.current&&{gpuDispatchMs:1e4},...ct&&{useDictionary:!1,startingLength:ht}},Ge=>{b(Ge)});if(G.current){G.current=!1,se.current=!1,b(null);return}if(Ke.found&&Ke.roomName&&Ke.key){S(Ue=>{const St=new Map(Ue),Kt=St.get(ot);return Kt&&St.set(ot,{...Kt,status:"cracked",attempts:Kt.attempts+1,lastAttemptLength:ht}),St});const Ge={roomName:Ke.roomName,key:Ke.key,packetId:ot,message:Ke.decryptedMessage||"",crackedAt:Date.now()};F(Ue=>[...Ue,Ge]);const Je=Ke.key.toUpperCase();if(!ce.has(Je))try{const Ue="#"+Ke.roomName;await i(Ue,Ke.key),D.current&&await it.decryptHistoricalPackets({key_type:"channel",channel_name:Ue})}catch(Ue){console.error("Failed to create channel or decrypt historical:",Ue),vt.error("Failed to save cracked channel",{description:Ue instanceof Error?Ue.message:"Channel discovered but could not be saved"})}}else S(Ge=>{const Je=new Map(Ge),Ue=Je.get(ot);return Ue&&Je.set(ot,{...Ue,status:"failed",attempts:Ue.attempts+1,lastAttemptLength:ht}),Je})}catch(Ke){console.error("Cracking error:",Ke),S(Ge=>{const Je=new Map(Ge),Ue=Je.get(ot);return Ue&&Je.set(ot,{...Ue,status:"failed",attempts:Ue.attempts+1,lastAttemptLength:ht}),Je})}se.current=!1,b(null),me.current&&setTimeout(()=>Be(),100)},[ce,i]),We=()=>{var Ce;if(!V){vt.error("WebGPU not available",{description:"Cracking requires Chrome 113+ or Edge 113+ with WebGPU support."});return}p(!0),me.current=!0,G.current=!1,(Ce=oe.current)==null||Ce.enable(),Be()},$e=()=>{var Ce,Ve;p(!1),me.current=!1,G.current=!0,(Ce=$.current)==null||Ce.abort(),(Ve=oe.current)==null| Line truncated
//# sourceMappingURL=index-DsqXtGVx.js.map
-1
View File
@@ -1 +0,0 @@
{"version":3,"mappings":";;;;;;;;6CASa,IAAIA,EAAE,OAAO,IAAI,eAAe,EAAEC,EAAE,OAAO,IAAI,cAAc,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,mBAAmB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,eAAe,EAAEC,EAAE,OAAO,IAAI,mBAAmB,EAAEC,EAAE,OAAO,IAAI,gBAAgB,EAAEC,EAAE,OAAO,IAAI,YAAY,EAAEC,EAAE,OAAO,IAAI,YAAY,EAAEC,EAAE,OAAO,SAAS,SAASC,EAAEC,EAAE,CAAC,OAAUA,IAAP,MAAqB,OAAOA,GAAlB,SAA2B,MAAKA,EAAEF,GAAGE,EAAEF,CAAC,GAAGE,EAAE,YAAY,EAAqB,OAAOA,GAApB,WAAsBA,EAAE,KAAI,CAC1e,IAAIC,EAAE,CAAC,UAAU,UAAU,CAAC,MAAM,EAAE,EAAE,mBAAmB,UAAU,GAAG,oBAAoB,UAAU,GAAG,gBAAgB,UAAU,EAAE,EAAEC,EAAE,OAAO,OAAOC,EAAE,GAAG,SAASC,EAAEJ,EAAEK,EAAEC,EAAE,CAAC,KAAK,MAAMN,EAAE,KAAK,QAAQK,EAAE,KAAK,KAAKF,EAAE,KAAK,QAAQG,GAAGL,CAAC,CAACG,EAAE,UAAU,iBAAiB,GACnQA,EAAE,UAAU,SAAS,SAASJ,EAAEK,EAAE,CAAC,GAAc,OAAOL,GAAlB,UAAkC,OAAOA,GAApB,YAA6BA,GAAN,KAAQ,MAAM,MAAM,uHAAuH,EAAE,KAAK,QAAQ,gBAAgB,KAAKA,EAAEK,EAAE,UAAU,CAAC,EAAED,EAAE,UAAU,YAAY,SAASJ,EAAE,CAAC,KAAK,QAAQ,mBAAmB,KAAKA,EAAE,aAAa,CAAC,EAAE,SAASO,GAAG,EAAEA,EAAE,UAAUH,EAAE,UAAU,SAASI,EAAER,EAAEK,EAAEC,EAAE,CAAC,KAAK,MAAMN,EAAE,KAAK,QAAQK,EAAE,KAAK,KAAKF,EAAE,KAAK,QAAQG,GAAGL,CAAC,CAAC,IAAIQ,EAAED,EAAE,UAAU,IAAID,EACrfE,EAAE,YAAYD,EAAEN,EAAEO,EAAEL,EAAE,SAAS,EAAEK,EAAE,qBAAqB,GAAG,IAAIC,EAAE,MAAM,QAAQC,EAAE,OAAO,UAAU,eAAeC,EAAE,CAAC,QAAQ,IAAI,EAAEC,EAAE,CAAC,IAAI,GAAG,IAAI,GAAG,OAAO,GAAG,SAAS,EAAE,EACxK,SAASC,EAAEd,EAAEK,EAAEC,EAAE,CAAC,IAAIS,EAAEC,GAAE,GAAGC,GAAE,KAAKC,GAAE,KAAK,GAASb,GAAN,KAAQ,IAAIU,KAAcV,EAAE,MAAX,SAAiBa,GAAEb,EAAE,KAAcA,EAAE,MAAX,SAAiBY,GAAE,GAAGZ,EAAE,KAAKA,EAAEM,EAAE,KAAKN,EAAEU,CAAC,GAAG,CAACF,EAAE,eAAeE,CAAC,IAAIC,GAAED,CAAC,EAAEV,EAAEU,CAAC,GAAG,IAAII,GAAE,UAAU,OAAO,EAAE,GAAOA,KAAJ,EAAMH,GAAE,SAASV,UAAU,EAAEa,GAAE,CAAC,QAAQC,GAAE,MAAMD,EAAC,EAAEE,GAAE,EAAEA,GAAEF,GAAEE,KAAID,GAAEC,EAAC,EAAE,UAAUA,GAAE,CAAC,EAAEL,GAAE,SAASI,EAAC,CAAC,GAAGpB,GAAGA,EAAE,aAAa,IAAIe,KAAKI,GAAEnB,EAAE,aAAamB,GAAWH,GAAED,CAAC,IAAZ,SAAgBC,GAAED,CAAC,EAAEI,GAAEJ,CAAC,GAAG,MAAM,CAAC,SAAS5B,EAAE,KAAKa,EAAE,IAAIiB,GAAE,IAAIC,GAAE,MAAMF,GAAE,OAAOJ,EAAE,OAAO,CAAC,CAC7a,SAASU,GAAEtB,EAAEK,EAAE,CAAC,MAAM,CAAC,SAASlB,EAAE,KAAKa,EAAE,KAAK,IAAIK,EAAE,IAAIL,EAAE,IAAI,MAAMA,EAAE,MAAM,OAAOA,EAAE,MAAM,CAAC,CAAC,SAASuB,EAAEvB,EAAE,CAAC,OAAiB,OAAOA,GAAlB,UAA4BA,IAAP,MAAUA,EAAE,WAAWb,CAAC,CAAC,SAASqC,EAAOxB,EAAE,CAAC,IAAIK,EAAE,CAAC,IAAI,KAAK,IAAI,IAAI,EAAE,MAAM,IAAIL,EAAE,QAAQ,QAAQ,SAASA,EAAE,CAAC,OAAOK,EAAEL,CAAC,CAAC,CAAC,CAAC,CAAC,IAAIyB,EAAE,OAAO,SAASC,EAAE1B,EAAEK,EAAE,CAAC,OAAiB,OAAOL,GAAlB,UAA4BA,IAAP,MAAgBA,EAAE,KAAR,KAAYwB,EAAO,GAAGxB,EAAE,GAAG,EAAEK,EAAE,SAAS,EAAE,CAAC,CAC/W,SAASsB,GAAE3B,EAAEK,EAAEC,EAAES,EAAEC,GAAE,CAAC,IAAIC,GAAE,OAAOjB,GAAmBiB,KAAd,aAA6BA,KAAZ,aAAcjB,EAAE,MAAK,IAAIkB,GAAE,GAAG,GAAUlB,IAAP,KAASkB,GAAE,OAAQ,QAAOD,GAAC,CAAE,IAAK,SAAS,IAAK,SAASC,GAAE,GAAG,MAAM,IAAK,SAAS,OAAOlB,EAAE,SAAQ,CAAE,KAAKb,EAAE,KAAKC,EAAE8B,GAAE,EAAE,CAAC,CAAC,GAAGA,GAAE,OAAOA,GAAElB,EAAEgB,GAAEA,GAAEE,EAAC,EAAElB,EAAOe,IAAL,GAAO,IAAIW,EAAER,GAAE,CAAC,EAAEH,EAAEL,EAAEM,EAAC,GAAGV,EAAE,GAASN,GAAN,OAAUM,EAAEN,EAAE,QAAQyB,EAAE,KAAK,EAAE,KAAKE,GAAEX,GAAEX,EAAEC,EAAE,GAAG,SAASN,GAAE,CAAC,OAAOA,EAAC,CAAC,GAASgB,IAAN,OAAUO,EAAEP,EAAC,IAAIA,GAAEM,GAAEN,GAAEV,GAAG,CAACU,GAAE,KAAKE,IAAGA,GAAE,MAAMF,GAAE,IAAI,IAAI,GAAGA,GAAE,KAAK,QAAQS,EAAE,KAAK,EAAE,KAAKzB,CAAC,GAAGK,EAAE,KAAKW,EAAC,GAAG,EAAyB,GAAvBE,GAAE,EAAEH,EAAOA,IAAL,GAAO,IAAIA,EAAE,IAAOL,EAAEV,CAAC,EAAE,QAAQmB,GAAE,EAAEA,GAAEnB,EAAE,OAAOmB,KAAI,CAACF,GACrfjB,EAAEmB,EAAC,EAAE,IAAIC,GAAEL,EAAEW,EAAET,GAAEE,EAAC,EAAED,IAAGS,GAAEV,GAAEZ,EAAEC,EAAEc,GAAEJ,EAAC,CAAC,SAASI,GAAErB,EAAEC,CAAC,EAAe,OAAOoB,IAApB,WAAsB,IAAIpB,EAAEoB,GAAE,KAAKpB,CAAC,EAAEmB,GAAE,EAAE,EAAEF,GAAEjB,EAAE,KAAI,GAAI,MAAMiB,GAAEA,GAAE,MAAMG,GAAEL,EAAEW,EAAET,GAAEE,IAAG,EAAED,IAAGS,GAAEV,GAAEZ,EAAEC,EAAEc,GAAEJ,EAAC,UAAqBC,KAAX,SAAa,MAAMZ,EAAE,OAAOL,CAAC,EAAE,MAAM,mDAAuEK,IAApB,kBAAsB,qBAAqB,OAAO,KAAKL,CAAC,EAAE,KAAK,IAAI,EAAE,IAAIK,GAAG,2EAA2E,EAAE,OAAOa,EAAC,CACzZ,SAASU,GAAE5B,EAAEK,EAAEC,EAAE,CAAC,GAASN,GAAN,KAAQ,OAAOA,EAAE,IAAIe,EAAE,GAAGC,GAAE,EAAE,OAAAW,GAAE3B,EAAEe,EAAE,GAAG,GAAG,SAASf,GAAE,CAAC,OAAOK,EAAE,KAAKC,EAAEN,GAAEgB,IAAG,CAAC,CAAC,EAASD,CAAC,CAAC,SAASc,EAAE7B,EAAE,CAAC,GAAQA,EAAE,UAAP,GAAe,CAAC,IAAIK,EAAEL,EAAE,QAAQK,EAAEA,EAAC,EAAGA,EAAE,KAAK,SAASA,EAAE,EAAQL,EAAE,UAAN,GAAoBA,EAAE,UAAP,MAAeA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAC,EAAE,SAASA,EAAE,EAAQL,EAAE,UAAN,GAAoBA,EAAE,UAAP,MAAeA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAC,CAAC,EAAOL,EAAE,UAAP,KAAiBA,EAAE,QAAQ,EAAEA,EAAE,QAAQK,EAAE,CAAC,GAAOL,EAAE,UAAN,EAAc,OAAOA,EAAE,QAAQ,QAAQ,MAAMA,EAAE,OAAQ,CAC5Z,IAAI8B,GAAE,CAAC,QAAQ,IAAI,EAAEC,EAAE,CAAC,WAAW,IAAI,EAAEC,GAAE,CAAC,uBAAuBF,GAAE,wBAAwBC,EAAE,kBAAkBnB,CAAC,EAAE,SAASqB,GAAG,CAAC,MAAM,MAAM,0DAA0D,CAAE,CACzM,OAAAC,GAAA,SAAiB,CAAC,IAAIN,GAAE,QAAQ,SAAS5B,EAAEK,EAAEC,EAAE,CAACsB,GAAE5B,EAAE,UAAU,CAACK,EAAE,MAAM,KAAK,SAAS,CAAC,EAAEC,CAAC,CAAC,EAAE,MAAM,SAASN,EAAE,CAAC,IAAIK,EAAE,EAAE,OAAAuB,GAAE5B,EAAE,UAAU,CAACK,GAAG,CAAC,EAASA,CAAC,EAAE,QAAQ,SAASL,EAAE,CAAC,OAAO4B,GAAE5B,EAAE,SAASA,EAAE,CAAC,OAAOA,CAAC,CAAC,GAAG,EAAE,EAAE,KAAK,SAASA,EAAE,CAAC,GAAG,CAACuB,EAAEvB,CAAC,EAAE,Line truncated
+2 -2
View File
@@ -13,8 +13,8 @@
<link rel="shortcut icon" href="/favicon.ico" />
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="manifest" href="/site.webmanifest" />
<script type="module" crossorigin src="/assets/index-DsqXtGVx.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Cxcg9Mr6.css">
<script type="module" crossorigin src="/assets/index-DpuVn1aK.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-B-EWrA2Q.css">
</head>
<body>
<div id="root"></div>
+30 -2
View File
@@ -1,12 +1,12 @@
{
"name": "remoteterm-meshcore-frontend",
"version": "1.4.1",
"version": "1.5.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "remoteterm-meshcore-frontend",
"version": "1.4.1",
"version": "1.5.0",
"dependencies": {
"@michaelhart/meshcore-decoder": "^0.2.7",
"@radix-ui/react-checkbox": "^1.3.3",
@@ -15,6 +15,7 @@
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@types/prismjs": "^1.26.5",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"d3-force": "^3.0.0",
@@ -22,9 +23,11 @@
"lucide-react": "^0.562.0",
"meshcore-hashtag-cracker": "^1.6.0",
"nosleep.js": "^0.12.0",
"prismjs": "^1.30.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-leaflet": "^4.2.1",
"react-simple-code-editor": "^0.14.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7"
@@ -1521,6 +1524,12 @@
"undici-types": "~7.16.0"
}
},
"node_modules/@types/prismjs": {
"version": "1.26.5",
"resolved": "https://registry.npmjs.org/@types/prismjs/-/prismjs-1.26.5.tgz",
"integrity": "sha512-AUZTa7hQ2KY5L7AmtSiqxlhWxb4ina0yd8hNbl4TWuqnv/pFP0nDMb3YrfSBf4hJVGLh2YEIBfKaBW/9UEl6IQ==",
"license": "MIT"
},
"node_modules/@types/prop-types": {
"version": "15.7.15",
"devOptional": true,
@@ -3953,6 +3962,15 @@
"node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
}
},
"node_modules/prismjs": {
"version": "1.30.0",
"resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
"integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"dev": true,
@@ -4071,6 +4089,16 @@
}
}
},
"node_modules/react-simple-code-editor": {
"version": "0.14.1",
"resolved": "https://registry.npmjs.org/react-simple-code-editor/-/react-simple-code-editor-0.14.1.tgz",
"integrity": "sha512-BR5DtNRy+AswWJECyA17qhUDvrrCZ6zXOCfkQY5zSmb96BVUbpVAv03WpcjcwtCwiLbIANx3gebHOcXYn1EHow==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/react-style-singleton": {
"version": "2.2.3",
"license": "MIT",
+3
View File
@@ -22,6 +22,7 @@
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tabs": "^1.1.13",
"@types/prismjs": "^1.26.5",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"d3-force": "^3.0.0",
@@ -29,9 +30,11 @@
"lucide-react": "^0.562.0",
"meshcore-hashtag-cracker": "^1.6.0",
"nosleep.js": "^0.12.0",
"prismjs": "^1.30.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-leaflet": "^4.2.1",
"react-simple-code-editor": "^0.14.1",
"sonner": "^2.0.7",
"tailwind-merge": "^3.4.0",
"tailwindcss-animate": "^1.0.7"
+136 -3
View File
@@ -1,4 +1,8 @@
import { useState, useEffect, useMemo } from 'react';
import Editor from 'react-simple-code-editor';
import { highlight, languages } from 'prismjs';
import 'prismjs/components/prism-python';
import 'prismjs/themes/prism-tomorrow.css';
import type {
AppSettings,
AppSettingsUpdate,
@@ -73,7 +77,7 @@ export function SettingsModal({
onRefreshAppSettings,
}: SettingsModalProps) {
// Tab state
type SettingsTab = 'radio' | 'identity' | 'serial' | 'database' | 'advertise';
type SettingsTab = 'radio' | 'identity' | 'serial' | 'database' | 'advertise' | 'bot';
const [activeTab, setActiveTab] = useState<SettingsTab>('radio');
// Radio config state
@@ -103,6 +107,31 @@ export function SettingsModal({
// Advertisement interval state
const [advertInterval, setAdvertInterval] = useState('0');
// Bot state
const DEFAULT_BOT_CODE = `def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
"""
Process incoming messages and optionally return a reply.
Args:
sender_name: Display name of sender (may be None)
sender_key: 64-char hex public key (empty for channel msgs)
message_text: The message content
is_dm: True for direct messages, False for channel
channel_key: 32-char hex key for channels, None for DMs
channel_name: Channel name with hash (e.g. "#bot"), None for DMs
sender_timestamp: Sender's timestamp (unix seconds, may be None)
path: Hex-encoded routing path (may be None)
Returns:
None for no reply, or a string to send as reply
"""
# Example: Only respond in #bot channel to "!pling" command
if channel_name == "#bot" and "!pling" in message_text.lower():
return "[BOT] Plong!"
return None`;
const [botEnabled, setBotEnabled] = useState(false);
const [botCode, setBotCode] = useState(DEFAULT_BOT_CODE);
useEffect(() => {
if (config) {
setName(config.name);
@@ -121,6 +150,11 @@ export function SettingsModal({
setMaxRadioContacts(String(appSettings.max_radio_contacts));
setAutoDecryptOnAdvert(appSettings.auto_decrypt_dm_on_advert);
setAdvertInterval(String(appSettings.advert_interval));
setBotEnabled(appSettings.bot_enabled);
// Only overwrite bot code if user has saved custom code
if (appSettings.bot_code) {
setBotCode(appSettings.bot_code);
}
}
}, [appSettings]);
@@ -354,9 +388,25 @@ export function SettingsModal({
}
};
const handleSaveBotSettings = async () => {
setLoading(true);
setError('');
try {
await onSaveAppSettings({ bot_enabled: botEnabled, bot_code: botCode });
toast.success('Bot settings saved');
} catch (err) {
console.error('Failed to save bot settings:', err);
setError(err instanceof Error ? err.message : 'Failed to save');
toast.error('Failed to save settings');
} finally {
setLoading(false);
}
};
return (
<Dialog open={open} onOpenChange={(isOpen) => !isOpen && onClose()}>
<DialogContent className="sm:max-w-[500px] max-h-[90vh] overflow-y-auto">
<DialogContent className="sm:max-w-[50vw] sm:min-w-[500px] max-h-[90vh] overflow-y-auto">
<DialogHeader>
<DialogTitle>Radio & Settings</DialogTitle>
<DialogDescription className="sr-only">
@@ -366,6 +416,7 @@ export function SettingsModal({
{activeTab === 'serial' && 'View serial port connection and configure contact sync'}
{activeTab === 'database' && 'View database statistics and clean up old packets'}
{activeTab === 'advertise' && 'Send a flood advertisement to announce your presence'}
{activeTab === 'bot' && 'Configure automatic message bot with Python code'}
</DialogDescription>
</DialogHeader>
@@ -377,12 +428,13 @@ export function SettingsModal({
onValueChange={(v) => setActiveTab(v as SettingsTab)}
className="w-full"
>
<TabsList className="grid w-full grid-cols-5">
<TabsList className="grid w-full grid-cols-6">
<TabsTrigger value="radio">Radio</TabsTrigger>
<TabsTrigger value="identity">Identity</TabsTrigger>
<TabsTrigger value="serial">Serial</TabsTrigger>
<TabsTrigger value="database">Database</TabsTrigger>
<TabsTrigger value="advertise">Advertise</TabsTrigger>
<TabsTrigger value="bot">Bot</TabsTrigger>
</TabsList>
{/* Radio Config Tab */}
@@ -747,6 +799,87 @@ export function SettingsModal({
)}
</div>
</TabsContent>
{/* Bot Tab */}
<TabsContent value="bot" className="space-y-4 mt-4">
<div className="p-3 bg-yellow-500/10 border border-yellow-500/30 rounded-md">
<p className="text-sm text-yellow-500">
<strong>Security Warning:</strong> This feature executes arbitrary Python code on
the server. Only enable if you understand the security implications.
</p>
</div>
<div className="space-y-3">
<label className="flex items-center gap-3 cursor-pointer">
<input
type="checkbox"
checked={botEnabled}
onChange={(e) => setBotEnabled(e.target.checked)}
className="w-4 h-4 rounded border-input accent-primary"
/>
<span className="text-sm font-medium">Enable Message Bot</span>
</label>
</div>
<Separator />
<div className="space-y-2">
<div className="flex items-center justify-between">
<Label htmlFor="bot-code">Bot Code (Python)</Label>
<Button
type="button"
variant="outline"
size="sm"
onClick={() => setBotCode(DEFAULT_BOT_CODE)}
disabled={!botEnabled}
>
Reset to Example
</Button>
</div>
<p className="text-xs text-muted-foreground">
Define a <code className="bg-muted px-1 rounded">bot()</code> function that
receives message data and optionally returns a reply string.
</p>
<div
className={`rounded-md border border-input bg-[#2d2d2d] overflow-auto h-64 ${!botEnabled ? 'opacity-50 pointer-events-none' : ''}`}
>
<Editor
value={botCode}
onValueChange={setBotCode}
highlight={(code) => highlight(code, languages.python, 'python')}
padding={12}
style={{
fontFamily:
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace',
fontSize: 13,
minHeight: '100%',
}}
textareaId="bot-code"
disabled={!botEnabled}
/>
</div>
</div>
<div className="text-xs text-muted-foreground space-y-1">
<p>
<strong>Available:</strong> Standard Python libraries and any modules installed in
the server environment.
</p>
<p>
<strong>Limits:</strong> 10 second timeout, max 3 concurrent executions.
</p>
<p>
<strong>Note:</strong> Bot only responds to incoming messages, not your own. For
channel messages, <code>sender_key</code> is <code>None</code>.
</p>
</div>
{error && <div className="text-sm text-destructive">{error}</div>}
<Button onClick={handleSaveBotSettings} disabled={loading} className="w-full">
{loading ? 'Saving...' : 'Save Bot Settings'}
</Button>
</TabsContent>
</Tabs>
)}
</DialogContent>
+4
View File
@@ -134,6 +134,8 @@ export interface AppSettings {
last_message_times: Record<string, number>;
preferences_migrated: boolean;
advert_interval: number;
bot_enabled: boolean;
bot_code: string;
}
export interface AppSettingsUpdate {
@@ -141,6 +143,8 @@ export interface AppSettingsUpdate {
auto_decrypt_dm_on_advert?: boolean;
sidebar_sort_order?: 'recent' | 'alpha';
advert_interval?: number;
bot_enabled?: boolean;
bot_code?: string;
}
export interface MigratePreferencesRequest {
+383
View File
@@ -0,0 +1,383 @@
"""Tests for the bot execution module."""
from unittest.mock import AsyncMock, MagicMock, patch
import pytest
from app.bot import (
_bot_semaphore,
execute_bot_code,
run_bot_for_message,
)
class TestExecuteBotCode:
"""Test bot code execution."""
def test_valid_code_returning_string(self):
"""Bot code that returns a string works correctly."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
return f"Hello, {sender_name}!"
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result == "Hello, Alice!"
def test_valid_code_returning_none(self):
"""Bot code that returns None works correctly."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
return None
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_empty_string_response_treated_as_none(self):
"""Bot returning empty/whitespace string is treated as None."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
return " "
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_code_with_syntax_error(self):
"""Bot code with syntax error returns None."""
code = """
def bot(sender_name:
return "broken"
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_code_without_bot_function(self):
"""Code that doesn't define 'bot' function returns None."""
code = """
def my_function():
return "hello"
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_bot_not_callable(self):
"""Code where 'bot' is not callable returns None."""
code = """
bot = "I'm a string, not a function"
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_bot_function_raises_exception(self):
"""Bot function that raises exception returns None."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
raise ValueError("oops!")
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_bot_returns_non_string(self):
"""Bot function returning non-string returns None."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
return 42
"""
result = execute_bot_code(
code=code,
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_empty_code_returns_none(self):
"""Empty bot code returns None."""
result = execute_bot_code(
code="",
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_whitespace_only_code_returns_none(self):
"""Whitespace-only bot code returns None."""
result = execute_bot_code(
code=" \n\t ",
sender_name="Alice",
sender_key="abc123",
message_text="Hi",
is_dm=True,
channel_key=None,
channel_name=None,
sender_timestamp=None,
path=None,
)
assert result is None
def test_bot_receives_all_parameters(self):
"""Bot function receives all expected parameters."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
# Verify all params are accessible
parts = [
f"name={sender_name}",
f"key={sender_key}",
f"msg={message_text}",
f"dm={is_dm}",
f"ch_key={channel_key}",
f"ch_name={channel_name}",
f"ts={sender_timestamp}",
f"path={path}",
]
return "|".join(parts)
"""
result = execute_bot_code(
code=code,
sender_name="Bob",
sender_key="def456",
message_text="Test",
is_dm=False,
channel_key="AABBCCDD",
channel_name="#test",
sender_timestamp=12345,
path="001122",
)
assert (
result
== "name=Bob|key=def456|msg=Test|dm=False|ch_key=AABBCCDD|ch_name=#test|ts=12345|path=001122"
)
def test_channel_message_with_none_sender_key(self):
"""Channel messages correctly pass None for sender_key."""
code = """
def bot(sender_name, sender_key, message_text, is_dm, channel_key, channel_name, sender_timestamp, path):
if sender_key is None and not is_dm:
return "channel message detected"
return "unexpected"
"""
result = execute_bot_code(
code=code,
sender_name="Someone",
sender_key=None, # Channel messages don't have sender key
message_text="Test",
is_dm=False,
channel_key="AABBCCDD",
channel_name="#general",
sender_timestamp=None,
path=None,
)
assert result == "channel message detected"
class TestRunBotForMessage:
"""Test the main bot entry point."""
@pytest.fixture(autouse=True)
def reset_semaphore(self):
"""Reset semaphore state between tests."""
# Ensure semaphore is fully released
while _bot_semaphore.locked():
_bot_semaphore.release()
yield
@pytest.mark.asyncio
async def test_skips_outgoing_messages(self):
"""Bot is not triggered for outgoing messages."""
with patch("app.repository.AppSettingsRepository") as mock_repo:
await run_bot_for_message(
sender_name="Me",
sender_key="abc123",
message_text="Hello",
is_dm=True,
channel_key=None,
is_outgoing=True,
)
# Should not even check settings
mock_repo.get.assert_not_called()
@pytest.mark.asyncio
async def test_skips_when_bot_disabled(self):
"""Bot is not triggered when disabled in settings."""
with patch("app.repository.AppSettingsRepository") as mock_repo:
mock_settings = MagicMock()
mock_settings.bot_enabled = False
mock_settings.bot_code = "def bot(): pass"
mock_repo.get = AsyncMock(return_value=mock_settings)
with patch("app.bot.execute_bot_code") as mock_exec:
await run_bot_for_message(
sender_name="Alice",
sender_key="abc123",
message_text="Hello",
is_dm=True,
channel_key=None,
)
mock_exec.assert_not_called()
@pytest.mark.asyncio
async def test_skips_when_bot_code_empty(self):
"""Bot is not triggered when code is empty."""
with patch("app.repository.AppSettingsRepository") as mock_repo:
mock_settings = MagicMock()
mock_settings.bot_enabled = True
mock_settings.bot_code = ""
mock_repo.get = AsyncMock(return_value=mock_settings)
with patch("app.bot.execute_bot_code") as mock_exec:
await run_bot_for_message(
sender_name="Alice",
sender_key="abc123",
message_text="Hello",
is_dm=True,
channel_key=None,
)
mock_exec.assert_not_called()
@pytest.mark.asyncio
async def test_rechecks_settings_after_sleep(self):
"""Settings are re-checked after 2 second sleep."""
with patch("app.repository.AppSettingsRepository") as mock_repo:
# First call: bot enabled
# Second call (after sleep): bot disabled
mock_settings_enabled = MagicMock()
mock_settings_enabled.bot_enabled = True
mock_settings_enabled.bot_code = "def bot(): return 'hi'"
mock_settings_disabled = MagicMock()
mock_settings_disabled.bot_enabled = False
mock_settings_disabled.bot_code = "def bot(): return 'hi'"
mock_repo.get = AsyncMock(side_effect=[mock_settings_enabled, mock_settings_disabled])
with (
patch("app.bot.asyncio.sleep", new_callable=AsyncMock) as mock_sleep,
patch("app.bot.execute_bot_code") as mock_exec,
):
await run_bot_for_message(
sender_name="Alice",
sender_key="abc123",
message_text="Hello",
is_dm=True,
channel_key=None,
)
# Should have slept
mock_sleep.assert_called_once_with(2)
# Should NOT have executed bot (disabled after sleep)
mock_exec.assert_not_called()
class TestBotCodeValidation:
"""Test bot code syntax validation on save."""
def test_valid_code_passes(self):
"""Valid Python code passes validation."""
from app.routers.settings import validate_bot_code
# Should not raise
validate_bot_code("def bot(): return 'hello'")
def test_syntax_error_raises(self):
"""Syntax error in code raises HTTPException."""
from fastapi import HTTPException
from app.routers.settings import validate_bot_code
with pytest.raises(HTTPException) as exc_info:
validate_bot_code("def bot(:\n return 'broken'")
assert exc_info.value.status_code == 400
assert "syntax error" in exc_info.value.detail.lower()
def test_empty_code_passes(self):
"""Empty code passes validation (disables bot)."""
from app.routers.settings import validate_bot_code
# Should not raise
validate_bot_code("")
validate_bot_code(" ")
+3
View File
@@ -192,6 +192,7 @@ class TestContactMessageCLIFiltering:
patch("app.event_handlers.MessageRepository") as mock_repo,
patch("app.event_handlers.ContactRepository") as mock_contact_repo,
patch("app.event_handlers.broadcast_event") as mock_broadcast,
patch("app.bot.run_bot_for_message", new_callable=AsyncMock),
):
mock_repo.create = AsyncMock(return_value=42)
mock_contact_repo.get_by_key_prefix = AsyncMock(return_value=None)
@@ -220,6 +221,7 @@ class TestContactMessageCLIFiltering:
patch("app.event_handlers.MessageRepository") as mock_repo,
patch("app.event_handlers.ContactRepository") as mock_contact_repo,
patch("app.event_handlers.broadcast_event") as mock_broadcast,
patch("app.bot.run_bot_for_message", new_callable=AsyncMock),
):
mock_repo.create = AsyncMock(return_value=42)
mock_contact_repo.get_by_key_prefix = AsyncMock(return_value=None)
@@ -254,6 +256,7 @@ class TestContactMessageCLIFiltering:
patch("app.event_handlers.MessageRepository") as mock_repo,
patch("app.event_handlers.ContactRepository") as mock_contact_repo,
patch("app.event_handlers.broadcast_event"),
patch("app.bot.run_bot_for_message", new_callable=AsyncMock),
):
mock_repo.create = AsyncMock(return_value=42)
mock_contact_repo.get_by_key_prefix = AsyncMock(return_value=None)
+6 -6
View File
@@ -100,8 +100,8 @@ class TestMigration001:
# Run migrations
applied = await run_migrations(conn)
assert applied == 11 # All 11 migrations run
assert await get_version(conn) == 11
assert applied == 12 # All 11 migrations run
assert await get_version(conn) == 12
# Verify columns exist by inserting and selecting
await conn.execute(
@@ -183,9 +183,9 @@ class TestMigration001:
applied1 = await run_migrations(conn)
applied2 = await run_migrations(conn)
assert applied1 == 11 # All 11 migrations run
assert applied1 == 12 # All 11 migrations run
assert applied2 == 0 # No migrations on second run
assert await get_version(conn) == 11
assert await get_version(conn) == 12
finally:
await conn.close()
@@ -246,8 +246,8 @@ class TestMigration001:
applied = await run_migrations(conn)
# All 11 migrations applied (version incremented) but no error
assert applied == 11
assert await get_version(conn) == 11
assert applied == 12
assert await get_version(conn) == 12
finally:
await conn.close()