Compare commits
55 Commits
v2.40.0
...
legacy-sup
| Author | SHA1 | Date | |
|---|---|---|---|
| bdf4eee267 | |||
| d8683c3191 | |||
| fb3096d3fa | |||
| d97676ad27 | |||
| 4200e43618 | |||
| c5ae53bf55 | |||
| bf8c22c31a | |||
| 9a9022ffb0 | |||
| 0443734ee3 | |||
| 6efac94f58 | |||
| 9e1a8ce180 | |||
| f2ab1ad067 | |||
| 365531be9b | |||
| 96f4fc8735 | |||
| d69a3e8522 | |||
| c95d2fd71c | |||
|
a74a6869ea
|
|||
| d8419990b1 | |||
|
085385a182
|
|||
|
f8b0dd18c5
|
|||
|
3231afb84d
|
|||
|
3848613a41
|
|||
|
284517bdfa
|
|||
|
5fc13dc61a
|
|||
|
f989295773
|
|||
|
|
d06ede8c5e | ||
|
a0047ea8fb
|
|||
|
c98131f76b
|
|||
|
9b4b8fdfeb
|
|||
|
48a0d8697e
|
|||
|
5627ae1640
|
|||
|
94d91c4934
|
|||
|
ac839df357
|
|||
|
cfad1ddc5f
|
|||
|
398ab570df
|
|||
|
50bc2cbfc8
|
|||
|
fe3a01c3c6
|
|||
|
0b0a39ea86
|
|||
|
2e001006c9
|
|||
|
0beaaaf4b1
|
|||
|
84f887df90
|
|||
|
80cf812e54
|
|||
|
19854e59da
|
|||
|
ba47e16b75
|
|||
|
578e80023f
|
|||
|
b7dcee4c06
|
|||
|
e44ec59b6e
|
|||
|
45379e6df1
|
|||
|
308f1f6459
|
|||
| 424ff116d1 | |||
|
|
73f677d319 | ||
|
4770c21499
|
|||
|
720bef90c7
|
|||
|
1c98a231fd
|
|||
|
f6a1be5e80
|
@@ -3,24 +3,36 @@ README.md
|
||||
LICENSE
|
||||
donate.md
|
||||
screenshots/
|
||||
docs/
|
||||
|
||||
# Development files
|
||||
.github/
|
||||
electron/
|
||||
scripts/
|
||||
Makefile
|
||||
|
||||
# Build artifacts and cache
|
||||
build/
|
||||
dist/
|
||||
public/
|
||||
meshchatx/public/
|
||||
node_modules/
|
||||
__pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
*.egg-info/
|
||||
*.egg
|
||||
python-dist/
|
||||
|
||||
# Virtual environments
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
.venv/
|
||||
|
||||
# IDE and editor files
|
||||
.vscode/
|
||||
@@ -47,9 +59,19 @@ Dockerfile*
|
||||
docker-compose*.yml
|
||||
.dockerignore
|
||||
|
||||
# Local storage and runtime data
|
||||
storage/
|
||||
testing/
|
||||
telemetry_test_lxmf/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# Temporary files
|
||||
*.tmp
|
||||
*.temp
|
||||
*.temp
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
368
.github/workflows/build.yml
vendored
@@ -4,94 +4,37 @@ 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
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build_windows:
|
||||
runs-on: windows-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Clone Repo
|
||||
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
|
||||
|
||||
- name: Install NodeJS
|
||||
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
|
||||
with:
|
||||
node-version: 22
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
python -m venv venv
|
||||
venv\Scripts\pip install --upgrade pip
|
||||
venv\Scripts\pip install -r requirements.txt
|
||||
|
||||
- name: Install NodeJS Deps
|
||||
run: npm install
|
||||
|
||||
- name: Build Electron App
|
||||
run: npm run dist
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
|
||||
with:
|
||||
draft: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
artifacts: "dist/*-win-installer.exe,dist/*-win-portable.exe"
|
||||
|
||||
build_mac:
|
||||
runs-on: macos-13
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Clone Repo
|
||||
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
|
||||
|
||||
- name: Install NodeJS
|
||||
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
|
||||
with:
|
||||
node-version: 18
|
||||
|
||||
- name: Install Python
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
python3 -m venv venv
|
||||
venv/bin/pip install --upgrade pip
|
||||
venv/bin/pip install -r requirements.txt
|
||||
|
||||
- name: Install NodeJS Deps
|
||||
run: npm install
|
||||
|
||||
- name: Build Electron App
|
||||
run: npm run dist
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
|
||||
with:
|
||||
draft: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
artifacts: "dist/*-mac.dmg"
|
||||
|
||||
build_linux:
|
||||
build_frontend:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
contents: read
|
||||
steps:
|
||||
- name: Clone Repo
|
||||
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
|
||||
@@ -106,34 +49,249 @@ jobs:
|
||||
with:
|
||||
python-version: "3.12"
|
||||
|
||||
- name: Install patchelf
|
||||
run: sudo apt-get update && sudo apt-get install -y patchelf
|
||||
|
||||
- name: Install Python Deps
|
||||
run: |
|
||||
python3 -m venv venv
|
||||
venv/bin/pip install --upgrade pip
|
||||
venv/bin/pip install -r requirements.txt
|
||||
- name: Sync versions
|
||||
run: python scripts/sync_version.py
|
||||
|
||||
- name: Install NodeJS Deps
|
||||
run: npm install
|
||||
|
||||
- name: Build Electron App
|
||||
run: npm run dist
|
||||
- name: Build Frontend
|
||||
run: npm run build-frontend
|
||||
|
||||
- name: Upload frontend artifact
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
|
||||
with:
|
||||
name: frontend-build
|
||||
path: meshchatx/public
|
||||
if-no-files-found: error
|
||||
|
||||
build_desktop:
|
||||
name: Build Desktop (${{ matrix.name }})
|
||||
needs: build_frontend
|
||||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: windows
|
||||
os: windows-latest
|
||||
node: 22
|
||||
python: "3.13"
|
||||
release_artifacts: "dist/*-win-installer.exe,dist/*-win-portable.exe"
|
||||
build_input: build_windows
|
||||
dist_script: dist-prebuilt
|
||||
variant: standard
|
||||
electron_version: "39.2.4"
|
||||
- name: mac
|
||||
os: macos-14
|
||||
node: 22
|
||||
python: "3.13"
|
||||
release_artifacts: "dist/*-mac-*.dmg"
|
||||
build_input: build_mac
|
||||
dist_script: dist:mac-universal
|
||||
variant: standard
|
||||
electron_version: "39.2.4"
|
||||
- name: linux
|
||||
os: ubuntu-latest
|
||||
node: 22
|
||||
python: "3.13"
|
||||
release_artifacts: "dist/*-linux.AppImage,dist/*-linux.deb,python-dist/*.whl"
|
||||
build_input: build_linux
|
||||
dist_script: dist-prebuilt
|
||||
variant: standard
|
||||
electron_version: "39.2.4"
|
||||
- name: windows-legacy
|
||||
os: windows-latest
|
||||
node: 18
|
||||
python: "3.11"
|
||||
release_artifacts: "dist/*-win-installer*.exe,dist/*-win-portable*.exe"
|
||||
build_input: build_windows
|
||||
dist_script: dist-prebuilt
|
||||
variant: legacy
|
||||
electron_version: "30.0.8"
|
||||
- name: linux-legacy
|
||||
os: ubuntu-latest
|
||||
node: 18
|
||||
python: "3.11"
|
||||
release_artifacts: "dist/*-linux*.AppImage,dist/*-linux*.deb,python-dist/*.whl"
|
||||
build_input: build_linux
|
||||
dist_script: dist-prebuilt
|
||||
variant: legacy
|
||||
electron_version: "30.0.8"
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Clone Repo
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
uses: actions/checkout@50fbc622fc4ef5163becd7fab6573eac35f8462e # v1
|
||||
|
||||
- name: Set legacy Electron version
|
||||
if: |
|
||||
matrix.variant == 'legacy' &&
|
||||
(github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true))
|
||||
shell: bash
|
||||
run: |
|
||||
node -e "const fs=require('fs');const pkg=require('./package.json');pkg.devDependencies.electron='${{ matrix.electron_version }}';fs.writeFileSync('package.json', JSON.stringify(pkg,null,2));"
|
||||
if [ -f package-lock.json ]; then rm package-lock.json; fi
|
||||
|
||||
- name: Install NodeJS
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
uses: actions/setup-node@f1f314fca9dfce2769ece7d933488f076716723e # v1
|
||||
with:
|
||||
node-version: ${{ matrix.node }}
|
||||
|
||||
- name: Install Python
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5
|
||||
with:
|
||||
python-version: ${{ matrix.python }}
|
||||
|
||||
- name: Install Poetry
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: python -m pip install --upgrade pip poetry
|
||||
|
||||
- name: Sync versions
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: python scripts/sync_version.py
|
||||
|
||||
- name: Install Python Deps
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: python -m poetry install
|
||||
|
||||
- name: Install NodeJS Deps
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: npm install
|
||||
|
||||
- name: Prepare frontend directory
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: python scripts/prepare_frontend_dir.py
|
||||
|
||||
- name: Download frontend artifact
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
name: frontend-build
|
||||
path: meshchatx/public
|
||||
|
||||
- name: Install patchelf
|
||||
if: |
|
||||
startsWith(matrix.name, 'linux') &&
|
||||
(github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true))
|
||||
run: sudo apt-get update && sudo apt-get install -y patchelf
|
||||
|
||||
- name: Build Python wheel
|
||||
if: |
|
||||
startsWith(matrix.name, 'linux') &&
|
||||
(github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true))
|
||||
run: |
|
||||
python -m poetry build -f wheel
|
||||
mkdir -p python-dist
|
||||
mv dist/*.whl python-dist/
|
||||
rm -rf dist
|
||||
|
||||
- name: Build Electron App (Universal)
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
run: npm run ${{ matrix.dist_script }}
|
||||
|
||||
- name: Rename artifacts for legacy build
|
||||
if: |
|
||||
matrix.variant == 'legacy' &&
|
||||
(github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true))
|
||||
run: ./scripts/rename_legacy_artifacts.sh
|
||||
|
||||
- name: Upload build artifacts
|
||||
if: |
|
||||
github.event_name == 'push' ||
|
||||
(github.event_name == 'workflow_dispatch' && inputs[matrix.build_input] == true)
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-${{ matrix.name }}
|
||||
path: |
|
||||
dist/*-win-installer*.exe
|
||||
dist/*-win-portable*.exe
|
||||
dist/*-mac-*.dmg
|
||||
dist/*-linux*.AppImage
|
||||
dist/*-linux*.deb
|
||||
python-dist/*.whl
|
||||
if-no-files-found: ignore
|
||||
|
||||
create_release:
|
||||
name: Create Release
|
||||
needs: build_desktop
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push'
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Download all artifacts
|
||||
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4
|
||||
with:
|
||||
path: artifacts
|
||||
|
||||
- name: Display structure of downloaded files
|
||||
run: ls -R artifacts
|
||||
|
||||
- name: Prepare release assets
|
||||
run: |
|
||||
mkdir -p release-assets
|
||||
find artifacts -type f \( -name "*.exe" -o -name "*.dmg" -o -name "*.AppImage" -o -name "*.deb" -o -name "*.whl" \) -exec cp {} release-assets/ \;
|
||||
ls -lh release-assets/
|
||||
|
||||
- name: Generate SHA256 checksums
|
||||
run: |
|
||||
cd release-assets
|
||||
echo "## SHA256 Checksums" > release-body.md
|
||||
echo "" >> release-body.md
|
||||
|
||||
for file in *.exe *.dmg *.AppImage *.deb *.whl; do
|
||||
if [ -f "$file" ]; then
|
||||
sha256sum "$file" | tee "${file}.sha256"
|
||||
echo "\`$(cat "${file}.sha256")\`" >> release-body.md
|
||||
fi
|
||||
done
|
||||
|
||||
echo "" >> release-body.md
|
||||
echo "Individual \`.sha256\` files are included for each artifact." >> release-body.md
|
||||
|
||||
cat release-body.md
|
||||
echo ""
|
||||
echo "Generated .sha256 files:"
|
||||
ls -1 *.sha256 2>/dev/null || echo "No .sha256 files found"
|
||||
|
||||
- name: Create Release
|
||||
id: create_release
|
||||
uses: ncipollo/release-action@b7eabc95ff50cbeeedec83973935c8f306dfcd0b # v1
|
||||
with:
|
||||
draft: true
|
||||
allowUpdates: true
|
||||
replacesArtifacts: true
|
||||
omitDraftDuringUpdate: true
|
||||
omitNameDuringUpdate: true
|
||||
artifacts: "dist/*-linux.AppImage,dist/*-linux.deb"
|
||||
artifacts: "release-assets/*"
|
||||
bodyFile: "release-assets/release-body.md"
|
||||
|
||||
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 +322,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/
|
||||
|
||||
22
.github/workflows/dependency-review.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
name: 'Dependency review'
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ "master" ]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: 'Checkout repository'
|
||||
uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
|
||||
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@3c4e3dcb1aa7874d2c16be7d79418e9b7efd6261 # v4
|
||||
with:
|
||||
comment-summary-in-pr: always
|
||||
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/
|
||||
|
||||
54
.gitignore
vendored
@@ -1,13 +1,57 @@
|
||||
# IDE and editor files
|
||||
.idea
|
||||
node_modules
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# build files
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
*.egg-info/
|
||||
dist/
|
||||
*.egg
|
||||
|
||||
# Virtual environments
|
||||
venv/
|
||||
env/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
.venv/
|
||||
|
||||
# Build files
|
||||
/build/
|
||||
/dist/
|
||||
/public/
|
||||
/meshchatx/public/
|
||||
public/
|
||||
/electron/build/exe/
|
||||
python-dist/
|
||||
|
||||
# local storage
|
||||
# Local storage and runtime data
|
||||
storage/
|
||||
testing/
|
||||
telemetry_test_lxmf/
|
||||
|
||||
*.pyc
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# OS files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
|
||||
# Environment variables
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
15
Dockerfile
@@ -10,9 +10,8 @@ FROM node:${NODE_VERSION}-alpine@${NODE_ALPINE_SHA256} AS build-frontend
|
||||
WORKDIR /src
|
||||
|
||||
# Copy required source files
|
||||
COPY *.json .
|
||||
COPY *.js .
|
||||
COPY src/frontend ./src/frontend
|
||||
COPY package*.json vite.config.js ./
|
||||
COPY meshchatx ./meshchatx
|
||||
|
||||
# Install NodeJS deps, exluding electron
|
||||
RUN npm install --omit=dev && \
|
||||
@@ -34,12 +33,10 @@ RUN apk add --no-cache --virtual .build-deps \
|
||||
apk del .build-deps
|
||||
|
||||
# Copy prebuilt frontend
|
||||
COPY --from=build-frontend /src/public public
|
||||
COPY --from=build-frontend /src/meshchatx/public meshchatx/public
|
||||
|
||||
# Copy other required source files
|
||||
COPY *.py .
|
||||
COPY src/__init__.py ./src/__init__.py
|
||||
COPY src/backend ./src/backend
|
||||
COPY *.json .
|
||||
COPY meshchatx ./meshchatx
|
||||
COPY pyproject.toml poetry.lock ./
|
||||
|
||||
CMD ["python", "meshchat.py", "--host=0.0.0.0", "--reticulum-config-dir=/config/.reticulum", "--storage-dir=/config/.meshchat", "--headless"]
|
||||
CMD ["python", "-m", "meshchatx.meshchat", "--host=0.0.0.0", "--reticulum-config-dir=/config/.reticulum", "--storage-dir=/config/.meshchat", "--headless"]
|
||||
|
||||
68
Makefile
@@ -1,26 +1,40 @@
|
||||
.PHONY: install run clean build build-appimage build-exe dist
|
||||
.PHONY: install run develop clean build build-appimage build-exe dist sync-version wheel node_modules python build-docker run-docker electron-legacy build-appimage-legacy build-exe-legacy
|
||||
|
||||
VENV = venv
|
||||
PYTHON = $(VENV)/bin/python
|
||||
PIP = $(VENV)/bin/pip
|
||||
PYTHON ?= python
|
||||
POETRY = $(PYTHON) -m poetry
|
||||
NPM = npm
|
||||
LEGACY_ELECTRON_VERSION ?= 30.0.8
|
||||
|
||||
install: $(VENV) node_modules
|
||||
DOCKER_COMPOSE_CMD ?= docker compose
|
||||
DOCKER_COMPOSE_FILE ?= docker-compose.yml
|
||||
DOCKER_IMAGE ?= reticulum-meshchatx:local
|
||||
DOCKER_BUILDER ?= meshchatx-builder
|
||||
DOCKER_PLATFORMS ?= linux/amd64
|
||||
DOCKER_BUILD_FLAGS ?= --load
|
||||
DOCKER_BUILD_ARGS ?=
|
||||
DOCKER_CONTEXT ?= .
|
||||
DOCKERFILE ?= Dockerfile
|
||||
|
||||
$(VENV):
|
||||
python3 -m venv $(VENV)
|
||||
$(PIP) install --upgrade pip
|
||||
$(PIP) install -r requirements.txt
|
||||
install: sync-version node_modules python
|
||||
|
||||
node_modules:
|
||||
$(NPM) install
|
||||
|
||||
python:
|
||||
$(POETRY) install
|
||||
|
||||
run: install
|
||||
$(PYTHON) meshchat.py
|
||||
$(POETRY) run meshchat
|
||||
|
||||
develop: run
|
||||
|
||||
build: install
|
||||
$(NPM) run build
|
||||
|
||||
wheel: install
|
||||
$(POETRY) build -f wheel
|
||||
$(PYTHON) scripts/move_wheels.py
|
||||
|
||||
build-appimage: build
|
||||
$(NPM) run electron-postinstall
|
||||
$(NPM) run dist -- --linux AppImage
|
||||
@@ -31,11 +45,43 @@ build-exe: build
|
||||
|
||||
dist: build-appimage
|
||||
|
||||
electron-legacy:
|
||||
$(NPM) install --no-save electron@$(LEGACY_ELECTRON_VERSION)
|
||||
|
||||
# Legacy targets intended for manual/local builds; CI uses workflow jobs.
|
||||
build-appimage-legacy: build electron-legacy
|
||||
$(NPM) run electron-postinstall
|
||||
$(NPM) run dist -- --linux AppImage
|
||||
./scripts/rename_legacy_artifacts.sh
|
||||
|
||||
build-exe-legacy: build electron-legacy
|
||||
$(NPM) run electron-postinstall
|
||||
$(NPM) run dist -- --win portable
|
||||
./scripts/rename_legacy_artifacts.sh
|
||||
|
||||
clean:
|
||||
rm -rf $(VENV)
|
||||
rm -rf node_modules
|
||||
rm -rf build
|
||||
rm -rf dist
|
||||
rm -rf python-dist
|
||||
rm -rf meshchatx/public
|
||||
|
||||
sync-version:
|
||||
$(PYTHON) scripts/sync_version.py
|
||||
|
||||
build-docker:
|
||||
@if ! docker buildx inspect $(DOCKER_BUILDER) >/dev/null 2>&1; then \
|
||||
docker buildx create --name $(DOCKER_BUILDER) --use >/dev/null; \
|
||||
else \
|
||||
docker buildx use $(DOCKER_BUILDER); \
|
||||
fi
|
||||
docker buildx build --builder $(DOCKER_BUILDER) --platform $(DOCKER_PLATFORMS) \
|
||||
$(DOCKER_BUILD_FLAGS) \
|
||||
-t $(DOCKER_IMAGE) \
|
||||
$(DOCKER_BUILD_ARGS) \
|
||||
-f $(DOCKERFILE) \
|
||||
$(DOCKER_CONTEXT)
|
||||
|
||||
run-docker:
|
||||
MESHCHAT_IMAGE="$(DOCKER_IMAGE)" \
|
||||
$(DOCKER_COMPOSE_CMD) -f $(DOCKER_COMPOSE_FILE) up --remove-orphans --pull never reticulum-meshchatx
|
||||
|
||||
81
README.md
@@ -8,15 +8,25 @@ A heavily customized fork of [Reticulum MeshChat](https://github.com/liamcottle/
|
||||
- [x] Ability to set inbound and propagation node stamps.
|
||||
- [x] Better config parsing.
|
||||
- [x] Cancel page fetching or file downloads
|
||||
- [x] Block recieving messages from users.
|
||||
- [x] Block receiving messages from users.
|
||||
- [ ] Spam filter (based on keywords)
|
||||
- [ ] Multi-identity support.
|
||||
- [ ] Multi-language support
|
||||
- [ ] Offline Reticulum documentation tool
|
||||
- [ ] More tools (translate, LoRa calculator, LXMFy bots, etc.)
|
||||
- [x] Codebase reorganization and cleanup.
|
||||
- [ ] Tests and proper CI/CD pipeline.
|
||||
- [ ] RNS hot reload
|
||||
- [ ] Backup/Import identities, messages and interfaces.
|
||||
- [ ] Full LXST support.
|
||||
- [x] Poetry for packaging and dependency management.
|
||||
- [x] More stats on about page.
|
||||
- [x] Actions are pinned to full-length SHA hashes.
|
||||
- [x] Docker images are smaller and use SHA256 hashes for the images.
|
||||
- [x] Electron improvements.
|
||||
- [x] Electron improvements (ASAR and security).
|
||||
- [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
|
||||
|
||||
@@ -25,21 +35,76 @@ Check [releases](https://github.com/Sudo-Ivan/reticulum-meshchatX/releases) for
|
||||
## Building
|
||||
|
||||
```bash
|
||||
make install
|
||||
make install # installs Python deps via Poetry and Node deps via npm
|
||||
make build
|
||||
```
|
||||
|
||||
You can run `make run` or `make develop` (a thin alias) to start the backend + frontend loop locally through `poetry run meshchat`.
|
||||
|
||||
### Python packaging
|
||||
|
||||
The Python build is driven entirely by Poetry now. Run `python3 scripts/sync_version.py` or `make sync-version` before packaging so `pyproject.toml` and `src/version.py` match `package.json`. After that:
|
||||
|
||||
```bash
|
||||
python -m poetry install
|
||||
make wheel # produces a wheel in python-dist/ that bundles the public assets
|
||||
```
|
||||
|
||||
The wheel includes the frontend `public/` assets, `logo/`, and the CLI entry point, and `python-dist/` keeps the artifact separate from the Electron `dist/` output.
|
||||
|
||||
### Building in Docker
|
||||
|
||||
```bash
|
||||
make docker-build
|
||||
make build-docker
|
||||
```
|
||||
|
||||
The build will be in the `dist` directory.
|
||||
`build-docker` creates `reticulum-meshchatx:local` (or `$(DOCKER_IMAGE)` if you override it) via `docker buildx`. Set `DOCKER_PLATFORMS` to `linux/amd64,linux/arm64` when you need multi-arch images, and adjust `DOCKER_BUILD_FLAGS`/`DOCKER_BUILD_ARGS` to control `--load`/`--push`.
|
||||
|
||||
## Development
|
||||
### Running with Docker Compose
|
||||
|
||||
```bash
|
||||
make develop
|
||||
make run-docker
|
||||
```
|
||||
|
||||
`run-docker` feeds the locally-built image into `docker compose -f docker-compose.yml up --remove-orphans --pull never reticulum-meshchatx`. The compose file uses the `MESHCHAT_IMAGE` env var so you can override the target image without editing the YAML (the default still points at `ghcr.io/sudo-ivan/reticulum-meshchatx:latest`). Use `docker compose down` or `Ctrl+C` to stop the container.
|
||||
|
||||
The Electron build artifacts will still live under `dist/` for releases.
|
||||
|
||||
## Python packaging
|
||||
|
||||
The backend uses Poetry with `pyproject.toml` for dependency management and packaging. Before building, run `python3 scripts/sync_version.py` (or `make sync-version`) to ensure the generated `src/version.py` reflects the version from `package.json` that the Electron artifacts use. This keeps the CLI release metadata, wheel packages, and other bundles aligned.
|
||||
|
||||
### Build artifact locations
|
||||
|
||||
Both `poetry build` and `python -m build` generate wheels inside the default `dist/` directory. The `make wheel` shortcut wraps `poetry build -f wheel` and then runs `python scripts/move_wheels.py` to relocate the generated `.whl` files into `python-dist/` (the layout expected by `scripts/test_wheel.sh` and the release automation). Use `make wheel` if you need the artifacts in `python-dist/`; `poetry build` or `python -m build` alone will leave them in `dist/`.
|
||||
|
||||
### Building with Poetry
|
||||
|
||||
```bash
|
||||
# Install dependencies
|
||||
poetry install
|
||||
|
||||
# Build the package (wheels land in dist/)
|
||||
poetry build
|
||||
|
||||
# Install locally for testing (consumes dist/)
|
||||
pip install dist/*.whl
|
||||
```
|
||||
|
||||
### Building with pip (alternative)
|
||||
|
||||
If you prefer pip, you can build/install directly:
|
||||
|
||||
```bash
|
||||
# Build the wheel
|
||||
pip install build
|
||||
python -m build
|
||||
|
||||
# Install locally
|
||||
pip install .
|
||||
```
|
||||
|
||||
### cx_Freeze (for AppImage/NSIS)
|
||||
|
||||
The `cx_setup.py` script uses cx_Freeze for creating standalone executables (AppImage for Linux, NSIS for Windows). This is separate from the Poetry/pip packaging workflow.
|
||||
|
||||
|
||||
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
|
||||
47
cx_setup.py
Normal file
@@ -0,0 +1,47 @@
|
||||
from pathlib import Path
|
||||
|
||||
from cx_Freeze import Executable, setup
|
||||
|
||||
from meshchatx.src.version import __version__
|
||||
|
||||
ROOT = Path(__file__).resolve().parent
|
||||
PUBLIC_DIR = ROOT / "meshchatx" / "public"
|
||||
|
||||
include_files = [
|
||||
(str(PUBLIC_DIR), "public"),
|
||||
("logo", "logo"),
|
||||
]
|
||||
|
||||
setup(
|
||||
name="ReticulumMeshChatX",
|
||||
version=__version__,
|
||||
description="A simple mesh network communications app powered by the Reticulum Network Stack",
|
||||
executables=[
|
||||
Executable(
|
||||
script="meshchatx/meshchat.py",
|
||||
base=None,
|
||||
target_name="ReticulumMeshChatX",
|
||||
shortcut_name="ReticulumMeshChatX",
|
||||
shortcut_dir="ProgramMenuFolder",
|
||||
icon="logo/icon.ico",
|
||||
),
|
||||
],
|
||||
options={
|
||||
"build_exe": {
|
||||
"packages": [
|
||||
"RNS",
|
||||
"RNS.Interfaces",
|
||||
"LXMF",
|
||||
],
|
||||
"include_files": include_files,
|
||||
"excludes": [
|
||||
"PIL",
|
||||
],
|
||||
"optimize": 2,
|
||||
"build_exe": "build/exe",
|
||||
"replace_paths": [
|
||||
("*", ""),
|
||||
],
|
||||
},
|
||||
},
|
||||
)
|
||||
@@ -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: ${MESHCHAT_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
|
||||
|
||||
@@ -133,6 +133,14 @@ app.whenReady().then(async () => {
|
||||
webPreferences: {
|
||||
// used to inject logging over ipc
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
// Security: disable node integration in renderer
|
||||
nodeIntegration: false,
|
||||
// Security: enable context isolation (default in Electron 12+)
|
||||
contextIsolation: true,
|
||||
// Security: enable sandbox for additional protection
|
||||
sandbox: true,
|
||||
// Security: disable remote module (deprecated but explicit)
|
||||
enableRemoteModule: false,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
3
meshchatx/__init__.py
Normal file
@@ -0,0 +1,3 @@
|
||||
"""Reticulum MeshChatX - A mesh network communications app."""
|
||||
|
||||
__version__ = "2.50.0"
|
||||
@@ -1,4 +1,4 @@
|
||||
from datetime import datetime, timezone
|
||||
from datetime import UTC, datetime
|
||||
|
||||
from peewee import * # noqa: F403
|
||||
from playhouse.migrate import SqliteMigrator
|
||||
@@ -17,7 +17,9 @@ def migrate(current_version):
|
||||
if current_version < 2:
|
||||
migrate_database(
|
||||
migrator.add_column(
|
||||
"lxmf_messages", "delivery_attempts", LxmfMessage.delivery_attempts,
|
||||
"lxmf_messages",
|
||||
"delivery_attempts",
|
||||
LxmfMessage.delivery_attempts,
|
||||
),
|
||||
migrator.add_column(
|
||||
"lxmf_messages",
|
||||
@@ -66,8 +68,8 @@ class Config(BaseModel):
|
||||
id = BigAutoField() # noqa: F405
|
||||
key = CharField(unique=True) # noqa: F405
|
||||
value = TextField() # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -85,7 +87,7 @@ class Announce(BaseModel):
|
||||
identity_hash = CharField( # noqa: F405
|
||||
index=True,
|
||||
) # identity hash that announced the destination
|
||||
identity_public_key = ( # noqa: F405
|
||||
identity_public_key = (
|
||||
CharField() # noqa: F405
|
||||
) # base64 encoded public key, incase we want to recreate the identity manually
|
||||
app_data = TextField(null=True) # noqa: F405 # base64 encoded app data bytes
|
||||
@@ -93,8 +95,8 @@ class Announce(BaseModel):
|
||||
snr = FloatField(null=True) # noqa: F405
|
||||
quality = FloatField(null=True) # noqa: F405
|
||||
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -106,8 +108,8 @@ class CustomDestinationDisplayName(BaseModel):
|
||||
destination_hash = CharField(unique=True) # noqa: F405 # unique destination hash
|
||||
display_name = CharField() # noqa: F405 # custom display name for the destination hash
|
||||
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -120,8 +122,8 @@ class FavouriteDestination(BaseModel):
|
||||
display_name = CharField() # noqa: F405 # custom display name for the destination hash
|
||||
aspect = CharField() # noqa: F405 # e.g: nomadnetwork.node
|
||||
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -133,7 +135,7 @@ class LxmfMessage(BaseModel):
|
||||
hash = CharField(unique=True) # noqa: F405 # unique lxmf message hash
|
||||
source_hash = CharField(index=True) # noqa: F405
|
||||
destination_hash = CharField(index=True) # noqa: F405
|
||||
state = ( # noqa: F405
|
||||
state = (
|
||||
CharField() # noqa: F405
|
||||
) # state is converted from internal int to a human friendly string
|
||||
progress = FloatField() # noqa: F405 # progress is converted from internal float 0.00-1.00 to float between 0.00/100 (2 decimal places)
|
||||
@@ -150,15 +152,15 @@ class LxmfMessage(BaseModel):
|
||||
title = TextField() # noqa: F405
|
||||
content = TextField() # noqa: F405
|
||||
fields = TextField() # noqa: F405 # json string
|
||||
timestamp = ( # noqa: F405
|
||||
timestamp = (
|
||||
FloatField() # noqa: F405
|
||||
) # timestamp of when the message was originally created (before ever being sent)
|
||||
rssi = IntegerField(null=True) # noqa: F405
|
||||
snr = FloatField(null=True) # noqa: F405
|
||||
quality = FloatField(null=True) # noqa: F405
|
||||
is_spam = BooleanField(default=False) # noqa: F405 # if true, message is marked as spam
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -170,8 +172,8 @@ class LxmfConversationReadState(BaseModel):
|
||||
destination_hash = CharField(unique=True) # noqa: F405 # unique destination hash
|
||||
last_read_at = DateTimeField() # noqa: F405
|
||||
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -183,12 +185,12 @@ class LxmfUserIcon(BaseModel):
|
||||
destination_hash = CharField(unique=True) # noqa: F405 # unique destination hash
|
||||
icon_name = CharField() # noqa: F405 # material design icon name for the destination hash
|
||||
foreground_colour = CharField() # noqa: F405 # hex colour to use for foreground (icon colour)
|
||||
background_colour = ( # noqa: F405
|
||||
background_colour = (
|
||||
CharField() # noqa: F405
|
||||
) # hex colour to use for background (background colour)
|
||||
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -198,10 +200,11 @@ class LxmfUserIcon(BaseModel):
|
||||
class BlockedDestination(BaseModel):
|
||||
id = BigAutoField() # noqa: F405
|
||||
destination_hash = CharField( # noqa: F405
|
||||
unique=True, index=True,
|
||||
unique=True,
|
||||
index=True,
|
||||
) # unique destination hash that is blocked
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
@@ -211,10 +214,11 @@ class BlockedDestination(BaseModel):
|
||||
class SpamKeyword(BaseModel):
|
||||
id = BigAutoField() # noqa: F405
|
||||
keyword = CharField( # noqa: F405
|
||||
unique=True, index=True,
|
||||
unique=True,
|
||||
index=True,
|
||||
) # keyword to match against message content
|
||||
created_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(timezone.utc)) # noqa: F405
|
||||
created_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
updated_at = DateTimeField(default=lambda: datetime.now(UTC)) # noqa: F405
|
||||
|
||||
# define table name
|
||||
class Meta:
|
||||
1
meshchatx/src/backend/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Backend utilities shared by the Reticulum MeshChatX CLI."""
|
||||
@@ -7,7 +7,11 @@ class AnnounceHandler:
|
||||
|
||||
# we will just pass the received announce back to the provided callback
|
||||
def received_announce(
|
||||
self, destination_hash, announced_identity, app_data, announce_packet_hash,
|
||||
self,
|
||||
destination_hash,
|
||||
announced_identity,
|
||||
app_data,
|
||||
announce_packet_hash,
|
||||
):
|
||||
try:
|
||||
# handle received announce
|
||||
@@ -18,6 +22,6 @@ class AnnounceHandler:
|
||||
app_data,
|
||||
announce_packet_hash,
|
||||
)
|
||||
except Exception: # noqa: E722
|
||||
except Exception:
|
||||
# ignore failure to handle received announce
|
||||
pass
|
||||
@@ -146,7 +146,9 @@ class AudioCallManager:
|
||||
|
||||
# attempts to initiate a call to the provided destination and returns the link hash on success
|
||||
async def initiate(
|
||||
self, destination_hash: bytes, timeout_seconds: int = 15,
|
||||
self,
|
||||
destination_hash: bytes,
|
||||
timeout_seconds: int = 15,
|
||||
) -> AudioCall:
|
||||
# determine when to timeout
|
||||
timeout_after_seconds = time.time() + timeout_seconds
|
||||
@@ -240,7 +242,7 @@ class AudioCallReceiver:
|
||||
)
|
||||
link.teardown()
|
||||
return
|
||||
except Exception: # noqa: E722
|
||||
except Exception:
|
||||
# if we can't get identity yet, we'll check later
|
||||
pass
|
||||
|
||||
@@ -71,7 +71,8 @@ class WebsocketClientInterface(Interface):
|
||||
self.websocket.send(data)
|
||||
except Exception as e:
|
||||
RNS.log(
|
||||
f"Exception occurred while transmitting via {self!s}", RNS.LOG_ERROR,
|
||||
f"Exception occurred while transmitting via {self!s}",
|
||||
RNS.LOG_ERROR,
|
||||
)
|
||||
RNS.log(f"The contained exception was: {e!s}", RNS.LOG_ERROR)
|
||||
return
|
||||
@@ -93,7 +94,9 @@ class WebsocketClientInterface(Interface):
|
||||
try:
|
||||
RNS.log(f"Connecting to Websocket for {self!s}...", RNS.LOG_DEBUG)
|
||||
self.websocket = connect(
|
||||
f"{self.target_url}", max_size=None, compression=None,
|
||||
f"{self.target_url}",
|
||||
max_size=None,
|
||||
compression=None,
|
||||
)
|
||||
RNS.log(f"Connected to Websocket for {self!s}", RNS.LOG_DEBUG)
|
||||
self.read_loop()
|
||||
@@ -3,9 +3,8 @@ import time
|
||||
|
||||
import RNS
|
||||
from RNS.Interfaces.Interface import Interface
|
||||
from websockets.sync.server import Server, ServerConnection, serve
|
||||
|
||||
from src.backend.interfaces.WebsocketClientInterface import WebsocketClientInterface
|
||||
from websockets.sync.server import Server, ServerConnection, serve
|
||||
|
||||
|
||||
class WebsocketServerInterface(Interface):
|
||||
1
meshchatx/src/backend/interfaces/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
"""Shared transport interfaces for MeshChatX."""
|
||||
|
Before Width: | Height: | Size: 109 KiB After Width: | Height: | Size: 109 KiB |
|
Before Width: | Height: | Size: 80 KiB After Width: | Height: | Size: 80 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 4.4 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 8.0 KiB After Width: | Height: | Size: 8.0 KiB |
|
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 85 KiB After Width: | Height: | Size: 85 KiB |