@groovenet/player 0.1.4 → 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,6 +45,9 @@ and `isPlay` are the pure rules: a track of 30 seconds or more counts after
45
45
  `min(50% of its duration, 240 s)` of accumulated play time, where only forward
46
46
  progress while playing is counted. The CLI wires it to `POST /api/spins` with
47
47
  `medium: "digital"` (`player_log_plays` / `--log-plays`).
48
+ Persistent server players apply the same threshold per queue entry and deliver
49
+ owner-library plays through the app's `/api/spins` endpoint. Pending deliveries
50
+ are stored in Postgres for retries across worker restarts.
48
51
 
49
52
  `MpvBackend` does not install mpv. Install it separately and make it available
50
53
  on `PATH`, or pass an executable path in the constructor. `close()` stops the
package/SERVER_PLAYERS.md CHANGED
@@ -6,7 +6,8 @@ queue and one dedicated OwnTone engine. Different players can use different
6
6
  speakers concurrently; synchronized groups are deferred. This is the backend
7
7
  for #693; remote TUI controls are tracked in #694. The web UI can control these sessions through an optional household browser
8
8
  session; see [web controls](../../my-collection-search/docs/server-player-web.md).
9
- There is no iOS UI yet.
9
+ There is no iOS UI yet. Web authorization can be provisioned from 1Password with
10
+ `just player-web-setup`; existing hosts remain opted out until that explicit setup.
10
11
 
11
12
  ## Deployment
12
13
 
@@ -24,10 +25,12 @@ builds the two local images before starting services. It survives the normal
24
25
  Player secrets and private worktree files are excluded from Docker build contexts.
25
26
 
26
27
  The optional `.env.players.tpl` uses the existing `GROOVENET_OP_VAULT` /
27
- `GROOVENET_OP_ITEM` selection (defaults `Homelab` / `groovenet`). Add three fields
28
- to that 1Password item: `PLAYER_API_KEY`, `PLAYER_ENGINE_A_PASSWORD`, and
29
- `PLAYER_ENGINE_B_PASSWORD`. API keys must be at least 32 characters on one line;
30
- engine passwords must be distinct hex/base64url values. To render locally:
28
+ `GROOVENET_OP_ITEM` selection (defaults `Homelab` / `groovenet`). Add four fields
29
+ to that 1Password item: `PLAYER_API_KEY`, `PLAYER_LIBRARY_FRIEND_ID`,
30
+ `PLAYER_ENGINE_A_PASSWORD`, and `PLAYER_ENGINE_B_PASSWORD`. The friend ID is the
31
+ positive `friends.id` of the library owner. API keys must be at least 32
32
+ characters on one line; engine passwords must be distinct hex/base64url values.
33
+ To render locally:
31
34
 
32
35
  ```sh
33
36
  mkdir -p .worktree
@@ -96,8 +99,10 @@ requires `/dev/shm/airptp_shm`, as well as network access to the clock. The engi
96
99
  entrypoint refuses startup without it. Run only one such shared clock per host.
97
100
 
98
101
  Outside Compose, build packages with `just build-packages`, then run
99
- `groovenet-player-server` with `DATABASE_URL`, `PLAYER_API_KEY` and
100
- `PLAYER_ENGINES_JSON`. Set the app's `PLAYER_WORKER_URL` to that private worker.
102
+ `groovenet-player-server` with `DATABASE_URL`, `PLAYER_API_KEY`,
103
+ `PLAYER_LIBRARY_FRIEND_ID`, `PLAYER_ENGINES_JSON` and `PLAYER_APP_URL` (the app
104
+ origin, default `http://app:3000`). Set the app's `PLAYER_WORKER_URL` to that
105
+ private worker.
101
106
  The standalone worker binds `0.0.0.0:13700` (override `PLAYER_WORKER_PORT`), so
102
107
  restrict access at the host/network boundary.
103
108
 
@@ -113,40 +118,97 @@ All public paths start with `/api/players`. Supply
113
118
  | `POST /api/players` | Create `{ "id": "lounge", "name": "Lounge", "engine_id": "primary" }` |
114
119
  | `GET /api/players/lounge` | Get full state and revision |
115
120
  | `GET /api/players/lounge/devices` | Discovered outputs, assignments and observations |
116
- | `POST /api/players/lounge/commands` | Apply a revisioned command |
121
+ | `POST /api/players/lounge/commands` | Apply a command |
117
122
  | `GET /api/players/lounge/events` | SSE snapshots and lightweight position updates |
118
123
 
119
124
  Each engine can belong to only one named player. Names can be changed; player
120
125
  IDs and engine assignments are fixed. Engine configuration is an operator
121
126
  allowlist, never a client-provided URL. Player deletion is not implemented.
122
127
 
123
- Commands include `expected_revision` from the most recent snapshot. A stale
124
- revision returns `REVISION_CONFLICT`; fetch fresh state before deciding whether
125
- to retry. Position ticks do not change the edit revision. For example:
128
+ Commands use last-write-wins behavior by default. Optionally include
129
+ `expected_revision` from a snapshot to require optimistic concurrency: a stale
130
+ value returns `REVISION_CONFLICT`. Position ticks do not change the revision.
131
+ Each player has a persisted `availability_policy`, initially `ask`. Set it with
132
+ the bearer credential:
133
+
134
+ ```sh
135
+ groovenet player set lounge --availability allow_unknown
136
+ groovenet player set lounge --availability always
137
+ groovenet player set lounge --availability ask
138
+ ```
139
+
140
+ The equivalent command is
141
+ `{"type":"availability.set","availability_policy":"allow_unknown","expected_revision":3}`.
142
+ `ask` requires the existing per-command acknowledgements. `allow_unknown`
143
+ connects when HA activity is unknown without `allow_unknown: true`, but still
144
+ requires `takeover: true` for observed occupied activity. `always` also permits
145
+ observed occupied activity without a takeover flag. Both policies apply to fresh
146
+ connection and reconnection checks; neither bypasses another Groovenet player's
147
+ assignment. Use `output.transfer` explicitly to move that assignment. Browser
148
+ sessions cannot change this policy.
149
+ For example:
126
150
 
127
151
  ```json
128
- {"type":"queue.add","expected_revision":0,"tracks":[{"track_id":"TRACK_ID","friend_id":1}]}
152
+ {"type":"queue.add","tracks":[{"track_id":"TRACK_ID","friend_id":1}]}
129
153
  ```
130
154
 
131
- After each command, use its returned player revision for the next command:
155
+ Scripts that need optimistic concurrency can use the returned player revision
156
+ for their next command:
132
157
 
133
158
  ```json
134
159
  {"type":"output.select","expected_revision":1,"output_id":"OUTPUT_ID"}
135
160
  ```
136
161
 
137
162
  ```json
138
- {"type":"play","expected_revision":2,"allow_unknown":true}
163
+ {"type":"play","allow_unknown":true}
139
164
  ```
140
165
 
141
166
  Selecting an output remembers intent; it does not connect or reserve the
142
167
  speaker. Playback requires indexed local audio, resolved afresh from Postgres.
143
168
  Queue entries get stable UUIDs, including repeated copies of the same track.
144
169
  Use those entry IDs for `queue.remove`, `queue.move` and an explicit `play`.
170
+ If an entry has disappeared, these commands return `ENTRY_NOT_FOUND`.
145
171
  Other commands are `rename`, `queue.clear`, `pause`, `resume`, `stop`, `next`,
146
172
  `previous`, `seek` (seconds) and `volume` (0–100). Stop clears the current entry
147
173
  and position while preserving the queue. Natural EOF advances only that player's
148
174
  queue; interruption/error preserves the current entry and requires a command.
149
175
 
176
+ ### Atomic queue replacement
177
+
178
+ `queue.replace` resolves every track before changing the queue or playback. An
179
+ unresolved track rejects the whole command. Entries accept optional UUIDs;
180
+ provided IDs are preserved and new entries receive generated IDs. Duplicate IDs
181
+ and reusing a current queue ID for another track/friend are rejected. Titles and
182
+ artists are resolved on the server, never accepted from the caller.
183
+
184
+ ```json
185
+ {"type":"queue.replace","expected_revision":3,"entries":[{"id":"11111111-1111-4111-8111-111111111111","track_id":"TRACK_ID","friend_id":1}],"current_entry_id":"11111111-1111-4111-8111-111111111111","position":42,"play":false}
186
+ ```
187
+
188
+ Omitting `current_entry_id` retains the current entry if present; otherwise it
189
+ selects the first replacement entry only when `play: true`. Explicit `null`
190
+ clears the current entry. A non-null ID must belong to the replacement queue.
191
+ Omitting `position` preserves the retained entry's position, or starts a new
192
+ entry at zero. An explicit position seeks a retained live entry, or saves a
193
+ checkpoint for a later play. Removing/changing the current entry stops playback
194
+ unless `play: true`. Retaining it keeps its existing backend and playing/paused
195
+ state; `play: true` resumes it. An empty replacement clears the queue and cannot
196
+ be played. Playback is opt-in and uses the usual output availability/assignment
197
+ checks; rejected preflight checks leave the old queue intact. Engine failures
198
+ after playback effects begin are reported as playback errors, not a rollback of
199
+ already-performed audio operations.
200
+
201
+ The typed client's `commandServerPlayer` accepts this command. From the CLI:
202
+
203
+ ```sh
204
+ groovenet player --remote lounge queue replace '{"entries":[{"track_id":"TRACK_ID","friend_id":1}],"play":true}' --json
205
+ ```
206
+
207
+ Use `--allow-unknown` or `--takeover` only when deliberately authorizing the
208
+ corresponding speaker policy. A replacement with retained UUIDs can restore an
209
+ Undo snapshot, including its current entry and position. Revisions still guard
210
+ against overwriting changes made after that snapshot.
211
+
150
212
  SSE begins with a complete `snapshot`. `position` events include player ID,
151
213
  revision, current entry ID and observation time; apply them only to a matching
152
214
  snapshot revision/entry. Each event also carries worker instance and sequence.
@@ -156,25 +218,88 @@ list/create/get/command/devices/engines requests; SSE can be consumed directly.
156
218
 
157
219
  ## Speaker activity and transfers
158
220
 
159
- Optionally configure `PLAYER_HA_URL`, `PLAYER_HA_TOKEN` and an output-to-entity
160
- map such as `PLAYER_HA_ENTITIES_JSON={"OUTPUT_ID":"media_player.lounge"}`.
161
- The observer only reads HA state, with a 2-second timeout and 5-second cache.
221
+ Configure `PLAYER_HA_URL`, `PLAYER_HA_TOKEN` and `PLAYER_HA_ENTITIES_JSON`
222
+ with exact OwnTone output IDs or names as keys. ID mappings take precedence.
223
+ Names are case-sensitive. A name mapping is used only when that name is unique
224
+ among the engine's discovered outputs; duplicate names remain unmapped unless
225
+ each output has an ID mapping. ID mappings always take precedence. Name mapping
226
+ still appears in device diagnostics when HA credentials are missing, so the
227
+ mapping can be checked separately from HA connectivity.
228
+ For example:
229
+
230
+ ```json
231
+ {"aswitch":"media_player.aswitch_streamer","Lounge Room Audio":"media_player.lounge_streamer","132116595608304":"media_player.bedroom_sonos"}
232
+ ```
233
+
234
+ Read-only inspection on beelink on 2026-10-25 confirmed both engines discover:
235
+
236
+ | OwnTone output ID | Name | HA entity from the installed registry (#691) |
237
+ | --- | --- | --- |
238
+ | `202481599519404` | aswitch | `media_player.aswitch_streamer` |
239
+ | `202481586338774` | Lounge Room Audio | `media_player.lounge_streamer` |
240
+ | `132116595608304` | Bedroom | `media_player.bedroom_sonos` |
241
+
242
+ The running worker had an empty HA URL/token and `{}` mappings. HA live states
243
+ could not be queried through that worker. These settings must be supplied to
244
+ `.env.players` and retained in the environment used to render it on deployment.
245
+ The optional `.env.players.tpl` does not supply HA credentials by default.
246
+
247
+ `groovenet player devices --remote lounge` (or the devices API) shows
248
+ `observed.entity_id`, availability, source, observation time and sender identity.
249
+ `entity=unmapped` exposes missing mappings; an entity with `source=unconfigured`
250
+ means the URL/token is missing. A configured but inaccessible entity reports
251
+ `source=home_assistant`, unknown activity and no observation timestamp.
252
+
253
+ The observer reads HA with a 2-second timeout. Device listings cache observations
254
+ for 5 seconds; connection/reconnection decisions always fetch fresh state.
162
255
  `idle`, `off`, `standby` mean observed idle; active/paused states mean occupied;
163
256
  unavailable, missing configuration and failed observations mean unknown.
164
- HA does not prove which app is sending audio. Observations can race another app.
257
+ Observations can race another app.
258
+
259
+ To recognise an engine, HA must expose receiver **session sender attributes**.
260
+ Configure exact attribute/value matches keyed by engine ID, for example:
261
+
262
+ ```sh
263
+ PLAYER_HA_SENDERS_JSON='{"primary":{"client_name":"Groovenet-primary","client_ip":"192.168.2.151"},"secondary":{"client_name":"Groovenet-secondary","client_ip":"192.168.2.151"}}'
264
+ ```
265
+
266
+ These attribute names/values are illustrative: inspect the actual HA entity
267
+ attributes before configuring them. All attributes for an engine must match;
268
+ exactly one engine must match. Matching only the beelink IP cannot distinguish
269
+ its two engines or another app on that host. Use a unique sender identifier,
270
+ never track metadata, a room source label or a shared host IP. Duplicate matches
271
+ remain unknown identity and occupied activity. Sender attributes must describe
272
+ the current session and be cleared/replaced on takeover. Idle/unavailable states
273
+ never identify a sender, even if attributes linger.
274
+
275
+ The installed `shairport_sync` 1.4.0 integration was inspected read-only: it
276
+ subscribes to playback and track metadata but exposes no client name/IP. It needs
277
+ an HA integration/receiver metadata update before this sender configuration can
278
+ work. Shairport's D-Bus client address is available on the Lounge receiver, but
279
+ its client name was empty in #691 and the address persists after disconnect.
280
+ Do not assume an engine library name appears as `client_name`. No receiver or HA
281
+ configuration was changed as part of the inspection.
282
+
283
+ An active matching sender reports `sender_identity=groovenet` and
284
+ `sender_engine_id`. Its own player may connect/resume without takeover; other
285
+ engines still need takeover. Nonmatching sender attributes report `foreign`;
286
+ missing/ambiguous attributes report `unknown`. Both retain occupancy protection.
165
287
 
166
288
  Connecting to unknown activity requires explicit `allow_unknown: true`.
167
- Occupied activity requires `takeover: true`. A paused engine may release its
168
- AirPlay transport, so resuming may require another availability decision.
289
+ Occupied activity requires `takeover: true` unless its sender identifies this
290
+ player's dedicated engine. A paused engine may release its AirPlay transport;
291
+ reconnection checks apply the same sender rules.
169
292
  Neither acknowledgement can steal another Groovenet player's assignment.
170
293
  For that, send `output.transfer` to the destination player:
171
294
 
172
295
  ```json
173
- {"type":"output.transfer","expected_revision":7,"from_player_id":"lounge","from_revision":12,"output_id":"OUTPUT_ID","play":true,"allow_unknown":true}
296
+ {"type":"output.transfer","from_player_id":"lounge","from_revision":12,"output_id":"OUTPUT_ID","play":true,"allow_unknown":true}
174
297
  ```
175
298
 
176
299
  Transfer detaches the source first and keeps each player's own queue and
177
300
  checkpoint. `play: false` only changes the destination's desired output.
301
+ `from_revision` is required even when `expected_revision` is omitted; it fences
302
+ the source player whose output is being transferred.
178
303
  Inspect `transfer.detached`, `attached` and `error` even when HTTP status is 200:
179
304
  the source can be detached while destination playback fails. It is never
180
305
  automatically reconnected to hide that partial result.
@@ -189,6 +314,14 @@ events share a serial lane; a slow engine can delay commands to other players.
189
314
  A worker restart restores **stopped checkpoints**, clears transient assignments
190
315
  and creates no engine connections. It never resumes or reclaims a speaker
191
316
  automatically. `checkpoint: true` means saved position, not observed live audio.
317
+
318
+ Server players log digital plays after the shared `playThreshold` listen time.
319
+ Only tracks belonging to `PLAYER_LIBRARY_FRIEND_ID` are eligible. Each queue
320
+ entry has its own durable delivery record; failed app API requests are retried
321
+ every 30 seconds and after a worker restart. An API conflict for an already
322
+ logged digital play completes the delivery. The worker must be able to reach
323
+ `POST /api/spins` at `PLAYER_APP_URL`.
324
+
192
325
  An abrupt crash can leave an old engine playing; stop that engine explicitly
193
326
  before issuing new playback if its ownership cannot be established. Do not use
194
327
  the dedicated engines from other controller apps.
@@ -1,25 +1,40 @@
1
1
  import { EventEmitter } from "node:events";
2
2
  import { type CreateServerPlayer, type ServerPlayer, type ServerPlayerCommand, type ServerPlayerCommandResult, type ServerPlayerDevice, type SpeakerObservation } from "@groovenet/contracts";
3
3
  import { type PlaybackBackend } from "../types.js";
4
- import { type PlayerStore } from "./store.js";
4
+ import { type PlayerStore, type ServerPlay } from "./store.js";
5
5
  export interface PlayerEngine {
6
6
  libraryRoot: string;
7
7
  create(outputId?: string): PlaybackBackend;
8
8
  }
9
- export type SpeakerObserver = (outputId: string) => Promise<SpeakerObservation>;
9
+ export type SpeakerObserver = (outputId: string, context?: {
10
+ outputName?: string;
11
+ resolveOutputName?: () => Promise<string | undefined>;
12
+ fresh?: boolean;
13
+ }) => Promise<SpeakerObservation>;
10
14
  export declare const unknownSpeaker: () => SpeakerObservation;
15
+ export interface ServerPlayLogging {
16
+ ownerFriendId: number;
17
+ logPlay: (play: ServerPlay) => Promise<void>;
18
+ now?: () => Date;
19
+ }
11
20
  /** Owns all player lifecycles; no HTTP connection owns a backend. */
12
21
  export declare class ServerPlayerManager extends EventEmitter {
13
22
  private readonly store;
14
23
  private readonly engines;
15
24
  private readonly observe;
25
+ private readonly playLogging?;
16
26
  private players;
17
27
  private runtimes;
18
28
  private generation;
19
29
  private tail;
20
30
  private stopping;
21
31
  private checkpointAt;
22
- constructor(store: PlayerStore, engines: Record<string, PlayerEngine>, observe?: SpeakerObserver);
32
+ private progress;
33
+ private queuedPlays;
34
+ private retrying;
35
+ constructor(store: PlayerStore, engines: Record<string, PlayerEngine>, observe?: SpeakerObserver, playLogging?: ServerPlayLogging | undefined);
36
+ /** Retry durable deliveries independently of queue changes and playback. */
37
+ retryPlays(): Promise<void>;
23
38
  private serial;
24
39
  initialize(): Promise<void>;
25
40
  engineIds(): string[];
@@ -28,6 +43,7 @@ export declare class ServerPlayerManager extends EventEmitter {
28
43
  create(input: CreateServerPlayer): Promise<ServerPlayer>;
29
44
  devices(id: string): Promise<ServerPlayerDevice[]>;
30
45
  command(id: string, input: ServerPlayerCommand): Promise<ServerPlayerCommandResult>;
46
+ private replaceQueue;
31
47
  private play;
32
48
  private enqueueEvent;
33
49
  private detach;
@@ -1 +1 @@
1
- {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/server/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAuD,KAAK,kBAAkB,EAAE,KAAK,YAAY,EAAE,KAAK,mBAAmB,EAAE,KAAK,yBAAyB,EAAE,KAAK,kBAAkB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAEnP,OAAO,EAAe,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEjE,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,eAAe,CAAC;CAC5C;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,CAAC,CAAC;AAChF,eAAO,MAAM,cAAc,QAAO,kBAA0H,CAAC;AAK7J,qEAAqE;AACrE,qBAAa,mBAAoB,SAAQ,YAAY;IAQvC,OAAO,CAAC,QAAQ,CAAC,KAAK;IAAe,OAAO,CAAC,QAAQ,CAAC,OAAO;IAAgC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAPjI,OAAO,CAAC,OAAO,CAAmC;IAClD,OAAO,CAAC,QAAQ,CAA8B;IAC9C,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,IAAI,CAAuC;IACnD,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,YAAY,CAA6B;IAEjD,YAA6B,KAAK,EAAE,WAAW,EAAmB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,EAAmB,OAAO,GAAE,eAA8C,EAAc;IAE/L,OAAO,CAAC,MAAM;IAMR,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAShC;IAED,SAAS,IAAI,MAAM,EAAE,CAA6C;IAClE,IAAI,IAAI,YAAY,EAAE,CAAkD;IACxE,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,YAAY,CAI5B;IAED,MAAM,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAUvD;IAEK,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAYvD;IAED,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,yBAAyB,CAAC,CAwFlF;YAEa,IAAI;IA2ElB,OAAO,CAAC,YAAY;YAcN,MAAM;YAYN,IAAI;YAOJ,QAAQ;IA2BhB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAQ9B;YAEa,gBAAgB;IAM9B,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,QAAQ;IAGhB,OAAO,CAAC,SAAS;YACH,IAAI;IAMlB,OAAO,CAAC,OAAO;CAChB"}
1
+ {"version":3,"file":"manager.d.ts","sourceRoot":"","sources":["../../src/server/manager.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import { randomUUID } from "node:crypto";
3
3
  import { createServerPlayerSchema, serverPlayerCommandSchema } from "@groovenet/contracts";
4
4
  import { audioSource } from "../resolver.js";
5
5
  import { PlayerError } from "../types.js";
6
+ import { advanceProgress, initialProgress, isPlay } from "../playThreshold.js";
6
7
  import { ServerPlayerError } from "./store.js";
7
8
  export const unknownSpeaker = () => ({ availability: "unknown", observed_at: null, source: "unconfigured", sender_identity: "unknown" });
8
9
  const errorValue = (error) => error instanceof PlayerError || error instanceof ServerPlayerError ? { code: error.code, message: error.message } : { code: "PLAYER_OPERATION_FAILED", message: "Player operation failed" };
@@ -12,17 +13,45 @@ export class ServerPlayerManager extends EventEmitter {
12
13
  store;
13
14
  engines;
14
15
  observe;
16
+ playLogging;
15
17
  players = new Map();
16
18
  runtimes = new Map();
17
19
  generation = 0;
18
20
  tail = Promise.resolve();
19
21
  stopping = false;
20
22
  checkpointAt = new Map();
21
- constructor(store, engines, observe = async () => unknownSpeaker()) {
23
+ progress = new Map();
24
+ queuedPlays = new Set();
25
+ retrying = false;
26
+ constructor(store, engines, observe = async () => unknownSpeaker(), playLogging) {
22
27
  super();
23
28
  this.store = store;
24
29
  this.engines = engines;
25
30
  this.observe = observe;
31
+ this.playLogging = playLogging;
32
+ }
33
+ /** Retry durable deliveries independently of queue changes and playback. */
34
+ async retryPlays() {
35
+ if (!this.playLogging || this.retrying || this.stopping)
36
+ return;
37
+ this.retrying = true;
38
+ try {
39
+ for (const play of await this.store.pendingPlays()) {
40
+ try {
41
+ await this.playLogging.logPlay(play);
42
+ await this.store.markPlayLogged(play.entryId);
43
+ }
44
+ catch (error) {
45
+ this.emit("play-log-error", error);
46
+ }
47
+ }
48
+ }
49
+ catch (error) {
50
+ this.emit("play-log-error", error);
51
+ }
52
+ finally {
53
+ this.retrying = false;
54
+ }
26
55
  }
27
56
  serial(action) {
28
57
  const result = this.tail.then(action);
@@ -65,10 +94,13 @@ export class ServerPlayerManager extends EventEmitter {
65
94
  const backend = runtime?.backend ?? this.engine(player).create();
66
95
  try {
67
96
  const outputs = await backend.listDevices();
97
+ const nameCounts = new Map();
98
+ for (const output of outputs)
99
+ nameCounts.set(output.name, (nameCounts.get(output.name) ?? 0) + 1);
68
100
  return await Promise.all(outputs.map(async (output) => ({ ...output,
69
101
  assigned_player_id: this.list().find((p) => p.assigned_output === output.id)?.id ?? null,
70
102
  desired_by: this.list().filter((p) => p.state.desired_output === output.id).map((p) => p.id),
71
- observed: await this.observe(output.id),
103
+ observed: await this.observe(output.id, { outputName: nameCounts.get(output.name) === 1 ? output.name : undefined }),
72
104
  })));
73
105
  }
74
106
  finally {
@@ -81,7 +113,8 @@ export class ServerPlayerManager extends EventEmitter {
81
113
  this.available();
82
114
  const command = serverPlayerCommandSchema.parse(input);
83
115
  let player = this.get(id);
84
- this.revision(player, command.expected_revision);
116
+ if (command.expected_revision !== undefined)
117
+ this.revision(player, command.expected_revision);
85
118
  if (command.type === "output.transfer")
86
119
  return this.transfer(player, command);
87
120
  try {
@@ -89,6 +122,9 @@ export class ServerPlayerManager extends EventEmitter {
89
122
  case "rename":
90
123
  player.name = command.name;
91
124
  break;
125
+ case "availability.set":
126
+ player.availability_policy = command.availability_policy;
127
+ break;
92
128
  case "queue.add": {
93
129
  const at = command.at ?? player.state.queue.length;
94
130
  if (at > player.state.queue.length || player.state.queue.length + command.tracks.length > 10000)
@@ -114,11 +150,14 @@ export class ServerPlayerManager extends EventEmitter {
114
150
  }
115
151
  case "queue.move": {
116
152
  const index = player.state.queue.findIndex((entry) => entry.id === command.entry_id);
117
- if (index < 0 || command.to >= player.state.queue.length)
153
+ if (index < 0)
154
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue entry does not exist", 404);
155
+ if (command.to >= player.state.queue.length)
118
156
  throw new ServerPlayerError("INVALID_QUEUE", "Queue move is out of range", 400);
119
157
  player.state.queue.splice(command.to, 0, player.state.queue.splice(index, 1)[0]);
120
158
  break;
121
159
  }
160
+ case "queue.replace": return { player: await this.replaceQueue(player, command) };
122
161
  case "queue.clear":
123
162
  await this.stop(player);
124
163
  player.state.queue = [];
@@ -138,7 +177,7 @@ export class ServerPlayerManager extends EventEmitter {
138
177
  if (this.runtimes.has(id)) {
139
178
  const backend = this.runtimes.get(id).backend;
140
179
  if (await backend.outputConnection?.() !== "connected")
141
- await this.requireAvailable(player.state.desired_output, command);
180
+ await this.requireAvailable(player, player.state.desired_output, command);
142
181
  await backend.pause(false);
143
182
  player.state.status = "playing";
144
183
  player.state.checkpoint = false;
@@ -203,10 +242,70 @@ export class ServerPlayerManager extends EventEmitter {
203
242
  }
204
243
  });
205
244
  }
245
+ async replaceQueue(player, command) {
246
+ // Resolve and validate the entire replacement before touching playback or
247
+ // saving anything. A bad final entry cannot leave a half-cleared queue.
248
+ const previousEntries = new Map(player.state.queue.map(entry => [entry.id, entry]));
249
+ const queue = [];
250
+ for (const ref of command.entries) {
251
+ const previous = ref.id ? previousEntries.get(ref.id) : undefined;
252
+ if (previous && (previous.track_id !== ref.track_id || previous.friend_id !== ref.friend_id))
253
+ throw new ServerPlayerError("INVALID_QUEUE", "An existing entry ID cannot identify a different track", 400);
254
+ const track = await this.store.resolve(ref).catch(() => {
255
+ throw new ServerPlayerError("TRACK_RESOLUTION_FAILED", "Unable to resolve replacement tracks", 503);
256
+ });
257
+ if (!track)
258
+ throw new ServerPlayerError("TRACK_NOT_FOUND", "Queued track does not exist or is ambiguous", 404);
259
+ queue.push({ ...ref, id: ref.id ?? randomUUID(), title: track.title, artist: track.artist });
260
+ }
261
+ const retained = queue.some(entry => entry.id === player.state.current_entry_id);
262
+ const current = command.current_entry_id === undefined
263
+ ? (retained ? player.state.current_entry_id : command.play ? queue[0]?.id ?? null : null)
264
+ : command.current_entry_id;
265
+ if (current !== null && !queue.some(entry => entry.id === current))
266
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Current entry must belong to the replacement queue", 404);
267
+ if (command.play && current === null)
268
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Select a replacement entry before playing", 400);
269
+ const unchanged = current !== null && current === player.state.current_entry_id;
270
+ const position = command.position ?? (unchanged ? player.state.position : 0);
271
+ if (unchanged && this.runtimes.has(player.id)) {
272
+ const backend = this.active(player.id).backend;
273
+ if (command.play && player.state.status !== "playing") {
274
+ if (await backend.outputConnection?.() !== "connected")
275
+ await this.requireAvailable(player, player.state.desired_output, command);
276
+ await backend.pause(false);
277
+ player.state.status = "playing";
278
+ player.state.checkpoint = false;
279
+ player.state.error = null;
280
+ }
281
+ if (position !== player.state.position)
282
+ await backend.seek(position);
283
+ player.state.queue = queue;
284
+ player.state.position = position;
285
+ return this.save(player);
286
+ }
287
+ if (command.play) {
288
+ // play validates output policy and audio before detaching the old backend.
289
+ player.state.queue = queue;
290
+ player.state.current_entry_id = current;
291
+ player.state.position = position;
292
+ await this.play(player, current, command);
293
+ return this.get(player.id);
294
+ }
295
+ if (!unchanged)
296
+ await this.stop(player);
297
+ player.state.queue = queue;
298
+ player.state.current_entry_id = current;
299
+ player.state.position = current === null ? 0 : position;
300
+ player.state.checkpoint = current !== null && !this.runtimes.has(player.id);
301
+ if (player.state.status !== "error")
302
+ player.state.error = null;
303
+ return this.save(player);
304
+ }
206
305
  async play(player, entryId, policy, resumeCheckpoint = true) {
207
306
  const entry = player.state.queue.find((entry) => entry.id === entryId);
208
307
  if (!entry)
209
- throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue is empty or the entry does not exist", 400);
308
+ throw new ServerPlayerError("ENTRY_NOT_FOUND", "Queue is empty or the entry does not exist", 404);
210
309
  const output = player.state.desired_output;
211
310
  if (!output)
212
311
  throw new ServerPlayerError("OUTPUT_REQUIRED", "Select a desired output before playing", 400);
@@ -215,7 +314,7 @@ export class ServerPlayerManager extends EventEmitter {
215
314
  throw new ServerPlayerError("OUTPUT_ASSIGNED", "Speaker belongs to another player; use explicit transfer");
216
315
  const needsReconnect = (player.state.status === "paused" || player.state.status === "error") && await this.runtimes.get(player.id)?.backend.outputConnection?.() !== "connected";
217
316
  if (player.assigned_output !== output || needsReconnect)
218
- await this.requireAvailable(output, policy);
317
+ await this.requireAvailable(player, output, policy);
219
318
  const track = await this.store.resolve(entry);
220
319
  const engine = this.engine(player);
221
320
  const source = track ? audioSource(track, { apiBase: "http://unused/api", audioLibraryRoot: engine.libraryRoot }) : null;
@@ -243,6 +342,23 @@ export class ServerPlayerManager extends EventEmitter {
243
342
  current.state.position = position;
244
343
  current.state.duration = duration !== null && Number.isFinite(duration) && duration >= 0 ? duration : null;
245
344
  current.state.checkpoint = false;
345
+ const entryId = current.state.current_entry_id;
346
+ if (this.playLogging && entryId && track?.friend_id === this.playLogging.ownerFriendId && track.release_id && !this.queuedPlays.has(entryId)) {
347
+ const listening = this.progress.get(entryId) ?? { listened: initialProgress, startedAt: this.playLogging.now?.() ?? new Date() };
348
+ listening.listened = advanceProgress(listening.listened, position, current.state.status === "playing");
349
+ this.progress.set(entryId, listening);
350
+ if (isPlay(listening.listened.listened, current.state.duration)) {
351
+ const play = { entryId, playerId: current.id, trackId: entry.track_id, friendId: entry.friend_id, releaseId: track.release_id, startedAt: listening.startedAt };
352
+ try {
353
+ await this.store.queuePlay(play);
354
+ this.queuedPlays.add(entryId);
355
+ void this.retryPlays();
356
+ }
357
+ catch (error) {
358
+ this.emit("play-log-error", error);
359
+ }
360
+ }
361
+ }
246
362
  this.players.set(current.id, current);
247
363
  this.emit("position", { player_id: current.id, revision: current.revision, current_entry_id: current.state.current_entry_id, position: current.state.position, duration: current.state.duration, observed_at: new Date().toISOString() });
248
364
  if (Date.now() - (this.checkpointAt.get(current.id) ?? 0) >= 5000) {
@@ -387,11 +503,27 @@ export class ServerPlayerManager extends EventEmitter {
387
503
  }
388
504
  });
389
505
  }
390
- async requireAvailable(output, policy) {
391
- const observed = await this.observe(output);
392
- if (observed.availability === "occupied" && !policy.takeover)
506
+ async requireAvailable(player, output, policy) {
507
+ // Assignment is a Groovenet claim, independent of HA's observation.
508
+ if (this.list().some(other => other.id !== player.id && other.assigned_output === output))
509
+ throw new ServerPlayerError("OUTPUT_ASSIGNED", "Speaker belongs to another player; use explicit transfer");
510
+ const observed = await this.observe(output, { fresh: true, resolveOutputName: async () => {
511
+ const runtime = this.runtimes.get(player.id);
512
+ const backend = runtime?.backend ?? this.engine(player).create();
513
+ try {
514
+ const devices = await backend.listDevices();
515
+ const name = devices.find(device => device.id === output)?.name;
516
+ return name && devices.filter(device => device.name === name).length === 1 ? name : undefined;
517
+ }
518
+ finally {
519
+ if (!runtime)
520
+ await backend.close();
521
+ }
522
+ } });
523
+ const ownSender = observed.sender_identity === "groovenet" && observed.sender_engine_id === player.engine_id;
524
+ if (observed.availability === "occupied" && !ownSender && !policy.takeover && player.availability_policy !== "always")
393
525
  throw new ServerPlayerError("SPEAKER_OCCUPIED", "Observed speaker activity requires explicit takeover");
394
- if (observed.availability === "unknown" && !policy.allow_unknown)
526
+ if (observed.availability === "unknown" && !policy.allow_unknown && player.availability_policy === "ask")
395
527
  throw new ServerPlayerError("AVAILABILITY_UNKNOWN", "Speaker availability is unknown; explicitly acknowledge it before connecting");
396
528
  }
397
529
  engine(player) {
@@ -1 +1 @@
1
- {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/server/manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,wBAAwB,EAAE,yBAAyB,EAA0J,MAAM,sBAAsB,CAAC;AACnP,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAwB,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,iBAAiB,EAAoB,MAAM,YAAY,CAAC;AAOjE,MAAM,CAAC,MAAM,cAAc,GAAG,GAAuB,EAAE,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC,CAAC;AAE7J,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,KAAK,YAAY,WAAW,IAAI,KAAK,YAAY,iBAAiB,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,yBAAyB,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;AACnO,MAAM,KAAK,GAAG,CAAI,KAAQ,EAAK,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC;AAEzD,qEAAqE;AACrE,MAAM,OAAO,mBAAoB,SAAQ,YAAY;IAQtB,KAAK;IAAgC,OAAO;IAAiD,OAAO;IAPzH,OAAO,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC1C,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAC;IACtC,UAAU,GAAG,CAAC,CAAC;IACf,IAAI,GAAqB,OAAO,CAAC,OAAO,EAAE,CAAC;IAC3C,QAAQ,GAAG,KAAK,CAAC;IACjB,YAAY,GAAG,IAAI,GAAG,EAAkB,CAAC;IAEjD,YAA6B,KAAkB,EAAmB,OAAqC,EAAmB,OAAO,GAAoB,KAAK,IAAI,EAAE,CAAC,cAAc,EAAE;QAAI,KAAK,EAAE,CAAC;qBAAhK,KAAK;uBAAgC,OAAO;uBAAiD,OAAO;IAA6D,CAAC;IAEvL,MAAM,CAAI,MAAwB;QACxC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QACnC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,KAAK,CAAC,UAAU;QACd,wEAAwE;QACxE,KAAK,MAAM,KAAK,IAAI,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;YAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;YAChC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,IAAI,CAAC;YAC/B,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7E,CAAC;IACH,CAAC;IAED,SAAS,KAAe,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAClE,IAAI,KAAqB,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACxE,GAAG,CAAC,EAAU;QACZ,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpC,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,uBAAuB,EAAE,GAAG,CAAC,CAAC;QAC3F,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IAED,MAAM,CAAC,KAAyB;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,MAAM,GAAG,wBAAwB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACrD,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC;gBAAE,MAAM,IAAI,iBAAiB,CAAC,uBAAuB,EAAE,yCAAyC,EAAE,GAAG,CAAC,CAAC;YAC1I,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,gBAAgB,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACxM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;YACrB,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC;QACjE,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,CAAC;YAC5C,OAAO,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,MAAM;gBACjE,kBAAkB,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,IAAI,IAAI;gBACxF,UAAU,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,cAAc,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC5F,QAAQ,EAAE,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;aACxC,CAAC,CAAC,CAAC,CAAC;QACP,CAAC;gBAAS,CAAC;YAAC,IAAI,CAAC,OAAO;gBAAE,MAAM,OAAO,CAAC,KAAK,EAAE,CAAC;QAAC,CAAC;IACpD,CAAC;IAED,OAAO,CAAC,EAAU,EAAE,KAA0B;QAC5C,OAAO,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC5B,IAAI,CAAC,SAAS,EAAE,CAAC;YACjB,MAAM,OAAO,GAAG,yBAAyB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YACvD,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC1B,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC;YACjD,IAAI,OAAO,CAAC,IAAI,KAAK,iBAAiB;gBAAE,OAAO,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9E,IAAI,CAAC;gBACH,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;oBACrB,KAAK,QAAQ;wBAAE,MAAM,CAAC,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;wBAAC,MAAM;oBACjD,KAAK,WAAW,EAAE,CAAC;wBACjB,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;wBACnD,IAAI,EAAE,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,GAAG,KAAK;4BAAE,MAAM,IAAI,iBAAiB,CAAC,eAAe,EAAE,iCAAiC,EAAE,GAAG,CAAC,CAAC;wBACtL,MAAM,KAAK,GAAG,EAAE,CAAC;wBACjB,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;4BACjC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;4BAC5C,IAAI,CAAC,KAAK;gCAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,6CAA6C,EAAE,GAAG,CAAC,CAAC;4BAC/G,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,GAAG,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;wBACrF,CAAC;wBACD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,EAAE,GAAG,KAAK,CAAC,CAAC;wBAC3C,MAAM;oBACR,CAAC;oBACD,KAAK,cAAc,EAAE,CAAC;wBACpB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;wBACrF,IAAI,KAAK,GAAG,CAAC;4BAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,4BAA4B,EAAE,GAAG,CAAC,CAAC;wBACjG,IAAI,OAAO,CAAC,QAAQ,KAAK,MAAM,CAAC,KAAK,CAAC,gBAAgB;4BAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAChF,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;wBACpC,MAAM;oBACR,CAAC;oBACD,KAAK,YAAY,EAAE,CAAC;wBAClB,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;wBACrF,IAAI,KAAK,GAAG,CAAC,IAAI,OAAO,CAAC,EAAE,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM;4BAAE,MAAM,IAAI,iBAAiB,CAAC,eAAe,EAAE,4BAA4B,EAAE,GAAG,CAAC,CAAC;wBAC1I,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAE,CAAC,CAAC;wBAClF,MAAM;oBACR,CAAC;oBACD,KAAK,aAAa;wBAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC;wBAAC,MAAM;oBAC5E,KAAK,eAAe;wBAClB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;4BAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;wBACzD,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;wBAChD,+DAA+D;wBAC/D,MAAM;oBACR,KAAK,MAAM,EAAE,CAAC;wBACZ,MAAM,OAAO,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;wBAC/F,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;wBAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;oBAC7E,CAAC;oBACD,KAAK,QAAQ;wBACX,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;4BAC1B,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAE,CAAC,OAAO,CAAC;4BAC/C,IAAI,MAAM,OAAO,CAAC,gBAAgB,EAAE,EAAE,KAAK,WAAW;gCAAE,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,CAAC,KAAK,CAAC,cAAe,EAAE,OAAO,CAAC,CAAC;4BAC3H,MAAM,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;4BAC3B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;4BAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;wBACnE,CAAC;6BAAM,CAAC;4BAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,gBAAgB,IAAI,SAAS,EAAE,OAAO,CAAC,CAAC;4BAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;wBAAC,CAAC;wBACzH,MAAM;oBACR,KAAK,OAAO;wBACV,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;wBAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC;wBAAC,MAAM;oBACnF,KAAK,MAAM;wBAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;wBAAC,MAAM;oBAC5C,KAAK,MAAM,CAAC;oBAAC,KAAK,UAAU,EAAE,CAAC;wBAC7B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;wBAClG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC;wBAC1E,IAAI,IAAI,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;4BAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;4BAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;wBAAC,CAAC;6BAC7F,CAAC;4BAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC;4BAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;wBAAC,CAAC;wBAChH,MAAM;oBACR,CAAC;oBACD,KAAK,MAAM;wBACT,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB;4BAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,kBAAkB,EAAE,GAAG,CAAC,CAAC;wBAC7G,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;4BAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;wBAC/E,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;wBAAC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;wBAAC,MAAM;oBACnG,KAAK,QAAQ;wBACX,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;4BAAE,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;wBACnF,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;wBAAC,MAAM;gBAChD,CAAC;gBACD,sEAAsE;gBACtE,yEAAyE;gBACzE,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO;oBAAE,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;gBAC/D,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBACjC,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;YACnC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,2EAA2E;gBAC3E,qEAAqE;gBACrE,IAAI,CAAC,CAAC,KAAK,YAAY,iBAAiB,CAAC,EAAE,CAAC;oBAC1C,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;oBACtB,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;oBAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;oBACvC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAC1B,CAAC;gBACD,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,MAAoB,EAAE,OAA2B,EAAE,MAAqD,EAAE,gBAAgB,GAAG,IAAI;QAClJ,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;QACvE,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,4CAA4C,EAAE,GAAG,CAAC,CAAC;QAC9G,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC;QAC3C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,wCAAwC,EAAE,GAAG,CAAC,CAAC;QAC3G,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,MAAM,IAAI,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC;QAC1F,IAAI,KAAK;YAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,0DAA0D,CAAC,CAAC;QACtH,MAAM,cAAc,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,KAAK,CAAC,MAAM,KAAK,OAAO,CAAC,IAAI,MAAM,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,gBAAgB,EAAE,EAAE,KAAK,WAAW,CAAC;QACjL,IAAI,MAAM,CAAC,eAAe,KAAK,MAAM,IAAI,cAAc;YAAE,MAAM,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACrG,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACnC,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACzH,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,iBAAiB,CAAC,UAAU,EAAE,2CAA2C,EAAE,GAAG,CAAC,CAAC;QACvG,MAAM,QAAQ,GAAG,gBAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5G,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,eAAe,GAAG,MAAM,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,KAAK,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAC7B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;QAChC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC;QAC1B,4EAA4E;QAC5E,4EAA4E;QAC5E,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,SAAS,EAAE,CAAC;QACjB,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,IAAI,CAAC,UAAU,EAAE,CAAC;QAC3D,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;QACtC,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACrG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC;gBAAE,OAAO;YACvD,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,CAAC;YAClC,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,QAAQ,KAAK,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;YAC3G,OAAO,CAAC,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC;YACjC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,gBAAgB,EAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,QAAQ,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YAC1O,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;gBAClE,MAAM,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;gBACrC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YAChD,CAAC;QACH,CAAC,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YAChF,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,KAAK,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;YACpG,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;YAC5C,IAAI,IAAI,EAAE,CAAC;gBACT,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC,EAAE,CAAC;gBACzC,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;gBAC3B,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;gBAC9B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;gBACjC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC1C,MAAM,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;YACtF,CAAC;iBAAM,CAAC;gBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAAC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;gBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAAC,CAAC;QAChG,CAAC,CAAC,CAAC,CAAC;QACJ,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE;YACrF,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;YAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YACxC,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,gCAAgC,CAAC,CAAC;YAC9E,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC3B,CAAC,CAAC,CAAC,CAAC;QACJ,IAAI,CAAC;YACH,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC3B,IAAI,QAAQ,GAAG,CAAC;gBAAE,MAAM,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YAC7C,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,SAAS,CAAC;YAChC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAC7B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;YAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;YACvC,IAAI,CAAC;gBAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YAAC,MAAM,CAAC,CAAC,uCAAuC,CAAC,CAAC;YACpF,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACxB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAEO,YAAY,CAAC,EAAU,EAAE,OAAgB,EAAE,MAA+C;QAChG,KAAK,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC1B,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,UAAU,KAAK,OAAO,CAAC,UAAU;gBAAE,OAAO;YACtF,IAAI,CAAC;gBAAC,MAAM,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;YAAC,CAAC;YACnC,OAAO,KAAK,EAAE,CAAC;gBACb,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBAC7B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;gBAC/B,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACxC,IAAI,CAAC;oBAAC,MAAM,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,8BAA8B,CAAC,CAAC;gBAC5E,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/D,CAAC;IAEO,KAAK,CAAC,MAAM,CAAC,MAAoB;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAC7C,IAAI,OAAO,EAAE,CAAC;YACZ,wEAAwE;YACxE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YAChC,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAChC,CAAC;aAAM,IAAI,MAAM,CAAC,eAAe,KAAK,IAAI,EAAE,CAAC;YAC3C,MAAM,IAAI,iBAAiB,CAAC,mBAAmB,EAAE,kGAAkG,EAAE,GAAG,CAAC,CAAC;QAC5J,CAAC;QACD,MAAM,CAAC,eAAe,GAAG,IAAI,CAAC;IAChC,CAAC;IAEO,KAAK,CAAC,IAAI,CAAC,MAAoB,EAAE,eAAe,GAAG,KAAK;QAC9D,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;QAC1B,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,eAAe,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9F,MAAM,CAAC,KAAK,CAAC,UAAU,GAAG,eAAe,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,KAAK,IAAI,CAAC;QACpF,IAAI,CAAC,eAAe,EAAE,CAAC;YAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB,GAAG,IAAI,CAAC;YAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,CAAC,CAAC;YAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,GAAG,IAAI,CAAC;QAAC,CAAC;IAC1H,CAAC;IAEO,KAAK,CAAC,QAAQ,CAAC,MAAoB,EAAE,OAAkE;QAC7G,IAAI,MAAM,CAAC,EAAE,KAAK,OAAO,CAAC,cAAc;YAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,yCAAyC,EAAE,GAAG,CAAC,CAAC;QAC1I,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC,CAAC;QAC9C,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;QAC7C,IAAI,MAAM,CAAC,eAAe,KAAK,OAAO,CAAC,SAAS;YAAE,MAAM,IAAI,iBAAiB,CAAC,qBAAqB,EAAE,yCAAyC,CAAC,CAAC;QAChJ,IAAI,QAAQ,GAAG,KAAK,CAAC;QACrB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YAC9B,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,QAAQ,GAAG,IAAI,CAAC;YAChB,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC;gBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;gBAAC,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAAC,CAAC;YACtG,MAAM,CAAC,KAAK,CAAC,cAAc,GAAG,OAAO,CAAC,SAAS,CAAC;YAChD,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACjC,IAAI,OAAO,CAAC,IAAI;gBAAE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,gBAAgB,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAC;YAC/G,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QACxI,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,OAAO,CAAC;gBAC9B,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;gBACvC,IAAI,CAAC;oBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAAC,CAAC;gBAAC,MAAM,CAAC,CAAC,uCAAuC,CAAC,CAAC;YACpF,CAAC;YACD,0EAA0E;YAC1E,0EAA0E;YAC1E,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QAC9I,CAAC;IACH,CAAC;IAED,KAAK,CAAC,QAAQ;QACZ,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,MAAM,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE;YAC3B,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBACjC,IAAI,CAAC;oBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;oBAAC,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gBAAC,CAAC;gBAC/D,OAAO,KAAK,EAAE,CAAC;oBAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;gBAAC,CAAC;YAC9C,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,KAAK,CAAC,gBAAgB,CAAC,MAAc,EAAE,MAAqD;QAClG,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,QAAQ,CAAC,YAAY,KAAK,UAAU,IAAI,CAAC,MAAM,CAAC,QAAQ;YAAE,MAAM,IAAI,iBAAiB,CAAC,kBAAkB,EAAE,sDAAsD,CAAC,CAAC;QACtK,IAAI,QAAQ,CAAC,YAAY,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,aAAa;YAAE,MAAM,IAAI,iBAAiB,CAAC,sBAAsB,EAAE,8EAA8E,CAAC,CAAC;IACxM,CAAC;IAEO,MAAM,CAAC,MAAoB;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,iBAAiB,CAAC,uBAAuB,EAAE,iCAAiC,EAAE,GAAG,CAAC,CAAC;QAC1G,OAAO,MAAM,CAAC;IAChB,CAAC;IACO,MAAM,CAAC,EAAU;QACvB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,mEAAmE,CAAC,CAAC;QAClI,OAAO,OAAO,CAAC;IACjB,CAAC;IACO,QAAQ,CAAC,MAAoB,EAAE,QAAgB;QACrD,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ;YAAE,MAAM,IAAI,iBAAiB,CAAC,mBAAmB,EAAE,mDAAmD,CAAC,CAAC;IAC1I,CAAC;IACO,SAAS,KAAW,IAAI,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,iBAAiB,CAAC,iBAAiB,EAAE,2BAA2B,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC;IAC1H,KAAK,CAAC,IAAI,CAAC,MAAoB;QACrC,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACpB,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACO,OAAO,CAAC,MAAoB,IAAU,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;CACtF"}
1
+ {"version":3,"file":"manager.js","sourceRoot":"","sources":["../../src/server/manager.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,10 @@
1
1
  import { type SpeakerObserver } from "./manager.js";
2
- /** Read-only observation. Neither a room state nor sender IP proves app identity. */
2
+ /** Exact attribute matches must identify one dedicated engine, never a shared host. */
3
3
  export declare function homeAssistantObserver(options: {
4
4
  url?: string;
5
5
  token?: string;
6
6
  entities?: Record<string, string>;
7
+ senders?: Record<string, Record<string, string>>;
7
8
  fetch?: typeof fetch;
8
9
  }): SpeakerObserver;
9
10
  //# sourceMappingURL=observer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../src/server/observer.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE,qFAAqF;AACrF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAAG,eAAe,CAsBzJ"}
1
+ {"version":3,"file":"observer.d.ts","sourceRoot":"","sources":["../../src/server/observer.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,KAAK,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpE,uFAAuF;AACvF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,KAAK,CAAA;CAAE,GAAG,eAAe,CAqC3M"}
@@ -1,28 +1,46 @@
1
1
  import { unknownSpeaker } from "./manager.js";
2
- /** Read-only observation. Neither a room state nor sender IP proves app identity. */
2
+ /** Exact attribute matches must identify one dedicated engine, never a shared host. */
3
3
  export function homeAssistantObserver(options) {
4
4
  const transport = options.fetch ?? globalThis.fetch;
5
5
  const cache = new Map();
6
- return async (outputId) => {
7
- const entity = options.entities?.[outputId];
6
+ return async (outputId, context) => {
7
+ const mappedEntity = (key) => options.entities && Object.hasOwn(options.entities, key) ? options.entities[key] : undefined;
8
+ let entity = mappedEntity(outputId);
9
+ if (!entity && Object.keys(options.entities ?? {}).length > 0) {
10
+ try {
11
+ const name = context?.outputName ?? await context?.resolveOutputName?.();
12
+ entity = name ? mappedEntity(name) : undefined;
13
+ }
14
+ catch { /* Discovery failure leaves the output unmapped. */ }
15
+ }
8
16
  if (!options.url || !options.token || !entity)
9
- return unknownSpeaker();
10
- const cached = cache.get(outputId);
11
- if (cached && cached.until > Date.now())
17
+ return { ...unknownSpeaker(), entity_id: entity ?? null };
18
+ const cached = cache.get(entity);
19
+ if (!context?.fresh && cached && cached.until > Date.now())
12
20
  return structuredClone(cached.value);
13
- let value = { availability: "unknown", observed_at: null, source: "home_assistant", sender_identity: "unknown" };
21
+ let value = { availability: "unknown", observed_at: null, source: "home_assistant", entity_id: entity, sender_identity: "unknown", sender_engine_id: null };
14
22
  try {
15
23
  const response = await transport(new URL(`api/states/${encodeURIComponent(entity)}`, options.url.endsWith("/") ? options.url : `${options.url}/`), { headers: { Authorization: `Bearer ${options.token}` }, signal: AbortSignal.timeout(2000), redirect: "error" });
16
24
  if (response.ok) {
17
25
  const body = await response.json();
18
26
  if (body && typeof body === "object" && "state" in body && typeof body.state === "string") {
19
27
  const state = body.state.toLowerCase();
28
+ const attributes = "attributes" in body && body.attributes && typeof body.attributes === "object" ? body.attributes : {};
29
+ const senders = Object.entries(options.senders ?? {});
30
+ const matches = senders.filter(([, expected]) => Object.keys(expected).length > 0 && Object.entries(expected).every(([key, expectedValue]) => Object.hasOwn(attributes, key) && attributes[key] === expectedValue));
31
+ // Idle/unavailable metadata can outlive a session. Never identify it.
32
+ if (["playing", "paused", "buffering"].includes(state)) {
33
+ if (matches.length === 1)
34
+ value = { ...value, sender_identity: "groovenet", sender_engine_id: matches[0][0] };
35
+ else if (matches.length === 0 && senders.some(([, expected]) => Object.keys(expected).some(key => typeof attributes[key] === "string" && attributes[key] !== "")))
36
+ value.sender_identity = "foreign";
37
+ }
20
38
  value = { ...value, availability: ["unknown", "unavailable"].includes(state) ? "unknown" : ["idle", "off", "standby"].includes(state) ? "idle" : "occupied", observed_at: new Date().toISOString() };
21
39
  }
22
40
  }
23
41
  }
24
42
  catch { /* Missing/stale observation is unknown, never free. */ }
25
- cache.set(outputId, { until: Date.now() + 5000, value });
43
+ cache.set(entity, { until: Date.now() + 5000, value });
26
44
  return structuredClone(value);
27
45
  };
28
46
  }
@@ -1 +1 @@
1
- {"version":3,"file":"observer.js","sourceRoot":"","sources":["../../src/server/observer.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAwB,MAAM,cAAc,CAAC;AAEpE,qFAAqF;AACrF,MAAM,UAAU,qBAAqB,CAAC,OAAkG;IACtI,MAAM,SAAS,GAAG,OAAO,CAAC,KAAK,IAAI,UAAU,CAAC,KAAK,CAAC;IACpD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwD,CAAC;IAC9E,OAAO,KAAK,EAAE,QAAQ,EAAE,EAAE;QACxB,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,CAAC,MAAM;YAAE,OAAO,cAAc,EAAE,CAAC;QACvE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACnC,IAAI,MAAM,IAAI,MAAM,CAAC,KAAK,GAAG,IAAI,CAAC,GAAG,EAAE;YAAE,OAAO,eAAe,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC9E,IAAI,KAAK,GAAuB,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;QACrI,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,SAAS,CAAC,IAAI,GAAG,CAAC,cAAc,kBAAkB,CAAC,MAAM,CAAC,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,GAAG,GAAG,CAAC,EAAE,EAAE,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,OAAO,CAAC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;YACpQ,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,IAAI,GAAY,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBAC5C,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;oBAC1F,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;oBACvC,KAAK,GAAG,EAAE,GAAG,KAAK,EAAE,YAAY,EAAE,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;gBACvM,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC,CAAC,uDAAuD,CAAC,CAAC;QACnE,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACzD,OAAO,eAAe,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"observer.js","sourceRoot":"","sources":["../../src/server/observer.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,9 @@
1
1
  import { ServerPlayerManager } from "./manager.js";
2
+ import type { ServerPlay } from "./store.js";
2
3
  import { PostgresPlayerStore } from "./store.js";
3
4
  import type { Server } from "node:http";
4
5
  import type { EventEmitter } from "node:events";
6
+ export declare function postServerPlay(appUrl: string, play: ServerPlay): Promise<void>;
5
7
  export declare function runPlayerWorker(env?: NodeJS.ProcessEnv, dependencies?: {
6
8
  store?: PostgresPlayerStore;
7
9
  manager?: ServerPlayerManager;
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAqB,MAAM,cAAc,CAAC;AACtE,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAIjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAsB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,YAAY,GAAE;IAAE,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,CAAA;CAAO;;;;oBAkB/K,OAAO,CAAC,IAAI,CAAC;GAqCnC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,mBAAmB,EAAqB,MAAM,cAAc,CAAC;AACtE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAIjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAsB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CASpF;AAED,wBAAsB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,EAAE,YAAY,GAAE;IAAE,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,YAAY,CAAA;CAAO;;;;oBAwB/K,OAAO,CAAC,IAAI,CAAC;GAwCnC"}
@@ -6,6 +6,18 @@ import { ServerPlayerManager } from "./manager.js";
6
6
  import { PostgresPlayerStore } from "./store.js";
7
7
  import { homeAssistantObserver } from "./observer.js";
8
8
  import { playerHttpServer } from "./http.js";
9
+ export async function postServerPlay(appUrl, play) {
10
+ const response = await fetch(new URL("/api/spins", appUrl), {
11
+ method: "POST", headers: { "Content-Type": "application/json" },
12
+ body: JSON.stringify({ friend_id: play.friendId, release_id: play.releaseId, medium: "digital", played_at: play.startedAt.toISOString(), context_type: "player", track_refs: [{ track_id: play.trackId, friend_id: play.friendId }] }),
13
+ signal: AbortSignal.timeout(5000),
14
+ });
15
+ if (response.ok)
16
+ return;
17
+ if (response.status === 409 && (await response.json()).error === "Digital play already logged")
18
+ return;
19
+ throw new Error(`Server play API returned ${response.status}`);
20
+ }
9
21
  export async function runPlayerWorker(env = process.env, dependencies = {}) {
10
22
  const connectionSchema = z.object({ apiUrl: z.url().refine((value) => { const url = new URL(value); return ["http:", "https:"].includes(url.protocol) && !url.username && !url.password && !url.search && !url.hash; }), libraryRoot: z.string().startsWith("/"), password: z.string().optional() }).strict();
11
23
  const configured = z.record(playerIdSchema, connectionSchema).parse(JSON.parse(env.PLAYER_ENGINES_JSON ?? "{}"));
@@ -19,20 +31,29 @@ export async function runPlayerWorker(env = process.env, dependencies = {}) {
19
31
  throw new Error("PLAYER_API_KEY must contain at least 32 characters");
20
32
  if (!env.DATABASE_URL)
21
33
  throw new Error("DATABASE_URL is required");
34
+ const ownerFriendId = z.coerce.number().int().positive().parse(env.PLAYER_LIBRARY_FRIEND_ID);
35
+ const appUrl = z.url().parse(env.PLAYER_APP_URL ?? "http://app:3000");
22
36
  const engines = Object.fromEntries(Object.entries(configured).map(([id, options]) => [id, { libraryRoot: options.libraryRoot, create: (outputId) => new OwnToneBackend({ apiUrl: options.apiUrl, password: options.password, outputId }) }]));
23
37
  const entities = z.record(z.string(), z.string().regex(/^[a-z_]+\.[a-z0-9_]+$/)).parse(JSON.parse(env.PLAYER_HA_ENTITIES_JSON ?? "{}"));
38
+ const senders = z.record(playerIdSchema, z.record(z.string().min(1), z.string().min(1)).refine(value => Object.keys(value).length > 0)).parse(JSON.parse(env.PLAYER_HA_SENDERS_JSON ?? "{}"));
39
+ for (const engineId of Object.keys(senders))
40
+ if (!configured[engineId])
41
+ throw new Error("HA sender must reference a configured engine");
24
42
  const store = dependencies.store ?? new PostgresPlayerStore(new Pool({ connectionString: env.DATABASE_URL, connectionTimeoutMillis: 5000, query_timeout: 5000, statement_timeout: 5000 }));
25
- const manager = dependencies.manager ?? new ServerPlayerManager(store, engines, homeAssistantObserver({ url: env.PLAYER_HA_URL, token: env.PLAYER_HA_TOKEN, entities }));
43
+ const logPlay = (play) => postServerPlay(appUrl, play);
44
+ const manager = dependencies.manager ?? new ServerPlayerManager(store, engines, homeAssistantObserver({ url: env.PLAYER_HA_URL, token: env.PLAYER_HA_TOKEN, entities, senders }), { ownerFriendId, logPlay });
26
45
  const server = dependencies.server ?? playerHttpServer(manager, key);
27
46
  const signals = dependencies.signals ?? process;
28
47
  let stopping = false;
29
48
  let shutdownPromise;
30
49
  let heartbeat;
50
+ let playRetry;
31
51
  function shutdown() {
32
52
  if (shutdownPromise)
33
53
  return shutdownPromise;
34
54
  stopping = true;
35
55
  clearInterval(heartbeat);
56
+ clearInterval(playRetry);
36
57
  signals.off("SIGINT", stop);
37
58
  signals.off("SIGTERM", stop);
38
59
  server.close();
@@ -63,6 +84,8 @@ export async function runPlayerWorker(env = process.env, dependencies = {}) {
63
84
  checking = true;
64
85
  void store.heartbeat().catch(failStop).finally(() => { checking = false; });
65
86
  }, 1000);
87
+ void manager.retryPlays();
88
+ playRetry = setInterval(() => { void manager.retryPlays(); }, 30_000);
66
89
  signals.once("SIGINT", stop);
67
90
  signals.once("SIGTERM", stop);
68
91
  const port = z.coerce.number().int().min(1).max(65535).parse(env.PLAYER_WORKER_PORT ?? "13700");
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../src/server/runtime.ts"],"names":[],"mappings":"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"}
@@ -6,12 +6,23 @@ export declare class ServerPlayerError extends Error {
6
6
  readonly status: number;
7
7
  constructor(code: string, message: string, status?: number);
8
8
  }
9
+ export interface ServerPlay {
10
+ entryId: string;
11
+ playerId: string;
12
+ trackId: string;
13
+ friendId: number;
14
+ releaseId: string;
15
+ startedAt: Date;
16
+ }
9
17
  export interface PlayerStore {
10
18
  list(): Promise<ServerPlayer[]>;
11
19
  create(input: CreateServerPlayer, state: ServerPlayerState): Promise<ServerPlayer>;
12
20
  save(player: ServerPlayer, expectedRevision: number): Promise<ServerPlayer>;
13
21
  checkpoint(player: ServerPlayer): Promise<void>;
14
22
  resolve(ref: PlayerTrackRef): Promise<Track | null>;
23
+ queuePlay(play: ServerPlay): Promise<void>;
24
+ pendingPlays(): Promise<ServerPlay[]>;
25
+ markPlayLogged(entryId: string): Promise<void>;
15
26
  }
16
27
  /** Only the elected worker writes this table; every command also uses CAS. */
17
28
  export declare class PostgresPlayerStore implements PlayerStore {
@@ -28,6 +39,9 @@ export declare class PostgresPlayerStore implements PlayerStore {
28
39
  save(player: ServerPlayer, expectedRevision: number): Promise<ServerPlayer>;
29
40
  checkpoint(player: ServerPlayer): Promise<void>;
30
41
  resolve(ref: PlayerTrackRef): Promise<Track | null>;
42
+ queuePlay(play: ServerPlay): Promise<void>;
43
+ pendingPlays(): Promise<ServerPlay[]>;
44
+ markPlayLogged(entryId: string): Promise<void>;
31
45
  private mapError;
32
46
  }
33
47
  //# sourceMappingURL=store.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACnJ,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAmB,QAAQ,CAAC,MAAM;IAAnE,YAAqB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAW,MAAM,SAAM,EAAqB;CAC/F;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnF,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5E,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;CACrD;AAED,8EAA8E;AAC9E,qBAAa,mBAAoB,YAAW,WAAW;IAGzC,QAAQ,CAAC,IAAI,EAAE,IAAI;IAF/B,OAAO,CAAC,KAAK,CAAC,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAC,CAAa;IAC5B,YAAqB,IAAI,EAAE,IAAI,EAAI;IAE7B,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/C;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAG/B;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB7B;IAED,OAAO,CAAC,GAAG;IAIL,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAGpC;IAEK,MAAM,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKvF;IAEK,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAMhF;IAEK,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpD;IAEK,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAIxD;IAED,OAAO,CAAC,QAAQ;CAIjB"}
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,IAAI,CAAC;AAC3C,OAAO,EAAsB,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACnJ,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE/C,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM;IAAmB,QAAQ,CAAC,MAAM;IAAnE,YAAqB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAW,MAAM,SAAM,EAAqB;CAC/F;AACD,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;CACjB;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAChC,MAAM,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACnF,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IAC5E,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;IACpD,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,YAAY,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACtC,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAChD;AAED,8EAA8E;AAC9E,qBAAa,mBAAoB,YAAW,WAAW;IAGzC,QAAQ,CAAC,IAAI,EAAE,IAAI;IAF/B,OAAO,CAAC,KAAK,CAAC,CAAa;IAC3B,OAAO,CAAC,MAAM,CAAC,CAAa;IAC5B,YAAqB,IAAI,EAAE,IAAI,EAAI;IAE7B,OAAO,CAAC,MAAM,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAW/C;IAEK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAG/B;IAEK,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAiB7B;IAED,OAAO,CAAC,GAAG;IAIL,IAAI,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAGpC;IAEK,MAAM,CAAC,KAAK,EAAE,kBAAkB,EAAE,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,YAAY,CAAC,CAKvF;IAEK,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAMhF;IAEK,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpD;IAEK,OAAO,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAIxD;IAEK,SAAS,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAI/C;IAEK,YAAY,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAI1C;IAEK,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAEnD;IAED,OAAO,CAAC,QAAQ;CAIjB"}
@@ -62,7 +62,7 @@ export class PostgresPlayerStore {
62
62
  }
63
63
  }
64
64
  row(row) {
65
- return serverPlayerSchema.parse({ id: row.id, name: row.name, engine_id: row.engine_id, revision: Number(row.revision), assigned_output: row.assigned_output, state: row.state });
65
+ return serverPlayerSchema.parse({ id: row.id, name: row.name, engine_id: row.engine_id, availability_policy: row.availability_policy, revision: Number(row.revision), assigned_output: row.assigned_output, state: row.state });
66
66
  }
67
67
  async list() {
68
68
  const result = await this.pool.query("SELECT * FROM server_players ORDER BY id");
@@ -79,7 +79,7 @@ export class PostgresPlayerStore {
79
79
  }
80
80
  async save(player, expectedRevision) {
81
81
  try {
82
- const result = await this.pool.query(`UPDATE server_players SET name=$2, assigned_output=$3, state=$4::jsonb, revision=revision+1, updated_at=now() WHERE id=$1 AND revision=$5 RETURNING *`, [player.id, player.name, player.assigned_output, JSON.stringify(player.state), expectedRevision]);
82
+ const result = await this.pool.query(`UPDATE server_players SET name=$2, assigned_output=$3, state=$4::jsonb, availability_policy=$5, revision=revision+1, updated_at=now() WHERE id=$1 AND revision=$6 RETURNING *`, [player.id, player.name, player.assigned_output, JSON.stringify(player.state), player.availability_policy, expectedRevision]);
83
83
  if (!result.rows[0])
84
84
  throw new ServerPlayerError("REVISION_CONFLICT", "Player changed; refresh its state before retrying");
85
85
  return this.row(result.rows[0]);
@@ -99,6 +99,18 @@ export class PostgresPlayerStore {
99
99
  return null;
100
100
  return result.rows[0];
101
101
  }
102
+ async queuePlay(play) {
103
+ await this.pool.query(`INSERT INTO server_player_plays (entry_id, player_id, track_id, friend_id, release_id, started_at)
104
+ VALUES ($1, $2, $3, $4, $5, $6) ON CONFLICT (entry_id) DO NOTHING`, [play.entryId, play.playerId, play.trackId, play.friendId, play.releaseId, play.startedAt]);
105
+ }
106
+ async pendingPlays() {
107
+ const result = await this.pool.query(`SELECT entry_id, player_id, track_id, friend_id, release_id, started_at
108
+ FROM server_player_plays WHERE logged_at IS NULL ORDER BY started_at`);
109
+ return result.rows.map(row => ({ entryId: row.entry_id, playerId: row.player_id, trackId: row.track_id, friendId: row.friend_id, releaseId: row.release_id, startedAt: new Date(row.started_at) }));
110
+ }
111
+ async markPlayLogged(entryId) {
112
+ await this.pool.query("UPDATE server_player_plays SET logged_at=now() WHERE entry_id=$1 AND logged_at IS NULL", [entryId]);
113
+ }
102
114
  mapError(error) {
103
115
  if (error && typeof error === "object" && "code" in error && error.code === "23505")
104
116
  return new ServerPlayerError("ASSIGNMENT_CONFLICT", "Player ID, engine, or speaker is already assigned");
@@ -1 +1 @@
1
- {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/server/store.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@groovenet/player",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Headless playback core and mpv backend for Groovenet",
5
5
  "type": "module",
6
6
  "engines": {
@@ -48,8 +48,8 @@
48
48
  "access": "public"
49
49
  },
50
50
  "dependencies": {
51
- "@groovenet/client": "^3.5.0",
52
- "@groovenet/contracts": "1.2.0",
51
+ "@groovenet/client": "^3.6.0",
52
+ "@groovenet/contracts": "1.3.0",
53
53
  "pg": "8.23.1",
54
54
  "zod": "4.6.7"
55
55
  },