Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
ba47e16b75
|
|||
|
578e80023f
|
|||
|
b7dcee4c06
|
|||
|
e44ec59b6e
|
|||
|
45379e6df1
|
|||
|
308f1f6459
|
|||
| 424ff116d1 | |||
|
|
73f677d319 | ||
|
4770c21499
|
|||
|
720bef90c7
|
|||
|
1c98a231fd
|
|||
|
f6a1be5e80
|
36
.github/workflows/build.yml
vendored
36
.github/workflows/build.yml
vendored
@@ -4,10 +4,33 @@ on:
|
||||
push:
|
||||
tags:
|
||||
- "*"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
build_windows:
|
||||
description: 'Build Windows'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
build_mac:
|
||||
description: 'Build macOS'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
build_linux:
|
||||
description: 'Build Linux'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
build_docker:
|
||||
description: 'Build Docker'
|
||||
required: false
|
||||
default: 'true'
|
||||
type: boolean
|
||||
|
||||
jobs:
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_windows == 'true')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -49,6 +72,7 @@ jobs:
|
||||
|
||||
build_mac:
|
||||
runs-on: macos-13
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_mac == 'true')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -90,6 +114,7 @@ jobs:
|
||||
|
||||
build_linux:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_linux == 'true')
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
@@ -134,6 +159,7 @@ jobs:
|
||||
|
||||
build_docker:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.build_docker == 'true')
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
@@ -164,9 +190,9 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: >-
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchat:latest,
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchat:${{ github.ref_name }}
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchatx:latest,
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchatx:${{ github.ref_name }}
|
||||
labels: >-
|
||||
org.opencontainers.image.title=Reticulum MeshChat,
|
||||
org.opencontainers.image.description=Docker image for Reticulum MeshChat,
|
||||
org.opencontainers.image.url=https://github.com/${{ github.repository }}/pkgs/container/reticulum-meshchat/
|
||||
org.opencontainers.image.title=Reticulum MeshChatX,
|
||||
org.opencontainers.image.description=Docker image for Reticulum MeshChatX,
|
||||
org.opencontainers.image.url=https://github.com/${{ github.repository }}/pkgs/container/reticulum-meshchatx/
|
||||
|
||||
45
.github/workflows/manual-docker-build.yml
vendored
45
.github/workflows/manual-docker-build.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: Temporary manual trigger for Docker build
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build_docker:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
packages: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Clone Repo
|
||||
uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 # v4
|
||||
|
||||
- name: Set lowercase repository owner
|
||||
run: echo "REPO_OWNER_LC=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392 # v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 # v3
|
||||
|
||||
- name: Log in to the GitHub Container registry
|
||||
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build and push Docker images
|
||||
uses: docker/build-push-action@ca052bb54ab0790a636c9b5f226502c73d547a25 # v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: >-
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchat:latest,
|
||||
ghcr.io/${{ env.REPO_OWNER_LC }}/reticulum-meshchat:${{ github.ref_name }}
|
||||
labels: >-
|
||||
org.opencontainers.image.title=Reticulum MeshChat,
|
||||
org.opencontainers.image.description=Docker image for Reticulum MeshChat,
|
||||
org.opencontainers.image.url=https://github.com/${{ github.repository }}/pkgs/container/reticulum-meshchat/
|
||||
|
||||
@@ -16,7 +16,8 @@ A heavily customized fork of [Reticulum MeshChat](https://github.com/liamcottle/
|
||||
- [x] Docker images are smaller and use SHA256 hashes for the images.
|
||||
- [x] Electron improvements.
|
||||
- [x] Latest updates for NPM and Python dependencies (bleeding edge)
|
||||
- [x] Ruff linting, CodeQL Advanced and Bearer SAST fixes.
|
||||
- [x] Numerous Ruff, Deepsource, CodeQL Advanced and Bearer Linting/SAST fixes.
|
||||
- [x] Some performance improvements.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
31
TODO.md
31
TODO.md
@@ -1,31 +0,0 @@
|
||||
1. for messages fix:
|
||||
|
||||
convo goes off edge, near edge should be ... 3 dots
|
||||
|
||||
long names push the last message/announced seconds/time to right and nearly off the side, fix please
|
||||
|
||||
2. interfaces:
|
||||
|
||||
3 dots background circle is a oval, fix to be circle
|
||||
|
||||
on 3 dots clicked there is still white background the buttons have dark backgrounds though but main dropdown window is white fix depdning on theme
|
||||
|
||||
also on 3 dots drop down it still makes me scroll down in that interfaces window, we can expand that interfaces box os something so this crap doesnt hapen or if dropdown is above it
|
||||
|
||||
rework propagation nodes page with new UI/UX please like rest of app.
|
||||
|
||||
1. the attachment dropups/popups are white on dark mode, they need a ui/ux rework.
|
||||
|
||||
2. for settings add ability to set inbound stamp, ref lxmf via python -c if needed.
|
||||
|
||||
3. add multi-identity / account suport and a switcher at bottom with ability to create, delete or import/export identies from other apps.
|
||||
|
||||
for all this you will likely need to look at my ren chat app for stamps, multi-identity, /mnt/projects/ren-messenger/
|
||||
|
||||
its pretty simple.
|
||||
|
||||
translator tool
|
||||
reticulum documentation tool
|
||||
lxmfy bot tool
|
||||
page downloader tool
|
||||
page snapshots
|
||||
@@ -1,7 +1,7 @@
|
||||
services:
|
||||
reticulum-meshchat:
|
||||
container_name: reticulum-meshchat
|
||||
image: ghcr.io/sudo-ivan/reticulum-meshchat:latest
|
||||
reticulum-meshchatx:
|
||||
container_name: reticulum-meshchatx
|
||||
image: ghcr.io/sudo-ivan/reticulum-meshchatx:latest
|
||||
pull_policy: always
|
||||
restart: unless-stopped
|
||||
# Make the meshchat web interface accessible from the host on port 8000
|
||||
|
||||
89
meshchat.py
89
meshchat.py
@@ -221,7 +221,8 @@ class ReticulumMeshChat:
|
||||
thread.start()
|
||||
|
||||
# gets app version from package.json
|
||||
def get_app_version(self) -> str:
|
||||
@staticmethod
|
||||
def get_app_version() -> str:
|
||||
with open(get_file_path("package.json")) as f:
|
||||
package_json = json.load(f)
|
||||
return package_json["version"]
|
||||
@@ -447,7 +448,8 @@ class ReticulumMeshChat:
|
||||
)
|
||||
return query.exists()
|
||||
|
||||
def message_fields_have_attachments(self, fields_json: str | None):
|
||||
@staticmethod
|
||||
def message_fields_have_attachments(fields_json: str | None):
|
||||
if not fields_json:
|
||||
return False
|
||||
try:
|
||||
@@ -491,7 +493,8 @@ class ReticulumMeshChat:
|
||||
|
||||
return matches
|
||||
|
||||
def parse_bool_query_param(self, value: str | None) -> bool:
|
||||
@staticmethod
|
||||
def parse_bool_query_param(value: str | None) -> bool:
|
||||
if value is None:
|
||||
return False
|
||||
value = value.lower()
|
||||
@@ -1986,14 +1989,14 @@ class ReticulumMeshChat:
|
||||
nomadnetwork_node_announce is not None
|
||||
and nomadnetwork_node_announce.app_data is not None
|
||||
):
|
||||
operator_display_name = self.parse_nomadnetwork_node_display_name(
|
||||
operator_display_name = ReticulumMeshChat.parse_nomadnetwork_node_display_name(
|
||||
nomadnetwork_node_announce.app_data, None,
|
||||
)
|
||||
|
||||
# parse app_data so we can see if propagation is enabled or disabled for this node
|
||||
is_propagation_enabled = None
|
||||
per_transfer_limit = None
|
||||
propagation_node_data = self.parse_lxmf_propagation_node_app_data(
|
||||
propagation_node_data = ReticulumMeshChat.parse_lxmf_propagation_node_app_data(
|
||||
announce.app_data,
|
||||
)
|
||||
if propagation_node_data is not None:
|
||||
@@ -2753,8 +2756,8 @@ class ReticulumMeshChat:
|
||||
other_user_hash,
|
||||
),
|
||||
"destination_hash": other_user_hash,
|
||||
"is_unread": self.is_lxmf_conversation_unread(other_user_hash),
|
||||
"failed_messages_count": self.lxmf_conversation_failed_messages_count(
|
||||
"is_unread": ReticulumMeshChat.is_lxmf_conversation_unread(other_user_hash),
|
||||
"failed_messages_count": ReticulumMeshChat.lxmf_conversation_failed_messages_count(
|
||||
other_user_hash,
|
||||
),
|
||||
"has_attachments": has_attachments,
|
||||
@@ -3167,7 +3170,8 @@ class ReticulumMeshChat:
|
||||
# to the following map:
|
||||
# - var_field1: 123
|
||||
# - var_field2: 456
|
||||
def convert_nomadnet_string_data_to_map(self, path_data: str | None):
|
||||
@staticmethod
|
||||
def convert_nomadnet_string_data_to_map(path_data: str | None):
|
||||
data = {}
|
||||
if path_data is not None:
|
||||
for field in path_data.split("|"):
|
||||
@@ -3178,7 +3182,8 @@ class ReticulumMeshChat:
|
||||
print(f"unhandled field: {field}")
|
||||
return data
|
||||
|
||||
def convert_nomadnet_field_data_to_map(self, field_data):
|
||||
@staticmethod
|
||||
def convert_nomadnet_field_data_to_map(field_data):
|
||||
data = {}
|
||||
if field_data is not None or "{}":
|
||||
try:
|
||||
@@ -3681,7 +3686,8 @@ class ReticulumMeshChat:
|
||||
}
|
||||
|
||||
# convert lxmf state to a human friendly string
|
||||
def convert_lxmf_state_to_string(self, lxmf_message: LXMF.LXMessage):
|
||||
@staticmethod
|
||||
def convert_lxmf_state_to_string(lxmf_message: LXMF.LXMessage):
|
||||
# convert state to string
|
||||
lxmf_message_state = "unknown"
|
||||
if lxmf_message.state == LXMF.LXMessage.GENERATING:
|
||||
@@ -3704,7 +3710,8 @@ class ReticulumMeshChat:
|
||||
return lxmf_message_state
|
||||
|
||||
# convert lxmf method to a human friendly string
|
||||
def convert_lxmf_method_to_string(self, lxmf_message: LXMF.LXMessage):
|
||||
@staticmethod
|
||||
def convert_lxmf_method_to_string(lxmf_message: LXMF.LXMessage):
|
||||
# convert method to string
|
||||
lxmf_message_method = "unknown"
|
||||
if lxmf_message.method == LXMF.LXMessage.OPPORTUNISTIC:
|
||||
@@ -3718,7 +3725,8 @@ class ReticulumMeshChat:
|
||||
|
||||
return lxmf_message_method
|
||||
|
||||
def convert_propagation_node_state_to_string(self, state):
|
||||
@staticmethod
|
||||
def convert_propagation_node_state_to_string(state):
|
||||
# map states to strings
|
||||
state_map = {
|
||||
LXMRouter.PR_IDLE: "idle",
|
||||
@@ -3749,7 +3757,7 @@ class ReticulumMeshChat:
|
||||
if announce.aspect == "lxmf.delivery":
|
||||
display_name = self.parse_lxmf_display_name(announce.app_data)
|
||||
elif announce.aspect == "nomadnetwork.node":
|
||||
display_name = self.parse_nomadnetwork_node_display_name(announce.app_data)
|
||||
display_name = ReticulumMeshChat.parse_nomadnetwork_node_display_name(announce.app_data)
|
||||
|
||||
# find lxmf user icon from database
|
||||
lxmf_user_icon = None
|
||||
@@ -3787,7 +3795,8 @@ class ReticulumMeshChat:
|
||||
}
|
||||
|
||||
# convert database favourite to a dictionary
|
||||
def convert_db_favourite_to_dict(self, favourite: database.FavouriteDestination):
|
||||
@staticmethod
|
||||
def convert_db_favourite_to_dict(favourite: database.FavouriteDestination):
|
||||
return {
|
||||
"id": favourite.id,
|
||||
"destination_hash": favourite.destination_hash,
|
||||
@@ -3798,7 +3807,8 @@ class ReticulumMeshChat:
|
||||
}
|
||||
|
||||
# convert database lxmf message to a dictionary
|
||||
def convert_db_lxmf_message_to_dict(self, db_lxmf_message: database.LxmfMessage):
|
||||
@staticmethod
|
||||
def convert_db_lxmf_message_to_dict(db_lxmf_message: database.LxmfMessage):
|
||||
return {
|
||||
"id": db_lxmf_message.id,
|
||||
"hash": db_lxmf_message.hash,
|
||||
@@ -3823,8 +3833,8 @@ class ReticulumMeshChat:
|
||||
}
|
||||
|
||||
# updates the lxmf user icon for the provided destination hash
|
||||
@staticmethod
|
||||
def update_lxmf_user_icon(
|
||||
self,
|
||||
destination_hash: str,
|
||||
icon_name: str,
|
||||
foreground_colour: str,
|
||||
@@ -3852,7 +3862,8 @@ class ReticulumMeshChat:
|
||||
query.execute()
|
||||
|
||||
# check if a destination is blocked
|
||||
def is_destination_blocked(self, destination_hash: str) -> bool:
|
||||
@staticmethod
|
||||
def is_destination_blocked(destination_hash: str) -> bool:
|
||||
try:
|
||||
blocked = database.BlockedDestination.get_or_none(
|
||||
database.BlockedDestination.destination_hash == destination_hash,
|
||||
@@ -3862,7 +3873,8 @@ class ReticulumMeshChat:
|
||||
return False
|
||||
|
||||
# check if message content matches spam keywords
|
||||
def check_spam_keywords(self, title: str, content: str) -> bool:
|
||||
@staticmethod
|
||||
def check_spam_keywords(title: str, content: str) -> bool:
|
||||
try:
|
||||
spam_keywords = database.SpamKeyword.select()
|
||||
search_text = (title + " " + content).lower()
|
||||
@@ -3874,7 +3886,8 @@ class ReticulumMeshChat:
|
||||
return False
|
||||
|
||||
# check if message has attachments and should be rejected
|
||||
def has_attachments(self, lxmf_fields: dict) -> bool:
|
||||
@staticmethod
|
||||
def has_attachments(lxmf_fields: dict) -> bool:
|
||||
try:
|
||||
if LXMF.FIELD_FILE_ATTACHMENTS in lxmf_fields:
|
||||
return len(lxmf_fields[LXMF.FIELD_FILE_ATTACHMENTS]) > 0
|
||||
@@ -4108,8 +4121,9 @@ class ReticulumMeshChat:
|
||||
query.execute()
|
||||
|
||||
# upserts a custom destination display name to the database
|
||||
@staticmethod
|
||||
def db_upsert_custom_destination_display_name(
|
||||
self, destination_hash: str, display_name: str,
|
||||
destination_hash: str, display_name: str,
|
||||
):
|
||||
# prepare data to insert or update
|
||||
data = {
|
||||
@@ -4127,8 +4141,9 @@ class ReticulumMeshChat:
|
||||
query.execute()
|
||||
|
||||
# upserts a custom destination display name to the database
|
||||
@staticmethod
|
||||
def db_upsert_favourite(
|
||||
self, destination_hash: str, display_name: str, aspect: str,
|
||||
destination_hash: str, display_name: str, aspect: str,
|
||||
):
|
||||
# prepare data to insert or update
|
||||
data = {
|
||||
@@ -4147,7 +4162,8 @@ class ReticulumMeshChat:
|
||||
query.execute()
|
||||
|
||||
# upserts lxmf conversation read state to the database
|
||||
def db_mark_lxmf_conversation_as_read(self, destination_hash: str):
|
||||
@staticmethod
|
||||
def db_mark_lxmf_conversation_as_read(destination_hash: str):
|
||||
# prepare data to insert or update
|
||||
data = {
|
||||
"destination_hash": destination_hash,
|
||||
@@ -4633,7 +4649,8 @@ class ReticulumMeshChat:
|
||||
)
|
||||
|
||||
# gets the custom display name a user has set for the provided destination hash
|
||||
def get_custom_destination_display_name(self, destination_hash: str):
|
||||
@staticmethod
|
||||
def get_custom_destination_display_name(destination_hash: str):
|
||||
# get display name from database
|
||||
db_destination_display_name = database.CustomDestinationDisplayName.get_or_none(
|
||||
database.CustomDestinationDisplayName.destination_hash == destination_hash,
|
||||
@@ -4646,7 +4663,8 @@ class ReticulumMeshChat:
|
||||
# get name to show for an lxmf conversation
|
||||
# currently, this will use the app data from the most recent announce
|
||||
# TODO: we should fetch this from our contacts database, when it gets implemented, and if not found, fallback to app data
|
||||
def get_lxmf_conversation_name(self, destination_hash):
|
||||
@staticmethod
|
||||
def get_lxmf_conversation_name(destination_hash):
|
||||
# get lxmf.delivery announce from database for the provided destination hash
|
||||
lxmf_announce = (
|
||||
database.Announce.select()
|
||||
@@ -4658,14 +4676,15 @@ class ReticulumMeshChat:
|
||||
# if app data is available in database, it should be base64 encoded text that was announced
|
||||
# we will return the parsed lxmf display name as the conversation name
|
||||
if lxmf_announce is not None and lxmf_announce.app_data is not None:
|
||||
return self.parse_lxmf_display_name(app_data_base64=lxmf_announce.app_data)
|
||||
return ReticulumMeshChat.parse_lxmf_display_name(app_data_base64=lxmf_announce.app_data)
|
||||
|
||||
# announce did not have app data, so provide a fallback name
|
||||
return "Anonymous Peer"
|
||||
|
||||
# reads the lxmf display name from the provided base64 app data
|
||||
@staticmethod
|
||||
def parse_lxmf_display_name(
|
||||
self, app_data_base64: str, default_value: str | None = "Anonymous Peer",
|
||||
app_data_base64: str, default_value: str | None = "Anonymous Peer",
|
||||
):
|
||||
try:
|
||||
app_data_bytes = base64.b64decode(app_data_base64)
|
||||
@@ -4678,7 +4697,8 @@ class ReticulumMeshChat:
|
||||
return default_value
|
||||
|
||||
# reads the lxmf stamp cost from the provided base64 app data
|
||||
def parse_lxmf_stamp_cost(self, app_data_base64: str):
|
||||
@staticmethod
|
||||
def parse_lxmf_stamp_cost(app_data_base64: str):
|
||||
try:
|
||||
app_data_bytes = base64.b64decode(app_data_base64)
|
||||
return LXMF.stamp_cost_from_app_data(app_data_bytes)
|
||||
@@ -4686,8 +4706,9 @@ class ReticulumMeshChat:
|
||||
return None
|
||||
|
||||
# reads the nomadnetwork node display name from the provided base64 app data
|
||||
@staticmethod
|
||||
def parse_nomadnetwork_node_display_name(
|
||||
self, app_data_base64: str, default_value: str | None = "Anonymous Node",
|
||||
app_data_base64: str, default_value: str | None = "Anonymous Node",
|
||||
):
|
||||
try:
|
||||
app_data_bytes = base64.b64decode(app_data_base64)
|
||||
@@ -4696,7 +4717,8 @@ class ReticulumMeshChat:
|
||||
return default_value
|
||||
|
||||
# parses lxmf propagation node app data
|
||||
def parse_lxmf_propagation_node_app_data(self, app_data_base64: str):
|
||||
@staticmethod
|
||||
def parse_lxmf_propagation_node_app_data(app_data_base64: str):
|
||||
try:
|
||||
app_data_bytes = base64.b64decode(app_data_base64)
|
||||
data = msgpack.unpackb(app_data_bytes)
|
||||
@@ -4709,7 +4731,8 @@ class ReticulumMeshChat:
|
||||
return None
|
||||
|
||||
# returns true if the conversation has messages newer than the last read at timestamp
|
||||
def is_lxmf_conversation_unread(self, destination_hash):
|
||||
@staticmethod
|
||||
def is_lxmf_conversation_unread(destination_hash):
|
||||
# get lxmf conversation read state from database for the provided destination hash
|
||||
lxmf_conversation_read_state = (
|
||||
database.LxmfConversationReadState.select()
|
||||
@@ -4745,7 +4768,8 @@ class ReticulumMeshChat:
|
||||
return conversation_last_read_at < conversation_latest_message_at
|
||||
|
||||
# returns number of messages that failed to send in a conversation
|
||||
def lxmf_conversation_failed_messages_count(self, destination_hash: str):
|
||||
@staticmethod
|
||||
def lxmf_conversation_failed_messages_count(destination_hash: str):
|
||||
return (
|
||||
database.LxmfMessage.select()
|
||||
.where(database.LxmfMessage.state == "failed")
|
||||
@@ -4754,7 +4778,8 @@ class ReticulumMeshChat:
|
||||
)
|
||||
|
||||
# find an interface by name
|
||||
def find_interface_by_name(self, name: str):
|
||||
@staticmethod
|
||||
def find_interface_by_name(name: str):
|
||||
for interface in RNS.Transport.interfaces:
|
||||
interface_name = str(interface)
|
||||
if name == interface_name:
|
||||
|
||||
9
package-lock.json
generated
9
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "reticulum-meshchat",
|
||||
"version": "2.32.3",
|
||||
"name": "reticulum-meshchatx",
|
||||
"version": "2.41.0",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "reticulum-meshchat",
|
||||
"version": "2.32.3",
|
||||
"name": "reticulum-meshchatx",
|
||||
"version": "2.41.0",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@mdi/js": "^7.4.47",
|
||||
@@ -3025,7 +3025,6 @@
|
||||
"integrity": "sha512-rcJUkMfnJpfCboZoOOPf4L29TRtEieHNOeAbYPWPxlaBw/Z1RKrRA86dOI9rwaI4tQSc/RD82zTNHprfUHXsoQ==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"app-builder-lib": "24.13.3",
|
||||
"builder-util": "24.13.1",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
{
|
||||
"name": "reticulum-meshchat",
|
||||
"version": "2.32.3",
|
||||
"name": "reticulum-meshchatx",
|
||||
"version": "2.41.0",
|
||||
"description": "A simple mesh network communications app powered by the Reticulum Network Stack",
|
||||
"author": "Sudo-Ivan",
|
||||
"main": "electron/main.js",
|
||||
"scripts": {
|
||||
"watch": "npm run build-frontend -- --watch",
|
||||
"build-frontend": "vite build",
|
||||
"build-backend": "venv/bin/python setup.py build",
|
||||
"build-backend": "node scripts/build-backend.js",
|
||||
"build": "npm run build-frontend && npm run build-backend",
|
||||
"electron-postinstall": "electron-builder install-app-deps",
|
||||
"electron": "npm run electron-postinstall && npm run build && electron .",
|
||||
|
||||
18
scripts/build-backend.js
Executable file
18
scripts/build-backend.js
Executable file
@@ -0,0 +1,18 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
|
||||
const platform = os.platform();
|
||||
const venvPython = platform === 'win32'
|
||||
? path.join('venv', 'Scripts', 'python.exe')
|
||||
: path.join('venv', 'bin', 'python');
|
||||
|
||||
try {
|
||||
execSync(`${venvPython} setup.py build`, { stdio: 'inherit' });
|
||||
} catch (error) {
|
||||
console.error('Build failed:', error.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user