Skip to content

Commit f0c44ba

Browse files
committed
0.11.3
1 parent f9fa056 commit f0c44ba

File tree

6 files changed

+71
-11
lines changed

6 files changed

+71
-11
lines changed

nightwatch/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = "0.11.2"
1+
__version__ = "0.11.3"
22

33
import re
44
HEX_COLOR_REGEX = re.compile(r"^[A-Fa-f0-9]{6}$")

nightwatch/rics/__init__.py

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88

99
from pydantic import BaseModel, Field
1010

11+
from requests import Session
1112
from fastapi import FastAPI, WebSocket
1213
from fastapi.responses import JSONResponse
1314
from fastapi.middleware.cors import CORSMiddleware
1415
from starlette.websockets import WebSocketDisconnect, WebSocketState
1516

1617
from nightwatch import __version__
18+
from nightwatch.logging import log
1719
from nightwatch.config import fetch_config
1820

1921
# Load config data
@@ -23,6 +25,21 @@
2325
app = FastAPI(openapi_url = None)
2426
app.add_middleware(CORSMiddleware, allow_origins = ["*"], allow_methods = ["*"])
2527

28+
session = Session()
29+
30+
# Check for updates
31+
app.state.latest_update = None
32+
if config["enable_update_checking"] is not False:
33+
latest = session.get("https://api.github.com/repos/iiPythonx/nightwatch/releases/latest").json()
34+
35+
def version(v: str) -> tuple:
36+
return tuple(map(int, v.split(".")))
37+
38+
if version(latest["name"][1:]) > version(__version__):
39+
log.info("update", f"Nightwatch {latest['name']} is now available, upgrading is recommended.")
40+
log.info("update", f"See the changelog at {latest['html_url']}.")
41+
app.state.latest_update = latest["name"][1:]
42+
2643
# Scaffold the application
2744
app.state.clients = {}
2845
app.state.pending_clients = {}
@@ -43,7 +60,7 @@ async def broadcast(payload: dict) -> None:
4360

4461
# Setup routing
4562
class Client:
46-
def __init__(self, websocket: WebSocket, user_data) -> None:
63+
def __init__(self, websocket: WebSocket, user_data: dict[str, typing.Any]) -> None:
4764
self.websocket = websocket
4865
self.username, self.hex_code = user_data["username"], user_data["hex"]
4966

@@ -95,6 +112,9 @@ async def receive(self) -> typing.Any:
95112
except WebSocketDisconnect:
96113
pass
97114

115+
except Exception:
116+
await self.websocket.close(1002, "Some data parsing issue occured, check your payloads.")
117+
98118
return None
99119

100120
class ClientJoinModel(BaseModel):
@@ -185,7 +205,7 @@ async def connect_endpoint(
185205

186206
@app.get("/api/version")
187207
async def route_version() -> JSONResponse:
188-
return JSONResponse({"code": 200, "data": {"version": __version__}})
208+
return JSONResponse({"code": 200, "data": {"version": __version__, "latest": app.state.latest_update}})
189209

190210
# Load additional routes
191211
from nightwatch.rics.routing import ( # noqa: E402

nightwatch/rics/routing/image_forward.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,17 @@
66
import binascii
77

88
from fastapi import Response
9+
from requests import RequestException
910
from fastapi.responses import JSONResponse
10-
from requests import Session, RequestException
1111

12-
from nightwatch.rics import app
12+
from nightwatch.rics import app, session
1313
from nightwatch.logging import log
1414

1515
# Exceptions
1616
class IllegalURL(Exception):
1717
pass
1818

1919
# Handle image forwarding
20-
SESSION = Session()
2120
PROXY_SIZE_LIMIT = 10 * (1024 ** 2)
2221

2322
FORWARD_DOMAIN = os.getenv("DOMAIN")
@@ -40,7 +39,7 @@ async def forward_image(public_url: str) -> Response | JSONResponse:
4039

4140
try:
4241
data = b""
43-
with SESSION.get(new_url, stream = True) as response:
42+
with session.get(new_url, stream = True) as response:
4443
response.raise_for_status()
4544
for chunk in response.iter_content(PROXY_SIZE_LIMIT):
4645
data += chunk

nightwatch/web/css/main.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ main.loading {
4747
flex-direction: row;
4848
align-items: center;
4949
justify-content: center;
50+
text-align: center;
5051
}
5152

5253
/* Random ass theming */

nightwatch/web/js/flows/connection.js

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// Copyright (c) 2024 iiPython
22

33
const CHARSET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
4+
const PROTOCOL_VERSION = "0.11.2";
45

56
export default class ConnectionManager {
67
constructor(payload, callbacks) {
@@ -24,11 +25,24 @@ export default class ConnectionManager {
2425
this.websocket.addEventListener("message", (e) => this.#on_message(e));
2526
this.callbacks.on_connect();
2627
});
27-
this.websocket.addEventListener("close", _ => console.warn("Connection closed"));
28-
this.websocket.addEventListener("error", e => console.error(e));
28+
this.websocket.addEventListener("close", e => this.callbacks.on_problem({ type: "generic", data: e.reason || "Connection was closed." }));
29+
this.websocket.addEventListener("error", e => this.callbacks.on_problem({ type: "something", data: e }));
2930
}
3031

3132
async #authenticate(username, hex) {
33+
try {
34+
const version_response = await fetch(`http${this.protocol}://${this.url}/api/version`);
35+
if (!version_response.ok) return this.callbacks.on_problem({ type: "unknown-version" });
36+
37+
const info = (await version_response.json()).data;
38+
if (PROTOCOL_VERSION.localeCompare(info.version, undefined, { numeric: true, sensitivity: "base" }) === 1) {
39+
return this.callbacks.on_problem({ type: "outdated-version", data: { version: info.version, supported: PROTOCOL_VERSION } });
40+
}
41+
42+
} catch (e) {
43+
return this.callbacks.on_problem({ type: "unknown-version" });
44+
}
45+
3246
const response = await (await fetch(
3347
`http${this.protocol}://${this.url}/api/join`,
3448
{
@@ -63,10 +77,10 @@ export default class ConnectionManager {
6377
case "join":
6478
case "leave":
6579
this.callbacks.handle_member(type, data.user);
66-
break
80+
break;
6781

6882
case "problem":
69-
console.warn({ type, data });
83+
this.callbacks.on_problem({ type: "protocol", data });
7084
break;
7185
}
7286
}

nightwatch/web/js/nightwatch.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,31 @@ const FILE_HANDLER = new FileHandler();
3737
const connection = new ConnectionManager(
3838
{ username, hex, address },
3939
{
40+
on_problem: ({ type, data }) => {
41+
main.classList = "loading", main.style.width = "520px";
42+
switch (type) {
43+
case "outdated-version":
44+
main.innerHTML = `This client is too new to connect.<br>RICS version ${data.version}, client version >= ${data.supported}`;
45+
break;
46+
47+
case "unknown-version":
48+
main.innerHTML = `Trying to fetch the RICS version failed.<br>The server might be offline, or it might be too old.`;
49+
break;
50+
51+
case "generic":
52+
main.innerHTML = data;
53+
break;
54+
55+
case "protocol":
56+
main.innerHTML = data.message;
57+
break;
58+
}
59+
if (connection.websocket.readyState === WebSocket.OPEN) {
60+
connection.websocket.close(1000, "The client is terminating this connection due to protocol error.");
61+
connection.callbacks.on_problem = () => {}; // Silence the close message
62+
};
63+
console.error(type, data);
64+
},
4065
on_connect: () => {
4166
main.classList.remove("loading");
4267
main.classList.add("full-layout");
@@ -182,6 +207,7 @@ const FILE_HANDLER = new FileHandler();
182207
}
183208
}
184209
);
210+
window.connection = connection;
185211

186212
// Handle loading spinner
187213
main.classList.add("loading");

0 commit comments

Comments
 (0)