add setup script to build an msi windows installer
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,6 @@
|
|||||||
|
# build files
|
||||||
|
build/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# local storage
|
||||||
storage/
|
storage/
|
||||||
|
|||||||
@@ -115,6 +115,14 @@ python web.py --identity-base64 "GCN6mMhVemdNIK/fw97C1zvU17qjQPFTXRBotVckeGmoOwQ
|
|||||||
|
|
||||||
> NOTE: this is a randomly generated identity for example purposes. Do not use it, it has been leaked!
|
> NOTE: this is a randomly generated identity for example purposes. Do not use it, it has been leaked!
|
||||||
|
|
||||||
|
# Build from Source
|
||||||
|
|
||||||
|
You can build a standalone Windows Installer `.msi` with the following command;
|
||||||
|
|
||||||
|
```
|
||||||
|
python setup.py bdist_msi
|
||||||
|
```
|
||||||
|
|
||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- [ ] conversations/contacts list ui with unread indicators
|
- [ ] conversations/contacts list ui with unread indicators
|
||||||
|
|||||||
BIN
logo/icon.ico
Normal file
BIN
logo/icon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 127 KiB |
@@ -1,4 +1,5 @@
|
|||||||
aiohttp>=3.9.5
|
aiohttp>=3.9.5
|
||||||
|
cx_freeze>=7.0.0
|
||||||
lxmf>=0.4.3
|
lxmf>=0.4.3
|
||||||
peewee>=3.17.3
|
peewee>=3.17.3
|
||||||
rns>=0.7.5
|
rns>=0.7.5
|
||||||
|
|||||||
44
setup.py
Normal file
44
setup.py
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
from cx_Freeze import setup, Executable
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name='ReticulumWebChat',
|
||||||
|
version='1.0.0',
|
||||||
|
description='A simple open-source web based LXMF client for Reticulum.',
|
||||||
|
executables=[
|
||||||
|
Executable(
|
||||||
|
script='web.py', # this script to run
|
||||||
|
base=None, # we are running a console application, not a gui
|
||||||
|
target_name='ReticulumWebChat', # creates ReticulumWebChat.exe
|
||||||
|
shortcut_name='ReticulumWebChat', # name shown in shortcut
|
||||||
|
shortcut_dir='ProgramMenuFolder', # put the shortcut in windows start menu
|
||||||
|
icon='logo/icon.ico', # set the icon for the exe
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'build_exe': {
|
||||||
|
# libs that are required
|
||||||
|
'packages': [
|
||||||
|
# required for dynamic import fix
|
||||||
|
# https://github.com/marcelotduarte/cx_Freeze/discussions/2039
|
||||||
|
# https://github.com/marcelotduarte/cx_Freeze/issues/2041
|
||||||
|
'RNS',
|
||||||
|
],
|
||||||
|
# files that are required
|
||||||
|
'include_files': [
|
||||||
|
'public/', # static files served by web server
|
||||||
|
],
|
||||||
|
# slim down the build by excluding these unused libs
|
||||||
|
'excludes': [
|
||||||
|
'PIL', # saves ~200MB
|
||||||
|
],
|
||||||
|
# this has the same effect as the -O command line option when executing CPython directly.
|
||||||
|
# it also prevents assert statements from executing, removes docstrings and sets __debug__ to False.
|
||||||
|
# https://stackoverflow.com/a/57948104
|
||||||
|
"optimize": 2,
|
||||||
|
},
|
||||||
|
'build_msi': {
|
||||||
|
# use a static upgrade code to allow installer to remove existing files on upgrade
|
||||||
|
'upgrade_code': '{6c69616d-ae73-460c-88e8-399b3134134e}',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
)
|
||||||
16
web.py
16
web.py
@@ -3,6 +3,7 @@
|
|||||||
import argparse
|
import argparse
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import time
|
import time
|
||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from typing import Callable, List
|
from typing import Callable, List
|
||||||
@@ -21,6 +22,17 @@ from lxmf_message_fields import LxmfImageField, LxmfFileAttachmentsField, LxmfFi
|
|||||||
from src.audio_call_manager import AudioCall, AudioCallManager
|
from src.audio_call_manager import AudioCall, AudioCallManager
|
||||||
|
|
||||||
|
|
||||||
|
# NOTE: this is required to be able to pack our app with cxfreeze as an exe, otherwise it can't access bundled assets
|
||||||
|
# this returns a file path based on if we are running web.py directly, or if we have packed it as an exe with cxfreeze
|
||||||
|
# https://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files
|
||||||
|
def get_file_path(filename):
|
||||||
|
if getattr(sys, "frozen", False):
|
||||||
|
datadir = os.path.dirname(sys.executable)
|
||||||
|
else:
|
||||||
|
datadir = os.path.dirname(__file__)
|
||||||
|
return os.path.join(datadir, filename)
|
||||||
|
|
||||||
|
|
||||||
class ReticulumWebChat:
|
class ReticulumWebChat:
|
||||||
|
|
||||||
def __init__(self, identity: RNS.Identity, storage_dir, reticulum_config_dir):
|
def __init__(self, identity: RNS.Identity, storage_dir, reticulum_config_dir):
|
||||||
@@ -116,7 +128,7 @@ class ReticulumWebChat:
|
|||||||
# serve index.html
|
# serve index.html
|
||||||
@routes.get("/")
|
@routes.get("/")
|
||||||
async def index(request):
|
async def index(request):
|
||||||
return web.FileResponse(path="public/index.html")
|
return web.FileResponse(path=get_file_path("public/index.html"))
|
||||||
|
|
||||||
# handle websocket clients
|
# handle websocket clients
|
||||||
@routes.get("/ws")
|
@routes.get("/ws")
|
||||||
@@ -562,7 +574,7 @@ class ReticulumWebChat:
|
|||||||
# create and run web app
|
# create and run web app
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
app.add_routes(routes)
|
app.add_routes(routes)
|
||||||
app.add_routes([web.static('/', "public")]) # serve anything in public folder
|
app.add_routes([web.static('/', get_file_path("public/"))]) # serve anything in public folder
|
||||||
app.on_shutdown.append(self.shutdown) # need to force close websockets and stop reticulum now
|
app.on_shutdown.append(self.shutdown) # need to force close websockets and stop reticulum now
|
||||||
app.on_startup.append(on_startup)
|
app.on_startup.append(on_startup)
|
||||||
web.run_app(app, host=host, port=port)
|
web.run_app(app, host=host, port=port)
|
||||||
|
|||||||
Reference in New Issue
Block a user