add half-working client

This commit is contained in:
2025-05-05 00:15:12 +02:00
parent 776ee8d637
commit bfa0ba8edf
13 changed files with 782 additions and 38 deletions

View File

@@ -1,22 +1,55 @@
import { uint_bytes_to_num, utf8_decode } from "./tools";
import { sleep, uint_bytes_to_num, utf8_decode, utf8_encode } from "./tools";
import { WSClient } from "./ws";
enum PythagorasIncomingMessageType {
SubUpdateCur,
SubFinishCur,
SelectedMessage,
export enum PythagorasIncomingMessageType {
// subtitles
SubEnUpdateCur = "subtitle_en_update_current",
SubEnSubmit = "subtitle_en_submit_sentence",
SubCzSubmit = "subtitle_cs_submit_sentence",
// mode management
SetScreen = "setscreen",
// video
PlayVideo = "playvideo",
SeekVideo = "seekvideo",
// message
SelectedMessage = "selectedmessage",
};
type PythagorasIncomingMessage = (
export type PythagorasIncomingMessage = (
{
type: PythagorasIncomingMessageType.SubFinishCur | PythagorasIncomingMessageType.SubUpdateCur,
type: (
PythagorasIncomingMessageType.SubEnUpdateCur |
PythagorasIncomingMessageType.SubEnSubmit |
PythagorasIncomingMessageType.SubCzSubmit
),
text: string,
} |
{
type: PythagorasIncomingMessageType.SelectedMessage,
message: string,
message: string | null,
} |
{
type: PythagorasIncomingMessageType.SetScreen,
screen: "main" | "video" | "idle",
} |
{
type: PythagorasIncomingMessageType.PlayVideo,
filename: string,
subtitles: string,
seconds_from_start: number,
} |
{
type: PythagorasIncomingMessageType.SeekVideo,
timestamp: number,
}
);
@@ -27,8 +60,6 @@ export class PythagorasClient {
private buf: Uint8Array;
private static max_recv_retry: number = 10;
public constructor(addr: string) {
this.sock = null;
this.addr = addr;
@@ -46,12 +77,22 @@ export class PythagorasClient {
*/
private async recv_inner(): Promise<Blob> {
if (this.sock === null) { await this.reconnect(); }
for (let i = 0; i < PythagorasClient.max_recv_retry; ++i) {
while (true) {
const received = await this.sock!.receive();
if (received !== null) { return received; }
await sleep(500);
await this.reconnect();
}
throw new Error("max reconnection attempts reached");
}
/**
* Force receive from the underlying `WSClient` and convert the result to bytes (if the result
* is not bytes already).
*/
private async recv_inner_bytes(): Promise<Uint8Array> {
const received = await this.recv_inner();
if (received.bytes !== undefined) { return await received.bytes(); }
return utf8_encode(await received.text());
}
/**
@@ -60,7 +101,7 @@ export class PythagorasClient {
private async recv_length(target: number): Promise<Uint8Array> {
if (target == 0) { return new Uint8Array(0); }
while (this.buf.length < target) {
const received = await (await this.recv_inner()).bytes();
const received = await this.recv_inner_bytes();
const merged = new Uint8Array(this.buf.length + received.length);
merged.set(this.buf);
merged.set(received, this.buf.length);
@@ -73,8 +114,17 @@ export class PythagorasClient {
}
public async recv(): Promise<PythagorasIncomingMessage> {
const advertised_length = uint_bytes_to_num(await this.recv_length(4));
const payload = utf8_decode(await this.recv_length(advertised_length));
return JSON.parse(payload);
while (true) {
const advertised_length = uint_bytes_to_num(await this.recv_length(4));
try {
const payload = utf8_decode(await this.recv_length(advertised_length));
const parsed = JSON.parse(payload);
console.log(parsed);
return parsed;
} catch {
this.buf = new Uint8Array(0);
await this.reconnect();
}
}
}
}