add setup script to build an msi windows installer

This commit is contained in:
liamcottle
2024-05-24 01:35:30 +12:00
parent e2f62d46c4
commit d42801c135
6 changed files with 72 additions and 2 deletions

5
.gitignore vendored
View File

@@ -1 +1,6 @@
# build files
build/
dist/
# local storage
storage/

View File

@@ -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!
# Build from Source
You can build a standalone Windows Installer `.msi` with the following command;
```
python setup.py bdist_msi
```
## TODO
- [ ] conversations/contacts list ui with unread indicators

BIN
logo/icon.ico Normal file
View File

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -1,4 +1,5 @@
aiohttp>=3.9.5
cx_freeze>=7.0.0
lxmf>=0.4.3
peewee>=3.17.3
rns>=0.7.5

44
setup.py Normal file
View 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
View File

@@ -3,6 +3,7 @@
import argparse
import json
import os
import sys
import time
from datetime import datetime, timezone
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
# 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:
def __init__(self, identity: RNS.Identity, storage_dir, reticulum_config_dir):
@@ -116,7 +128,7 @@ class ReticulumWebChat:
# serve index.html
@routes.get("/")
async def index(request):
return web.FileResponse(path="public/index.html")
return web.FileResponse(path=get_file_path("public/index.html"))
# handle websocket clients
@routes.get("/ws")
@@ -562,7 +574,7 @@ class ReticulumWebChat:
# create and run web app
app = web.Application()
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_startup.append(on_startup)
web.run_app(app, host=host, port=port)