Skip to content

Commit

Permalink
Merge pull request #2 from DavidCEllis/rewrite_settings
Browse files Browse the repository at this point in the history
Complete write of server, convert settings to attrs
  • Loading branch information
DavidCEllis authored Dec 6, 2019
2 parents f86c147 + 82e0811 commit 8c8c551
Show file tree
Hide file tree
Showing 16 changed files with 179 additions and 130 deletions.
29 changes: 29 additions & 0 deletions application/app_server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from splitnotes2.server import app, get_notes, settings
import flask.cli as cli

# Stop flask from giving users an unhelpful warning.
cli.show_server_banner = lambda *x: None


def launch():
get_notes() # Sets internal 'notes' and 'notefile' variables

print(
"This server version of Splitnotes2 allows you view splitnotes via a browser window "
"and should work across a local network.\n"
"It is not intended to be used over the internet and as such is not based on a "
"production server."
)

print(
f"Connect a browser to http://{settings.server_hostname}:{settings.server_port}/ "
f"in order to view the notes."
)

print(f"This hostname and port can be changed in {settings.output_file} if needed.")

app.run(threaded=True, host=settings.server_hostname, port=settings.server_port)


if __name__ == "__main__":
launch()
20 changes: 11 additions & 9 deletions application/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,30 +8,32 @@
from cx_Freeze import setup, Executable

python3_dll = str(Path(sys.executable).parent / "python3.dll")
templates = str(
Path(__file__).resolve().parents[1] / "src" / "splitnotes2" / "ui" / "templates"
)
icon_file = str(Path(__file__).resolve().parents[1] / "resources" / "logo_alpha.ico")
icon_png = str(Path(__file__).resolve().parents[1] / "resources" / "logo_alpha.png")

base_path = Path(__file__).resolve().parents[1]
templates = str(base_path / "src" / "splitnotes2" / "templates")
static_folder = str(base_path / "src" / "splitnotes2" / "static")
icon_file = str(base_path / "resources" / "logo_alpha.ico")
icon_png = str(base_path / "resources" / "logo_alpha.png")

base = None
if sys.platform == "win32":
base = "Win32GUI"

options = {
"build_exe": {
"includes": "atexit",
"include_files": [python3_dll, templates, icon_png],
"includes": ["atexit", "jinja2.ext"],
"include_files": [python3_dll, templates, static_folder, icon_png],
}
}

executables = [
Executable("app.py", base=base, targetName="splitnotes2", icon=icon_file)
Executable("app.py", base=base, targetName="splitnotes2", icon=icon_file),
Executable("app_server.py", targetName="splitnotes2_server", icon=icon_file),
]

setup(
name="splitnotes2",
version="0.3.2",
version="0.5.0",
description="Speedrun splitnotes tool with HTML rendering",
options=options,
executables=executables,
Expand Down
10 changes: 10 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
SplitNotes2 is an application for displaying speedrun notes in sync with livesplit.
Requires *livesplit server* to be running.

There is now a server version included to allow reading from a browser on another device.

## Install/Setup ##

1. Under the Livesplit layout editor add 'LiveSplit Server' (listed under 'control')
Expand Down Expand Up @@ -32,6 +34,14 @@ with some additional enhancements and exceptions.
a backslash `\ ` at the end of a line will indicate that the line should **not**
have a break inserted (useful for headers and lists).

## splitnotes2_server.exe ##

Now included is a server version which launches a (local) webhost so you can view the splitnotes
on another device on your local network. Launch splitnotes2_server.exe to start the service.

If the hostname and port defaults aren't usable you can set them by editing server_hostname
and server_port in settings.json. There is no dialog for editing these settings yet.

### Example Notes ###

#### Source ####
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from setuptools import setup, find_packages

__version__ = "0.3.2"
__version__ = "0.5.0"
__author__ = "DavidCEllis"


Expand All @@ -19,7 +19,7 @@
"Programming Language :: Python :: 3.7",
],
package_dir={"": "src"},
install_requires=["pyside2", "jinja2", "bleach", "flask"],
install_requires=["pyside2", "jinja2", "bleach", "flask", "attrs"],
tests_require=["pytest", "pytest-cov", "pytest-qt"],
extras_require={"build_exe": ["cx-freeze"], "dev": ["black"]},
extras_require={"build_exe": ["cx-freeze", "pywin32"], "dev": ["black"]},
)
5 changes: 5 additions & 0 deletions src/splitnotes2/livesplit_client/networking.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ def connect(self):
self.sock.close()
self.sock = None
return False
except socket.gaierror:
# Could not resolve hostname
self.sock.close()
self.sock = None
return False
else:
self.sock.settimeout(self.timeout)
return True
Expand Down
1 change: 1 addition & 0 deletions src/splitnotes2/server/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .split_server import app, get_notes, settings
68 changes: 36 additions & 32 deletions src/splitnotes2/server/split_server.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,32 @@
import random
import secrets
import socket
import string
import time
from pathlib import Path

from flask import Flask, render_template, Response
from PySide2.QtWidgets import QApplication, QFileDialog

from splitnotes2.settings import Settings
from splitnotes2.livesplit_client import get_client
from splitnotes2.note_parser import Notes
from ..settings import Settings
from ..livesplit_client import get_client
from ..note_parser import Notes

KEEP_ALIVE = 10

settings = Settings.load()

template_folder = str(Path(__file__).parent / "templates")
static_folder = str(Path(__file__).parent / "static")

app = Flask("splitnotes2", template_folder=template_folder, static_folder=static_folder)
app = Flask(
"splitnotes2",
template_folder=settings.server_template_folder,
static_folder=settings.server_static_folder,
)

notefile = None
notes = None

settings = Settings()

app.secret_key = "".join(
secrets.choice(string.printable) for _ in range(random.randint(30, 40))
)
Expand All @@ -37,7 +40,7 @@ def notes_page():
:return:
"""
global notefile
return render_template("index.html", notefile=notefile.stem)
return render_template(settings.server_html_template_file, notefile=notefile.stem)


@app.route("/splits")
Expand All @@ -56,6 +59,10 @@ def event_stream():
last_update = 0
client = get_client(settings.hostname, settings.port)
connected = client.connect()
# Note if the previous state was not connected
disconnected = True
# Define empty data, used to display the last notes even if disconnected
data = ""

while True:
if connected:
Expand All @@ -64,12 +71,20 @@ def event_stream():
new_index = max(client.get_split_index(), 0)
except (ConnectionError, TimeoutError):
connected = client.connect()
yield "data: <h1>Trying to connect to livesplit.</h1>\n\n"
yield (
f"data: <h2>Trying to connect to livesplit.</h2>"
f"<h3>Make sure Livesplit server is running.</h3>{data}\n\n"
)
else:
if current_note_index != new_index:
if current_note_index != new_index or disconnected:
disconnected = False

last_update = now
current_note_index = new_index
split_text = notes.render_splits(new_index, new_index + 1)
split_text = notes.render_splits(
new_index - settings.server_previous_splits,
new_index + settings.server_next_splits + 1,
)
if len(split_text) > 0:
# Remove newlines from the notes as they break the send
data = split_text[0].replace("\n", "")
Expand All @@ -80,14 +95,19 @@ def event_stream():
last_update = now
yield ":No update, keep connection\n\n"
else:
disconnected = True
connected = client.connect()
yield "data: <h1>Trying to connect to livesplit.</h1>\n\n"
yield (
f"data: <h2>Trying to connect to livesplit.</h2>"
f"<h3>Make sure Livesplit server is running.</h3>{data}\n\n"
)
time.sleep(0.5)

return Response(event_stream(), mimetype="text/event-stream")


def get_filename():
def get_notes():
global notes, notefile
temp_app = QApplication()

filepath, _ = QFileDialog.getOpenFileName(
Expand All @@ -99,24 +119,8 @@ def get_filename():

temp_app.quit()

filepath = Path(filepath)
return filepath


def launch():
global notes, notefile
notefile = get_filename()
settings.notes_folder = str(Path(notefile).parent)
settings.save()
notefile = Path(filepath)
notes = Notes.from_file(notefile)

hostname = socket.gethostname()
port = 14250

print(f"Connect a browser to http://{hostname}:{port}/")

app.run(threaded=True, host=hostname, port=port)


if __name__ == "__main__":
launch()
settings.notes_folder = str(notefile.parent)
settings.save()
Loading

0 comments on commit 8c8c551

Please sign in to comment.