@rocksky/sdk 0.1.0
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/LICENSE +21 -0
- package/README.md +279 -0
- package/dist/client.d.ts +107 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/http.d.ts +28 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1492 -0
- package/dist/namespaces/_helpers.d.ts +9 -0
- package/dist/namespaces/_helpers.d.ts.map +1 -0
- package/dist/namespaces/actor.d.ts +30 -0
- package/dist/namespaces/actor.d.ts.map +1 -0
- package/dist/namespaces/album.d.ts +18 -0
- package/dist/namespaces/album.d.ts.map +1 -0
- package/dist/namespaces/apikey.d.ts +27 -0
- package/dist/namespaces/apikey.d.ts.map +1 -0
- package/dist/namespaces/artist.d.ts +31 -0
- package/dist/namespaces/artist.d.ts.map +1 -0
- package/dist/namespaces/charts.d.ts +25 -0
- package/dist/namespaces/charts.d.ts.map +1 -0
- package/dist/namespaces/dropbox.d.ts +19 -0
- package/dist/namespaces/dropbox.d.ts.map +1 -0
- package/dist/namespaces/feed.d.ts +38 -0
- package/dist/namespaces/feed.d.ts.map +1 -0
- package/dist/namespaces/googledrive.d.ts +16 -0
- package/dist/namespaces/googledrive.d.ts.map +1 -0
- package/dist/namespaces/graph.d.ts +28 -0
- package/dist/namespaces/graph.d.ts.map +1 -0
- package/dist/namespaces/like.d.ts +14 -0
- package/dist/namespaces/like.d.ts.map +1 -0
- package/dist/namespaces/mirror.d.ts +15 -0
- package/dist/namespaces/mirror.d.ts.map +1 -0
- package/dist/namespaces/player.d.ts +41 -0
- package/dist/namespaces/player.d.ts.map +1 -0
- package/dist/namespaces/playlist.d.ts +40 -0
- package/dist/namespaces/playlist.d.ts.map +1 -0
- package/dist/namespaces/scrobble.d.ts +43 -0
- package/dist/namespaces/scrobble.d.ts.map +1 -0
- package/dist/namespaces/shout.d.ts +38 -0
- package/dist/namespaces/shout.d.ts.map +1 -0
- package/dist/namespaces/song.d.ts +48 -0
- package/dist/namespaces/song.d.ts.map +1 -0
- package/dist/namespaces/spotify.d.ts +17 -0
- package/dist/namespaces/spotify.d.ts.map +1 -0
- package/dist/namespaces/stats.d.ts +14 -0
- package/dist/namespaces/stats.d.ts.map +1 -0
- package/dist/paginate.d.ts +38 -0
- package/dist/paginate.d.ts.map +1 -0
- package/dist/pipe.d.ts +36 -0
- package/dist/pipe.d.ts.map +1 -0
- package/dist/realtime.d.ts +144 -0
- package/dist/realtime.d.ts.map +1 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +65 -0
- package/src/client.ts +235 -0
- package/src/errors.ts +47 -0
- package/src/http.ts +195 -0
- package/src/index.ts +85 -0
- package/src/namespaces/_helpers.ts +17 -0
- package/src/namespaces/actor.ts +89 -0
- package/src/namespaces/album.ts +34 -0
- package/src/namespaces/apikey.ts +50 -0
- package/src/namespaces/artist.ts +74 -0
- package/src/namespaces/charts.ts +47 -0
- package/src/namespaces/dropbox.ts +47 -0
- package/src/namespaces/feed.ts +106 -0
- package/src/namespaces/googledrive.ts +36 -0
- package/src/namespaces/graph.ts +63 -0
- package/src/namespaces/like.ts +40 -0
- package/src/namespaces/mirror.ts +31 -0
- package/src/namespaces/player.ts +127 -0
- package/src/namespaces/playlist.ts +85 -0
- package/src/namespaces/scrobble.ts +67 -0
- package/src/namespaces/shout.ts +90 -0
- package/src/namespaces/song.ts +81 -0
- package/src/namespaces/spotify.ts +52 -0
- package/src/namespaces/stats.ts +23 -0
- package/src/paginate.ts +90 -0
- package/src/pipe.ts +146 -0
- package/src/realtime.ts +408 -0
- package/src/types.ts +41 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,1492 @@
|
|
|
1
|
+
// src/errors.ts
|
|
2
|
+
class RockskyError extends Error {
|
|
3
|
+
cause;
|
|
4
|
+
constructor(message, options) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.name = "RockskyError";
|
|
7
|
+
this.cause = options?.cause;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
class RockskyHttpError extends RockskyError {
|
|
12
|
+
status;
|
|
13
|
+
statusText;
|
|
14
|
+
url;
|
|
15
|
+
body;
|
|
16
|
+
constructor(args) {
|
|
17
|
+
const message = args.message ?? `Rocksky API ${args.status} ${args.statusText} at ${args.url}`;
|
|
18
|
+
super(message);
|
|
19
|
+
this.name = "RockskyHttpError";
|
|
20
|
+
this.status = args.status;
|
|
21
|
+
this.statusText = args.statusText;
|
|
22
|
+
this.url = args.url;
|
|
23
|
+
this.body = args.body;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
class RockskyTimeoutError extends RockskyError {
|
|
28
|
+
constructor(ms) {
|
|
29
|
+
super(`Rocksky request timed out after ${ms}ms`);
|
|
30
|
+
this.name = "RockskyTimeoutError";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
class RockskyAuthError extends RockskyError {
|
|
35
|
+
constructor(message = "Authentication required") {
|
|
36
|
+
super(message);
|
|
37
|
+
this.name = "RockskyAuthError";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// src/types.ts
|
|
42
|
+
var DEFAULT_BASE_URL = "https://api.rocksky.app";
|
|
43
|
+
|
|
44
|
+
// src/http.ts
|
|
45
|
+
function buildConfig(opts) {
|
|
46
|
+
const headers = {
|
|
47
|
+
accept: "application/json",
|
|
48
|
+
...opts.userAgent ? { "user-agent": opts.userAgent } : {},
|
|
49
|
+
...opts.headers ?? {}
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
baseUrl: stripTrailingSlash(opts.baseUrl ?? DEFAULT_BASE_URL),
|
|
53
|
+
auth: opts.auth,
|
|
54
|
+
fetch: opts.fetch ?? globalThis.fetch.bind(globalThis),
|
|
55
|
+
headers,
|
|
56
|
+
timeoutMs: opts.timeoutMs ?? 30000,
|
|
57
|
+
retries: opts.retries ?? 0,
|
|
58
|
+
retryDelayMs: opts.retryDelayMs ?? 300
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function stripTrailingSlash(url) {
|
|
62
|
+
return url.endsWith("/") ? url.slice(0, -1) : url;
|
|
63
|
+
}
|
|
64
|
+
async function resolveAuth(provider) {
|
|
65
|
+
if (provider == null)
|
|
66
|
+
return;
|
|
67
|
+
if (typeof provider === "string")
|
|
68
|
+
return provider;
|
|
69
|
+
return await provider();
|
|
70
|
+
}
|
|
71
|
+
function serializeParams(params) {
|
|
72
|
+
if (!params)
|
|
73
|
+
return "";
|
|
74
|
+
const usp = new URLSearchParams;
|
|
75
|
+
for (const [k, v] of Object.entries(params)) {
|
|
76
|
+
if (v == null)
|
|
77
|
+
continue;
|
|
78
|
+
if (Array.isArray(v)) {
|
|
79
|
+
for (const item of v) {
|
|
80
|
+
if (item == null)
|
|
81
|
+
continue;
|
|
82
|
+
usp.append(k, String(item));
|
|
83
|
+
}
|
|
84
|
+
} else if (typeof v === "boolean") {
|
|
85
|
+
usp.append(k, v ? "true" : "false");
|
|
86
|
+
} else {
|
|
87
|
+
usp.append(k, String(v));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const s = usp.toString();
|
|
91
|
+
return s ? `?${s}` : "";
|
|
92
|
+
}
|
|
93
|
+
async function xrpcCall(config, nsid, method, opts = {}) {
|
|
94
|
+
const url = `${config.baseUrl}/xrpc/${nsid}` + serializeParams(opts.params);
|
|
95
|
+
const timeoutMs = opts.timeoutMs ?? config.timeoutMs;
|
|
96
|
+
const retries = opts.retries ?? config.retries;
|
|
97
|
+
const headers = {
|
|
98
|
+
...config.headers,
|
|
99
|
+
...opts.headers ?? {}
|
|
100
|
+
};
|
|
101
|
+
const authProvider = opts.auth === undefined ? config.auth : opts.auth;
|
|
102
|
+
const token = await resolveAuth(authProvider);
|
|
103
|
+
if (token) {
|
|
104
|
+
headers.authorization = `Bearer ${token}`;
|
|
105
|
+
} else if (opts.requireAuth) {
|
|
106
|
+
throw new RockskyAuthError(`${nsid} requires authentication — provide an "auth" token`);
|
|
107
|
+
}
|
|
108
|
+
const init = {
|
|
109
|
+
method,
|
|
110
|
+
headers,
|
|
111
|
+
signal: opts.signal
|
|
112
|
+
};
|
|
113
|
+
if (method === "POST" && opts.body !== undefined) {
|
|
114
|
+
headers["content-type"] = "application/json";
|
|
115
|
+
init.body = JSON.stringify(opts.body);
|
|
116
|
+
}
|
|
117
|
+
let lastErr;
|
|
118
|
+
for (let attempt = 0;attempt <= retries; attempt++) {
|
|
119
|
+
try {
|
|
120
|
+
return await runOnce(config.fetch, url, init, timeoutMs);
|
|
121
|
+
} catch (err) {
|
|
122
|
+
lastErr = err;
|
|
123
|
+
if (!isRetryable(err) || attempt === retries)
|
|
124
|
+
throw err;
|
|
125
|
+
await sleep(config.retryDelayMs * Math.pow(2, attempt));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
throw lastErr;
|
|
129
|
+
}
|
|
130
|
+
async function runOnce(fetchImpl, url, init, timeoutMs) {
|
|
131
|
+
const controller = new AbortController;
|
|
132
|
+
const upstream = init.signal;
|
|
133
|
+
const onAbort = () => controller.abort(upstream?.reason);
|
|
134
|
+
upstream?.addEventListener("abort", onAbort, { once: true });
|
|
135
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
136
|
+
try {
|
|
137
|
+
const res = await fetchImpl(url, { ...init, signal: controller.signal });
|
|
138
|
+
const text = await res.text();
|
|
139
|
+
const body = parseMaybeJson(text);
|
|
140
|
+
if (!res.ok) {
|
|
141
|
+
throw new RockskyHttpError({
|
|
142
|
+
status: res.status,
|
|
143
|
+
statusText: res.statusText,
|
|
144
|
+
url,
|
|
145
|
+
body
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
return body;
|
|
149
|
+
} catch (err) {
|
|
150
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
151
|
+
if (upstream?.aborted)
|
|
152
|
+
throw err;
|
|
153
|
+
throw new RockskyTimeoutError(timeoutMs);
|
|
154
|
+
}
|
|
155
|
+
throw err;
|
|
156
|
+
} finally {
|
|
157
|
+
clearTimeout(timer);
|
|
158
|
+
upstream?.removeEventListener("abort", onAbort);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
function parseMaybeJson(text) {
|
|
162
|
+
if (!text)
|
|
163
|
+
return null;
|
|
164
|
+
try {
|
|
165
|
+
return JSON.parse(text);
|
|
166
|
+
} catch {
|
|
167
|
+
return text;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
function isRetryable(err) {
|
|
171
|
+
if (err instanceof RockskyTimeoutError)
|
|
172
|
+
return true;
|
|
173
|
+
if (err instanceof RockskyHttpError) {
|
|
174
|
+
return err.status >= 500 || err.status === 429;
|
|
175
|
+
}
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
function sleep(ms) {
|
|
179
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// src/paginate.ts
|
|
183
|
+
function paginate(args) {
|
|
184
|
+
const pageSize = args.pageSize ?? 50;
|
|
185
|
+
const maxItems = args.maxItems ?? Number.POSITIVE_INFINITY;
|
|
186
|
+
async function* iter() {
|
|
187
|
+
let offset = 0;
|
|
188
|
+
let cursor;
|
|
189
|
+
let yielded = 0;
|
|
190
|
+
while (yielded < maxItems) {
|
|
191
|
+
checkAbort(args.signal);
|
|
192
|
+
const result = await args.fetch({ limit: pageSize, offset, cursor });
|
|
193
|
+
checkAbort(args.signal);
|
|
194
|
+
const { items, nextCursor } = normalize(result);
|
|
195
|
+
if (items.length === 0)
|
|
196
|
+
return;
|
|
197
|
+
for (const item of items) {
|
|
198
|
+
if (yielded >= maxItems)
|
|
199
|
+
return;
|
|
200
|
+
yield item;
|
|
201
|
+
yielded++;
|
|
202
|
+
}
|
|
203
|
+
offset += items.length;
|
|
204
|
+
if (nextCursor !== undefined) {
|
|
205
|
+
if (nextCursor === cursor || nextCursor === null)
|
|
206
|
+
return;
|
|
207
|
+
cursor = nextCursor ?? undefined;
|
|
208
|
+
} else if (items.length < pageSize) {
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
const iterable = { [Symbol.asyncIterator]: iter };
|
|
214
|
+
return Object.assign(iterable, {
|
|
215
|
+
async toArray() {
|
|
216
|
+
const out = [];
|
|
217
|
+
for await (const item of iter())
|
|
218
|
+
out.push(item);
|
|
219
|
+
return out;
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
function normalize(result) {
|
|
224
|
+
if (Array.isArray(result))
|
|
225
|
+
return { items: result };
|
|
226
|
+
return { items: result.items, nextCursor: result.cursor ?? null };
|
|
227
|
+
}
|
|
228
|
+
function checkAbort(signal) {
|
|
229
|
+
if (signal?.aborted) {
|
|
230
|
+
throw signal.reason ?? new DOMException("aborted", "AbortError");
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// src/realtime.ts
|
|
235
|
+
var RECONNECT_DEFAULTS = {
|
|
236
|
+
backoffMs: 500,
|
|
237
|
+
maxBackoffMs: 30000,
|
|
238
|
+
maxAttempts: Number.POSITIVE_INFINITY,
|
|
239
|
+
factor: 2
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
class RealtimeClient {
|
|
243
|
+
options;
|
|
244
|
+
ws;
|
|
245
|
+
listeners = new Map;
|
|
246
|
+
reconnectAttempts = 0;
|
|
247
|
+
pingTimer;
|
|
248
|
+
closed = false;
|
|
249
|
+
deviceId;
|
|
250
|
+
url;
|
|
251
|
+
reconnectOpts;
|
|
252
|
+
WsCtor;
|
|
253
|
+
constructor(options) {
|
|
254
|
+
this.options = options;
|
|
255
|
+
this.url = options.url ?? deriveWsUrl(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
256
|
+
this.reconnectOpts = options.reconnect === false ? null : {
|
|
257
|
+
...RECONNECT_DEFAULTS,
|
|
258
|
+
...typeof options.reconnect === "object" ? options.reconnect : {}
|
|
259
|
+
};
|
|
260
|
+
const ctor = options.webSocket ?? globalThis.WebSocket;
|
|
261
|
+
if (!ctor) {
|
|
262
|
+
throw new RockskyError("No WebSocket implementation available — pass `webSocket` in options");
|
|
263
|
+
}
|
|
264
|
+
this.WsCtor = ctor;
|
|
265
|
+
}
|
|
266
|
+
get currentDeviceId() {
|
|
267
|
+
return this.deviceId;
|
|
268
|
+
}
|
|
269
|
+
get isOpen() {
|
|
270
|
+
return this.ws?.readyState === 1;
|
|
271
|
+
}
|
|
272
|
+
on(event, listener) {
|
|
273
|
+
const set = this.listeners.get(event) ?? new Set;
|
|
274
|
+
set.add(listener);
|
|
275
|
+
this.listeners.set(event, set);
|
|
276
|
+
return () => this.off(event, listener);
|
|
277
|
+
}
|
|
278
|
+
off(event, listener) {
|
|
279
|
+
this.listeners.get(event)?.delete(listener);
|
|
280
|
+
}
|
|
281
|
+
emit(event, payload) {
|
|
282
|
+
const set = this.listeners.get(event);
|
|
283
|
+
if (!set)
|
|
284
|
+
return;
|
|
285
|
+
for (const fn of set) {
|
|
286
|
+
try {
|
|
287
|
+
fn(payload);
|
|
288
|
+
} catch (err) {
|
|
289
|
+
const errSet = this.listeners.get("error");
|
|
290
|
+
errSet?.forEach((f) => f(err));
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
async connect() {
|
|
295
|
+
this.closed = false;
|
|
296
|
+
const ws = new this.WsCtor(this.url);
|
|
297
|
+
this.ws = ws;
|
|
298
|
+
await new Promise((resolve, reject) => {
|
|
299
|
+
const onOpen = () => {
|
|
300
|
+
ws.removeEventListener("open", onOpen);
|
|
301
|
+
ws.removeEventListener("error", onError);
|
|
302
|
+
resolve();
|
|
303
|
+
};
|
|
304
|
+
const onError = (err) => {
|
|
305
|
+
ws.removeEventListener("open", onOpen);
|
|
306
|
+
ws.removeEventListener("error", onError);
|
|
307
|
+
reject(err);
|
|
308
|
+
};
|
|
309
|
+
ws.addEventListener("open", onOpen);
|
|
310
|
+
ws.addEventListener("error", onError);
|
|
311
|
+
});
|
|
312
|
+
this.attachHandlers(ws);
|
|
313
|
+
this.reconnectAttempts = 0;
|
|
314
|
+
this.emit("open", undefined);
|
|
315
|
+
if (this.options.autoRegister !== false) {
|
|
316
|
+
await this.register();
|
|
317
|
+
}
|
|
318
|
+
this.startPing();
|
|
319
|
+
}
|
|
320
|
+
async register() {
|
|
321
|
+
const token = await resolveToken(this.options.token);
|
|
322
|
+
this.sendRaw({
|
|
323
|
+
type: "register",
|
|
324
|
+
clientName: this.options.clientName ?? "rocksky-sdk",
|
|
325
|
+
token
|
|
326
|
+
});
|
|
327
|
+
}
|
|
328
|
+
async sendMessage(data) {
|
|
329
|
+
if (!this.deviceId) {
|
|
330
|
+
throw new RockskyError("Cannot send message — device not registered yet (await connect() first)");
|
|
331
|
+
}
|
|
332
|
+
const token = await resolveToken(this.options.token);
|
|
333
|
+
this.sendRaw({
|
|
334
|
+
type: "message",
|
|
335
|
+
data,
|
|
336
|
+
device_id: this.deviceId,
|
|
337
|
+
token
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
async sendControl(args) {
|
|
341
|
+
const token = await resolveToken(this.options.token);
|
|
342
|
+
this.sendRaw({
|
|
343
|
+
type: args.type ?? "control",
|
|
344
|
+
target: args.target,
|
|
345
|
+
action: args.action,
|
|
346
|
+
args: args.args,
|
|
347
|
+
token
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
ping() {
|
|
351
|
+
if (this.ws?.readyState === 1)
|
|
352
|
+
this.ws.send("ping");
|
|
353
|
+
}
|
|
354
|
+
sendRaw(payload) {
|
|
355
|
+
if (this.ws?.readyState !== 1) {
|
|
356
|
+
throw new RockskyError("WebSocket is not open");
|
|
357
|
+
}
|
|
358
|
+
this.ws.send(typeof payload === "string" ? payload : JSON.stringify(payload));
|
|
359
|
+
}
|
|
360
|
+
async close(code = 1000, reason = "client closing") {
|
|
361
|
+
this.closed = true;
|
|
362
|
+
this.stopPing();
|
|
363
|
+
this.ws?.close(code, reason);
|
|
364
|
+
}
|
|
365
|
+
attachHandlers(ws) {
|
|
366
|
+
ws.addEventListener("message", (event) => {
|
|
367
|
+
const raw = event.data;
|
|
368
|
+
if (raw === "pong")
|
|
369
|
+
return;
|
|
370
|
+
let parsed;
|
|
371
|
+
try {
|
|
372
|
+
parsed = typeof raw === "string" ? JSON.parse(raw) : raw;
|
|
373
|
+
} catch {
|
|
374
|
+
this.emit("raw", raw);
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
this.emit("raw", parsed);
|
|
378
|
+
this.dispatch(parsed);
|
|
379
|
+
});
|
|
380
|
+
ws.addEventListener("close", (event) => {
|
|
381
|
+
this.stopPing();
|
|
382
|
+
this.emit("close", event);
|
|
383
|
+
if (!this.closed && this.reconnectOpts)
|
|
384
|
+
this.scheduleReconnect();
|
|
385
|
+
});
|
|
386
|
+
ws.addEventListener("error", (err) => {
|
|
387
|
+
this.emit("error", err);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
dispatch(msg) {
|
|
391
|
+
if (!msg || typeof msg !== "object")
|
|
392
|
+
return;
|
|
393
|
+
const m = msg;
|
|
394
|
+
if (m.status === "registered" && typeof m.deviceId === "string") {
|
|
395
|
+
this.deviceId = m.deviceId;
|
|
396
|
+
this.emit("registered", { deviceId: m.deviceId });
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
399
|
+
if (m.type === "device_registered" && typeof m.deviceId === "string") {
|
|
400
|
+
this.emit("deviceRegistered", {
|
|
401
|
+
deviceId: m.deviceId,
|
|
402
|
+
clientName: String(m.clientName ?? "")
|
|
403
|
+
});
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
if (m.type === "message" && typeof m.device_id === "string") {
|
|
407
|
+
this.emit("message", {
|
|
408
|
+
data: m.data,
|
|
409
|
+
device_id: m.device_id
|
|
410
|
+
});
|
|
411
|
+
return;
|
|
412
|
+
}
|
|
413
|
+
if (typeof m.action === "string") {
|
|
414
|
+
this.emit("control", {
|
|
415
|
+
type: String(m.type ?? "control"),
|
|
416
|
+
action: m.action,
|
|
417
|
+
args: m.args
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
scheduleReconnect() {
|
|
422
|
+
if (!this.reconnectOpts)
|
|
423
|
+
return;
|
|
424
|
+
if (this.reconnectAttempts >= this.reconnectOpts.maxAttempts)
|
|
425
|
+
return;
|
|
426
|
+
const delay = Math.min(this.reconnectOpts.backoffMs * Math.pow(this.reconnectOpts.factor, this.reconnectAttempts), this.reconnectOpts.maxBackoffMs);
|
|
427
|
+
this.reconnectAttempts++;
|
|
428
|
+
setTimeout(() => {
|
|
429
|
+
if (this.closed)
|
|
430
|
+
return;
|
|
431
|
+
this.connect().catch((err) => this.emit("error", err));
|
|
432
|
+
}, delay);
|
|
433
|
+
}
|
|
434
|
+
startPing() {
|
|
435
|
+
const ms = this.options.pingIntervalMs ?? 25000;
|
|
436
|
+
if (ms <= 0)
|
|
437
|
+
return;
|
|
438
|
+
this.pingTimer = setInterval(() => this.ping(), ms);
|
|
439
|
+
}
|
|
440
|
+
stopPing() {
|
|
441
|
+
if (this.pingTimer) {
|
|
442
|
+
clearInterval(this.pingTimer);
|
|
443
|
+
this.pingTimer = undefined;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
function createRealtimeClient(opts) {
|
|
448
|
+
return new RealtimeClient(opts);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
class RealtimeClientBuilder {
|
|
452
|
+
opts = {};
|
|
453
|
+
url(u) {
|
|
454
|
+
this.opts.url = u;
|
|
455
|
+
return this;
|
|
456
|
+
}
|
|
457
|
+
baseUrl(u) {
|
|
458
|
+
this.opts.baseUrl = u;
|
|
459
|
+
return this;
|
|
460
|
+
}
|
|
461
|
+
token(t) {
|
|
462
|
+
this.opts.token = t;
|
|
463
|
+
return this;
|
|
464
|
+
}
|
|
465
|
+
clientName(name) {
|
|
466
|
+
this.opts.clientName = name;
|
|
467
|
+
return this;
|
|
468
|
+
}
|
|
469
|
+
autoRegister(value) {
|
|
470
|
+
this.opts.autoRegister = value;
|
|
471
|
+
return this;
|
|
472
|
+
}
|
|
473
|
+
reconnect(value) {
|
|
474
|
+
this.opts.reconnect = value;
|
|
475
|
+
return this;
|
|
476
|
+
}
|
|
477
|
+
pingInterval(ms) {
|
|
478
|
+
this.opts.pingIntervalMs = ms;
|
|
479
|
+
return this;
|
|
480
|
+
}
|
|
481
|
+
webSocket(ctor) {
|
|
482
|
+
this.opts.webSocket = ctor;
|
|
483
|
+
return this;
|
|
484
|
+
}
|
|
485
|
+
build() {
|
|
486
|
+
if (!this.opts.token) {
|
|
487
|
+
throw new RockskyError("RealtimeClientBuilder: token() is required before build()");
|
|
488
|
+
}
|
|
489
|
+
return new RealtimeClient(this.opts);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
((RealtimeClient) => {
|
|
493
|
+
function builder() {
|
|
494
|
+
return new RealtimeClientBuilder;
|
|
495
|
+
}
|
|
496
|
+
RealtimeClient.builder = builder;
|
|
497
|
+
})(RealtimeClient ||= {});
|
|
498
|
+
function deriveWsUrl(httpBase) {
|
|
499
|
+
const u = new URL(httpBase);
|
|
500
|
+
u.protocol = u.protocol === "https:" ? "wss:" : "ws:";
|
|
501
|
+
u.pathname = u.pathname.replace(/\/$/, "") + "/ws";
|
|
502
|
+
return u.toString();
|
|
503
|
+
}
|
|
504
|
+
async function resolveToken(source) {
|
|
505
|
+
return typeof source === "function" ? await source() : source;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
// src/namespaces/actor.ts
|
|
509
|
+
class ActorNamespace {
|
|
510
|
+
call;
|
|
511
|
+
constructor(call) {
|
|
512
|
+
this.call = call;
|
|
513
|
+
}
|
|
514
|
+
getProfile(params = {}, opts) {
|
|
515
|
+
return this.call("app.rocksky.actor.getProfile", "GET", {
|
|
516
|
+
params,
|
|
517
|
+
...opts
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
getActorAlbums(params, opts) {
|
|
521
|
+
return this.call("app.rocksky.actor.getActorAlbums", "GET", {
|
|
522
|
+
params,
|
|
523
|
+
...opts
|
|
524
|
+
});
|
|
525
|
+
}
|
|
526
|
+
getActorArtists(params, opts) {
|
|
527
|
+
return this.call("app.rocksky.actor.getActorArtists", "GET", {
|
|
528
|
+
params,
|
|
529
|
+
...opts
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
getActorSongs(params, opts) {
|
|
533
|
+
return this.call("app.rocksky.actor.getActorSongs", "GET", {
|
|
534
|
+
params,
|
|
535
|
+
...opts
|
|
536
|
+
});
|
|
537
|
+
}
|
|
538
|
+
getActorScrobbles(params, opts) {
|
|
539
|
+
return this.call("app.rocksky.actor.getActorScrobbles", "GET", {
|
|
540
|
+
params,
|
|
541
|
+
...opts
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
getActorLovedSongs(params, opts) {
|
|
545
|
+
return this.call("app.rocksky.actor.getActorLovedSongs", "GET", {
|
|
546
|
+
params,
|
|
547
|
+
...opts
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
getActorPlaylists(params, opts) {
|
|
551
|
+
return this.call("app.rocksky.actor.getActorPlaylists", "GET", {
|
|
552
|
+
params,
|
|
553
|
+
...opts
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
getActorNeighbours(params, opts) {
|
|
557
|
+
return this.call("app.rocksky.actor.getActorNeighbours", "GET", {
|
|
558
|
+
params,
|
|
559
|
+
...opts
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
getActorCompatibility(params, opts) {
|
|
563
|
+
return this.call("app.rocksky.actor.getActorCompatibility", "GET", {
|
|
564
|
+
params,
|
|
565
|
+
...opts
|
|
566
|
+
});
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
// src/namespaces/album.ts
|
|
571
|
+
class AlbumNamespace {
|
|
572
|
+
call;
|
|
573
|
+
constructor(call) {
|
|
574
|
+
this.call = call;
|
|
575
|
+
}
|
|
576
|
+
getAlbum(params, opts) {
|
|
577
|
+
return this.call("app.rocksky.album.getAlbum", "GET", {
|
|
578
|
+
params,
|
|
579
|
+
...opts
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
getAlbums(params = {}, opts) {
|
|
583
|
+
return this.call("app.rocksky.album.getAlbums", "GET", {
|
|
584
|
+
params,
|
|
585
|
+
...opts
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
getAlbumTracks(params, opts) {
|
|
589
|
+
return this.call("app.rocksky.album.getAlbumTracks", "GET", {
|
|
590
|
+
params,
|
|
591
|
+
...opts
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// src/namespaces/apikey.ts
|
|
597
|
+
class ApikeyNamespace {
|
|
598
|
+
call;
|
|
599
|
+
constructor(call) {
|
|
600
|
+
this.call = call;
|
|
601
|
+
}
|
|
602
|
+
getApikeys(params = {}, opts) {
|
|
603
|
+
return this.call("app.rocksky.apikey.getApikeys", "GET", {
|
|
604
|
+
params,
|
|
605
|
+
requireAuth: true,
|
|
606
|
+
...opts
|
|
607
|
+
});
|
|
608
|
+
}
|
|
609
|
+
createApikey(input, opts) {
|
|
610
|
+
return this.call("app.rocksky.apikey.createApikey", "POST", {
|
|
611
|
+
body: input,
|
|
612
|
+
requireAuth: true,
|
|
613
|
+
...opts
|
|
614
|
+
});
|
|
615
|
+
}
|
|
616
|
+
updateApikey(input, opts) {
|
|
617
|
+
return this.call("app.rocksky.apikey.updateApikey", "POST", {
|
|
618
|
+
body: input,
|
|
619
|
+
requireAuth: true,
|
|
620
|
+
...opts
|
|
621
|
+
});
|
|
622
|
+
}
|
|
623
|
+
removeApikey(params, opts) {
|
|
624
|
+
return this.call("app.rocksky.apikey.removeApikey", "POST", {
|
|
625
|
+
params,
|
|
626
|
+
requireAuth: true,
|
|
627
|
+
...opts
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
// src/namespaces/artist.ts
|
|
633
|
+
class ArtistNamespace {
|
|
634
|
+
call;
|
|
635
|
+
constructor(call) {
|
|
636
|
+
this.call = call;
|
|
637
|
+
}
|
|
638
|
+
getArtist(params, opts) {
|
|
639
|
+
return this.call("app.rocksky.artist.getArtist", "GET", {
|
|
640
|
+
params,
|
|
641
|
+
...opts
|
|
642
|
+
});
|
|
643
|
+
}
|
|
644
|
+
getArtists(params = {}, opts) {
|
|
645
|
+
return this.call("app.rocksky.artist.getArtists", "GET", {
|
|
646
|
+
params,
|
|
647
|
+
...opts
|
|
648
|
+
});
|
|
649
|
+
}
|
|
650
|
+
getArtistAlbums(params, opts) {
|
|
651
|
+
return this.call("app.rocksky.artist.getArtistAlbums", "GET", {
|
|
652
|
+
params,
|
|
653
|
+
...opts
|
|
654
|
+
});
|
|
655
|
+
}
|
|
656
|
+
getArtistTracks(params = {}, opts) {
|
|
657
|
+
return this.call("app.rocksky.artist.getArtistTracks", "GET", {
|
|
658
|
+
params,
|
|
659
|
+
...opts
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
getArtistListeners(params, opts) {
|
|
663
|
+
return this.call("app.rocksky.artist.getArtistListeners", "GET", {
|
|
664
|
+
params,
|
|
665
|
+
...opts
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
getArtistRecentListeners(params, opts) {
|
|
669
|
+
return this.call("app.rocksky.artist.getArtistRecentListeners", "GET", {
|
|
670
|
+
params,
|
|
671
|
+
...opts
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
// src/namespaces/charts.ts
|
|
677
|
+
class ChartsNamespace {
|
|
678
|
+
call;
|
|
679
|
+
constructor(call) {
|
|
680
|
+
this.call = call;
|
|
681
|
+
}
|
|
682
|
+
getScrobblesChart(params = {}, opts) {
|
|
683
|
+
return this.call("app.rocksky.charts.getScrobblesChart", "GET", {
|
|
684
|
+
params,
|
|
685
|
+
...opts
|
|
686
|
+
});
|
|
687
|
+
}
|
|
688
|
+
getTopArtists(params = {}, opts) {
|
|
689
|
+
return this.call("app.rocksky.charts.getTopArtists", "GET", {
|
|
690
|
+
params,
|
|
691
|
+
...opts
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
getTopTracks(params = {}, opts) {
|
|
695
|
+
return this.call("app.rocksky.charts.getTopTracks", "GET", {
|
|
696
|
+
params,
|
|
697
|
+
...opts
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// src/namespaces/dropbox.ts
|
|
703
|
+
class DropboxNamespace {
|
|
704
|
+
call;
|
|
705
|
+
constructor(call) {
|
|
706
|
+
this.call = call;
|
|
707
|
+
}
|
|
708
|
+
getFiles(params = {}, opts) {
|
|
709
|
+
return this.call("app.rocksky.dropbox.getFiles", "GET", {
|
|
710
|
+
params,
|
|
711
|
+
requireAuth: true,
|
|
712
|
+
...opts
|
|
713
|
+
});
|
|
714
|
+
}
|
|
715
|
+
getMetadata(params, opts) {
|
|
716
|
+
return this.call("app.rocksky.dropbox.getMetadata", "GET", {
|
|
717
|
+
params,
|
|
718
|
+
requireAuth: true,
|
|
719
|
+
...opts
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
getTemporaryLink(params, opts) {
|
|
723
|
+
return this.call("app.rocksky.dropbox.getTemporaryLink", "GET", {
|
|
724
|
+
params,
|
|
725
|
+
requireAuth: true,
|
|
726
|
+
...opts
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
downloadFile(params, opts) {
|
|
730
|
+
return this.call("app.rocksky.dropbox.downloadFile", "GET", {
|
|
731
|
+
params,
|
|
732
|
+
requireAuth: true,
|
|
733
|
+
...opts
|
|
734
|
+
});
|
|
735
|
+
}
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// src/namespaces/feed.ts
|
|
739
|
+
class FeedNamespace {
|
|
740
|
+
call;
|
|
741
|
+
constructor(call) {
|
|
742
|
+
this.call = call;
|
|
743
|
+
}
|
|
744
|
+
search(params, opts) {
|
|
745
|
+
return this.call("app.rocksky.feed.search", "GET", {
|
|
746
|
+
params,
|
|
747
|
+
...opts
|
|
748
|
+
});
|
|
749
|
+
}
|
|
750
|
+
getFeed(params, opts) {
|
|
751
|
+
return this.call("app.rocksky.feed.getFeed", "GET", {
|
|
752
|
+
params,
|
|
753
|
+
...opts
|
|
754
|
+
});
|
|
755
|
+
}
|
|
756
|
+
getFeedGenerators(params = {}, opts) {
|
|
757
|
+
return this.call("app.rocksky.feed.getFeedGenerators", "GET", {
|
|
758
|
+
params,
|
|
759
|
+
...opts
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
getFeedGenerator(params, opts) {
|
|
763
|
+
return this.call("app.rocksky.feed.getFeedGenerator", "GET", {
|
|
764
|
+
params,
|
|
765
|
+
...opts
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
describeFeedGenerator(opts) {
|
|
769
|
+
return this.call("app.rocksky.feed.describeFeedGenerator", "GET", {
|
|
770
|
+
...opts
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
getFeedSkeleton(params, opts) {
|
|
774
|
+
return this.call("app.rocksky.feed.getFeedSkeleton", "GET", {
|
|
775
|
+
params,
|
|
776
|
+
...opts
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
getRecommendations(params, opts) {
|
|
780
|
+
return this.call("app.rocksky.feed.getRecommendations", "GET", {
|
|
781
|
+
params,
|
|
782
|
+
...opts
|
|
783
|
+
});
|
|
784
|
+
}
|
|
785
|
+
getArtistRecommendations(params, opts) {
|
|
786
|
+
return this.call("app.rocksky.feed.getArtistRecommendations", "GET", {
|
|
787
|
+
params,
|
|
788
|
+
...opts
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
getAlbumRecommendations(params, opts) {
|
|
792
|
+
return this.call("app.rocksky.feed.getAlbumRecommendations", "GET", {
|
|
793
|
+
params,
|
|
794
|
+
...opts
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
getStories(params = {}, opts) {
|
|
798
|
+
return this.call("app.rocksky.feed.getStories", "GET", {
|
|
799
|
+
params,
|
|
800
|
+
...opts
|
|
801
|
+
});
|
|
802
|
+
}
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// src/namespaces/googledrive.ts
|
|
806
|
+
class GoogleDriveNamespace {
|
|
807
|
+
call;
|
|
808
|
+
constructor(call) {
|
|
809
|
+
this.call = call;
|
|
810
|
+
}
|
|
811
|
+
getFile(params, opts) {
|
|
812
|
+
return this.call("app.rocksky.googledrive.getFile", "GET", {
|
|
813
|
+
params,
|
|
814
|
+
requireAuth: true,
|
|
815
|
+
...opts
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
getFiles(params = {}, opts) {
|
|
819
|
+
return this.call("app.rocksky.googledrive.getFiles", "GET", {
|
|
820
|
+
params,
|
|
821
|
+
requireAuth: true,
|
|
822
|
+
...opts
|
|
823
|
+
});
|
|
824
|
+
}
|
|
825
|
+
downloadFile(params, opts) {
|
|
826
|
+
return this.call("app.rocksky.googledrive.downloadFile", "GET", {
|
|
827
|
+
params,
|
|
828
|
+
requireAuth: true,
|
|
829
|
+
...opts
|
|
830
|
+
});
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// src/namespaces/graph.ts
|
|
835
|
+
class GraphNamespace {
|
|
836
|
+
call;
|
|
837
|
+
constructor(call) {
|
|
838
|
+
this.call = call;
|
|
839
|
+
}
|
|
840
|
+
followAccount(params, opts) {
|
|
841
|
+
return this.call("app.rocksky.graph.followAccount", "POST", {
|
|
842
|
+
params,
|
|
843
|
+
requireAuth: true,
|
|
844
|
+
...opts
|
|
845
|
+
});
|
|
846
|
+
}
|
|
847
|
+
unfollowAccount(params, opts) {
|
|
848
|
+
return this.call("app.rocksky.graph.unfollowAccount", "POST", {
|
|
849
|
+
params,
|
|
850
|
+
requireAuth: true,
|
|
851
|
+
...opts
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
getFollowers(params, opts) {
|
|
855
|
+
return this.call("app.rocksky.graph.getFollowers", "GET", {
|
|
856
|
+
params,
|
|
857
|
+
...opts
|
|
858
|
+
});
|
|
859
|
+
}
|
|
860
|
+
getFollows(params, opts) {
|
|
861
|
+
return this.call("app.rocksky.graph.getFollows", "GET", {
|
|
862
|
+
params,
|
|
863
|
+
...opts
|
|
864
|
+
});
|
|
865
|
+
}
|
|
866
|
+
getKnownFollowers(params, opts) {
|
|
867
|
+
return this.call("app.rocksky.graph.getKnownFollowers", "GET", {
|
|
868
|
+
params,
|
|
869
|
+
...opts
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// src/namespaces/like.ts
|
|
875
|
+
class LikeNamespace {
|
|
876
|
+
call;
|
|
877
|
+
constructor(call) {
|
|
878
|
+
this.call = call;
|
|
879
|
+
}
|
|
880
|
+
likeSong(input = {}, opts) {
|
|
881
|
+
return this.call("app.rocksky.like.likeSong", "POST", {
|
|
882
|
+
body: input,
|
|
883
|
+
requireAuth: true,
|
|
884
|
+
...opts
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
dislikeSong(input = {}, opts) {
|
|
888
|
+
return this.call("app.rocksky.like.dislikeSong", "POST", {
|
|
889
|
+
body: input,
|
|
890
|
+
requireAuth: true,
|
|
891
|
+
...opts
|
|
892
|
+
});
|
|
893
|
+
}
|
|
894
|
+
likeShout(input = {}, opts) {
|
|
895
|
+
return this.call("app.rocksky.like.likeShout", "POST", {
|
|
896
|
+
body: input,
|
|
897
|
+
requireAuth: true,
|
|
898
|
+
...opts
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
dislikeShout(input = {}, opts) {
|
|
902
|
+
return this.call("app.rocksky.like.dislikeShout", "POST", {
|
|
903
|
+
body: input,
|
|
904
|
+
requireAuth: true,
|
|
905
|
+
...opts
|
|
906
|
+
});
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
|
|
910
|
+
// src/namespaces/mirror.ts
|
|
911
|
+
class MirrorNamespace {
|
|
912
|
+
call;
|
|
913
|
+
constructor(call) {
|
|
914
|
+
this.call = call;
|
|
915
|
+
}
|
|
916
|
+
getMirrorSources(opts) {
|
|
917
|
+
return this.call("app.rocksky.mirror.getMirrorSources", "GET", {
|
|
918
|
+
requireAuth: true,
|
|
919
|
+
...opts
|
|
920
|
+
});
|
|
921
|
+
}
|
|
922
|
+
putMirrorSource(input, opts) {
|
|
923
|
+
return this.call("app.rocksky.mirror.putMirrorSource", "POST", {
|
|
924
|
+
body: input,
|
|
925
|
+
requireAuth: true,
|
|
926
|
+
...opts
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// src/namespaces/player.ts
|
|
932
|
+
class PlayerNamespace {
|
|
933
|
+
call;
|
|
934
|
+
constructor(call) {
|
|
935
|
+
this.call = call;
|
|
936
|
+
}
|
|
937
|
+
getCurrentlyPlaying(params = {}, opts) {
|
|
938
|
+
return this.call("app.rocksky.player.getCurrentlyPlaying", "GET", {
|
|
939
|
+
params,
|
|
940
|
+
...opts
|
|
941
|
+
});
|
|
942
|
+
}
|
|
943
|
+
getPlaybackQueue(params = {}, opts) {
|
|
944
|
+
return this.call("app.rocksky.player.getPlaybackQueue", "GET", {
|
|
945
|
+
params,
|
|
946
|
+
...opts
|
|
947
|
+
});
|
|
948
|
+
}
|
|
949
|
+
play(params = {}, opts) {
|
|
950
|
+
return this.call("app.rocksky.player.play", "POST", {
|
|
951
|
+
params,
|
|
952
|
+
requireAuth: true,
|
|
953
|
+
...opts
|
|
954
|
+
});
|
|
955
|
+
}
|
|
956
|
+
pause(params = {}, opts) {
|
|
957
|
+
return this.call("app.rocksky.player.pause", "POST", {
|
|
958
|
+
params,
|
|
959
|
+
requireAuth: true,
|
|
960
|
+
...opts
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
next(params = {}, opts) {
|
|
964
|
+
return this.call("app.rocksky.player.next", "POST", {
|
|
965
|
+
params,
|
|
966
|
+
requireAuth: true,
|
|
967
|
+
...opts
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
previous(params = {}, opts) {
|
|
971
|
+
return this.call("app.rocksky.player.previous", "POST", {
|
|
972
|
+
params,
|
|
973
|
+
requireAuth: true,
|
|
974
|
+
...opts
|
|
975
|
+
});
|
|
976
|
+
}
|
|
977
|
+
seek(params, opts) {
|
|
978
|
+
return this.call("app.rocksky.player.seek", "POST", {
|
|
979
|
+
params,
|
|
980
|
+
requireAuth: true,
|
|
981
|
+
...opts
|
|
982
|
+
});
|
|
983
|
+
}
|
|
984
|
+
playFile(params, opts) {
|
|
985
|
+
return this.call("app.rocksky.player.playFile", "POST", {
|
|
986
|
+
params,
|
|
987
|
+
requireAuth: true,
|
|
988
|
+
...opts
|
|
989
|
+
});
|
|
990
|
+
}
|
|
991
|
+
playDirectory(params, opts) {
|
|
992
|
+
return this.call("app.rocksky.player.playDirectory", "POST", {
|
|
993
|
+
params,
|
|
994
|
+
requireAuth: true,
|
|
995
|
+
...opts
|
|
996
|
+
});
|
|
997
|
+
}
|
|
998
|
+
addItemsToQueue(params, opts) {
|
|
999
|
+
return this.call("app.rocksky.player.addItemsToQueue", "POST", {
|
|
1000
|
+
params,
|
|
1001
|
+
requireAuth: true,
|
|
1002
|
+
...opts
|
|
1003
|
+
});
|
|
1004
|
+
}
|
|
1005
|
+
addDirectoryToQueue(params, opts) {
|
|
1006
|
+
return this.call("app.rocksky.player.addDirectoryToQueue", "POST", {
|
|
1007
|
+
params,
|
|
1008
|
+
...opts
|
|
1009
|
+
});
|
|
1010
|
+
}
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
// src/namespaces/playlist.ts
|
|
1014
|
+
class PlaylistNamespace {
|
|
1015
|
+
call;
|
|
1016
|
+
constructor(call) {
|
|
1017
|
+
this.call = call;
|
|
1018
|
+
}
|
|
1019
|
+
getPlaylists(params = {}, opts) {
|
|
1020
|
+
return this.call("app.rocksky.playlist.getPlaylists", "GET", {
|
|
1021
|
+
params,
|
|
1022
|
+
...opts
|
|
1023
|
+
});
|
|
1024
|
+
}
|
|
1025
|
+
getPlaylist(params, opts) {
|
|
1026
|
+
return this.call("app.rocksky.playlist.getPlaylist", "GET", {
|
|
1027
|
+
params,
|
|
1028
|
+
...opts
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
createPlaylist(params, opts) {
|
|
1032
|
+
return this.call("app.rocksky.playlist.createPlaylist", "POST", {
|
|
1033
|
+
params,
|
|
1034
|
+
requireAuth: true,
|
|
1035
|
+
...opts
|
|
1036
|
+
});
|
|
1037
|
+
}
|
|
1038
|
+
removePlaylist(params, opts) {
|
|
1039
|
+
return this.call("app.rocksky.playlist.removePlaylist", "POST", {
|
|
1040
|
+
params,
|
|
1041
|
+
requireAuth: true,
|
|
1042
|
+
...opts
|
|
1043
|
+
});
|
|
1044
|
+
}
|
|
1045
|
+
startPlaylist(params, opts) {
|
|
1046
|
+
return this.call("app.rocksky.playlist.startPlaylist", "POST", {
|
|
1047
|
+
params,
|
|
1048
|
+
requireAuth: true,
|
|
1049
|
+
...opts
|
|
1050
|
+
});
|
|
1051
|
+
}
|
|
1052
|
+
insertDirectory(params, opts) {
|
|
1053
|
+
return this.call("app.rocksky.playlist.insertDirectory", "POST", {
|
|
1054
|
+
params,
|
|
1055
|
+
requireAuth: true,
|
|
1056
|
+
...opts
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
insertFiles(params, opts) {
|
|
1060
|
+
return this.call("app.rocksky.playlist.insertFiles", "POST", {
|
|
1061
|
+
params,
|
|
1062
|
+
requireAuth: true,
|
|
1063
|
+
...opts
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
removeTrack(params, opts) {
|
|
1067
|
+
return this.call("app.rocksky.playlist.removeTrack", "POST", {
|
|
1068
|
+
params,
|
|
1069
|
+
...opts
|
|
1070
|
+
});
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
// src/namespaces/scrobble.ts
|
|
1075
|
+
class ScrobbleNamespace {
|
|
1076
|
+
call;
|
|
1077
|
+
constructor(call) {
|
|
1078
|
+
this.call = call;
|
|
1079
|
+
}
|
|
1080
|
+
createScrobble(input, opts) {
|
|
1081
|
+
return this.call("app.rocksky.scrobble.createScrobble", "POST", {
|
|
1082
|
+
body: input,
|
|
1083
|
+
requireAuth: true,
|
|
1084
|
+
...opts
|
|
1085
|
+
});
|
|
1086
|
+
}
|
|
1087
|
+
getScrobble(params, opts) {
|
|
1088
|
+
return this.call("app.rocksky.scrobble.getScrobble", "GET", {
|
|
1089
|
+
params,
|
|
1090
|
+
...opts
|
|
1091
|
+
});
|
|
1092
|
+
}
|
|
1093
|
+
getScrobbles(params = {}, opts) {
|
|
1094
|
+
return this.call("app.rocksky.scrobble.getScrobbles", "GET", {
|
|
1095
|
+
params,
|
|
1096
|
+
...opts
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
// src/namespaces/shout.ts
|
|
1102
|
+
class ShoutNamespace {
|
|
1103
|
+
call;
|
|
1104
|
+
constructor(call) {
|
|
1105
|
+
this.call = call;
|
|
1106
|
+
}
|
|
1107
|
+
createShout(input = {}, opts) {
|
|
1108
|
+
return this.call("app.rocksky.shout.createShout", "POST", {
|
|
1109
|
+
body: input,
|
|
1110
|
+
requireAuth: true,
|
|
1111
|
+
...opts
|
|
1112
|
+
});
|
|
1113
|
+
}
|
|
1114
|
+
replyShout(input, opts) {
|
|
1115
|
+
return this.call("app.rocksky.shout.replyShout", "POST", {
|
|
1116
|
+
body: input,
|
|
1117
|
+
requireAuth: true,
|
|
1118
|
+
...opts
|
|
1119
|
+
});
|
|
1120
|
+
}
|
|
1121
|
+
reportShout(input, opts) {
|
|
1122
|
+
return this.call("app.rocksky.shout.reportShout", "POST", {
|
|
1123
|
+
body: input,
|
|
1124
|
+
requireAuth: true,
|
|
1125
|
+
...opts
|
|
1126
|
+
});
|
|
1127
|
+
}
|
|
1128
|
+
removeShout(params, opts) {
|
|
1129
|
+
return this.call("app.rocksky.shout.removeShout", "POST", {
|
|
1130
|
+
params,
|
|
1131
|
+
requireAuth: true,
|
|
1132
|
+
...opts
|
|
1133
|
+
});
|
|
1134
|
+
}
|
|
1135
|
+
getShoutReplies(params, opts) {
|
|
1136
|
+
return this.call("app.rocksky.shout.getShoutReplies", "GET", {
|
|
1137
|
+
params,
|
|
1138
|
+
...opts
|
|
1139
|
+
});
|
|
1140
|
+
}
|
|
1141
|
+
getProfileShouts(params, opts) {
|
|
1142
|
+
return this.call("app.rocksky.shout.getProfileShouts", "GET", {
|
|
1143
|
+
params,
|
|
1144
|
+
...opts
|
|
1145
|
+
});
|
|
1146
|
+
}
|
|
1147
|
+
getTrackShouts(params, opts) {
|
|
1148
|
+
return this.call("app.rocksky.shout.getTrackShouts", "GET", {
|
|
1149
|
+
params,
|
|
1150
|
+
...opts
|
|
1151
|
+
});
|
|
1152
|
+
}
|
|
1153
|
+
getArtistShouts(params, opts) {
|
|
1154
|
+
return this.call("app.rocksky.shout.getArtistShouts", "GET", {
|
|
1155
|
+
params,
|
|
1156
|
+
...opts
|
|
1157
|
+
});
|
|
1158
|
+
}
|
|
1159
|
+
getAlbumShouts(params, opts) {
|
|
1160
|
+
return this.call("app.rocksky.shout.getAlbumShouts", "GET", {
|
|
1161
|
+
params,
|
|
1162
|
+
...opts
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
// src/namespaces/song.ts
|
|
1168
|
+
class SongNamespace {
|
|
1169
|
+
call;
|
|
1170
|
+
constructor(call) {
|
|
1171
|
+
this.call = call;
|
|
1172
|
+
}
|
|
1173
|
+
getSong(params, opts) {
|
|
1174
|
+
return this.call("app.rocksky.song.getSong", "GET", {
|
|
1175
|
+
params,
|
|
1176
|
+
...opts
|
|
1177
|
+
});
|
|
1178
|
+
}
|
|
1179
|
+
getSongs(params = {}, opts) {
|
|
1180
|
+
return this.call("app.rocksky.song.getSongs", "GET", {
|
|
1181
|
+
params,
|
|
1182
|
+
...opts
|
|
1183
|
+
});
|
|
1184
|
+
}
|
|
1185
|
+
getSongRecentListeners(params, opts) {
|
|
1186
|
+
return this.call("app.rocksky.song.getSongRecentListeners", "GET", {
|
|
1187
|
+
params,
|
|
1188
|
+
...opts
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
1191
|
+
matchSong(params, opts) {
|
|
1192
|
+
return this.call("app.rocksky.song.matchSong", "GET", {
|
|
1193
|
+
params,
|
|
1194
|
+
...opts
|
|
1195
|
+
});
|
|
1196
|
+
}
|
|
1197
|
+
createSong(input, opts) {
|
|
1198
|
+
return this.call("app.rocksky.song.createSong", "POST", {
|
|
1199
|
+
body: input,
|
|
1200
|
+
requireAuth: true,
|
|
1201
|
+
...opts
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
}
|
|
1205
|
+
|
|
1206
|
+
// src/namespaces/spotify.ts
|
|
1207
|
+
class SpotifyNamespace {
|
|
1208
|
+
call;
|
|
1209
|
+
constructor(call) {
|
|
1210
|
+
this.call = call;
|
|
1211
|
+
}
|
|
1212
|
+
getCurrentlyPlaying(params = {}, opts) {
|
|
1213
|
+
return this.call("app.rocksky.spotify.getCurrentlyPlaying", "GET", {
|
|
1214
|
+
params,
|
|
1215
|
+
...opts
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
play(opts) {
|
|
1219
|
+
return this.call("app.rocksky.spotify.play", "POST", {
|
|
1220
|
+
requireAuth: true,
|
|
1221
|
+
...opts
|
|
1222
|
+
});
|
|
1223
|
+
}
|
|
1224
|
+
pause(opts) {
|
|
1225
|
+
return this.call("app.rocksky.spotify.pause", "POST", {
|
|
1226
|
+
requireAuth: true,
|
|
1227
|
+
...opts
|
|
1228
|
+
});
|
|
1229
|
+
}
|
|
1230
|
+
next(opts) {
|
|
1231
|
+
return this.call("app.rocksky.spotify.next", "POST", {
|
|
1232
|
+
requireAuth: true,
|
|
1233
|
+
...opts
|
|
1234
|
+
});
|
|
1235
|
+
}
|
|
1236
|
+
previous(opts) {
|
|
1237
|
+
return this.call("app.rocksky.spotify.previous", "POST", {
|
|
1238
|
+
requireAuth: true,
|
|
1239
|
+
...opts
|
|
1240
|
+
});
|
|
1241
|
+
}
|
|
1242
|
+
seek(params, opts) {
|
|
1243
|
+
return this.call("app.rocksky.spotify.seek", "POST", {
|
|
1244
|
+
params,
|
|
1245
|
+
requireAuth: true,
|
|
1246
|
+
...opts
|
|
1247
|
+
});
|
|
1248
|
+
}
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// src/namespaces/stats.ts
|
|
1252
|
+
class StatsNamespace {
|
|
1253
|
+
call;
|
|
1254
|
+
constructor(call) {
|
|
1255
|
+
this.call = call;
|
|
1256
|
+
}
|
|
1257
|
+
getStats(params, opts) {
|
|
1258
|
+
return this.call("app.rocksky.stats.getStats", "GET", {
|
|
1259
|
+
params,
|
|
1260
|
+
...opts
|
|
1261
|
+
});
|
|
1262
|
+
}
|
|
1263
|
+
getWrapped(params, opts) {
|
|
1264
|
+
return this.call("app.rocksky.stats.getWrapped", "GET", {
|
|
1265
|
+
params,
|
|
1266
|
+
...opts
|
|
1267
|
+
});
|
|
1268
|
+
}
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
// src/client.ts
|
|
1272
|
+
class RockskyClient {
|
|
1273
|
+
config;
|
|
1274
|
+
actor;
|
|
1275
|
+
album;
|
|
1276
|
+
apikey;
|
|
1277
|
+
artist;
|
|
1278
|
+
charts;
|
|
1279
|
+
dropbox;
|
|
1280
|
+
feed;
|
|
1281
|
+
googledrive;
|
|
1282
|
+
graph;
|
|
1283
|
+
like;
|
|
1284
|
+
mirror;
|
|
1285
|
+
player;
|
|
1286
|
+
playlist;
|
|
1287
|
+
scrobble;
|
|
1288
|
+
shout;
|
|
1289
|
+
song;
|
|
1290
|
+
spotify;
|
|
1291
|
+
stats;
|
|
1292
|
+
constructor(options = {}) {
|
|
1293
|
+
this.config = buildConfig(options);
|
|
1294
|
+
const call = (nsid, method, opts) => xrpcCall(this.config, nsid, method, opts ?? {});
|
|
1295
|
+
this.actor = new ActorNamespace(call);
|
|
1296
|
+
this.album = new AlbumNamespace(call);
|
|
1297
|
+
this.apikey = new ApikeyNamespace(call);
|
|
1298
|
+
this.artist = new ArtistNamespace(call);
|
|
1299
|
+
this.charts = new ChartsNamespace(call);
|
|
1300
|
+
this.dropbox = new DropboxNamespace(call);
|
|
1301
|
+
this.feed = new FeedNamespace(call);
|
|
1302
|
+
this.googledrive = new GoogleDriveNamespace(call);
|
|
1303
|
+
this.graph = new GraphNamespace(call);
|
|
1304
|
+
this.like = new LikeNamespace(call);
|
|
1305
|
+
this.mirror = new MirrorNamespace(call);
|
|
1306
|
+
this.player = new PlayerNamespace(call);
|
|
1307
|
+
this.playlist = new PlaylistNamespace(call);
|
|
1308
|
+
this.scrobble = new ScrobbleNamespace(call);
|
|
1309
|
+
this.shout = new ShoutNamespace(call);
|
|
1310
|
+
this.song = new SongNamespace(call);
|
|
1311
|
+
this.spotify = new SpotifyNamespace(call);
|
|
1312
|
+
this.stats = new StatsNamespace(call);
|
|
1313
|
+
}
|
|
1314
|
+
withAuth(auth) {
|
|
1315
|
+
return new RockskyClient({
|
|
1316
|
+
...this.optionsSnapshot(),
|
|
1317
|
+
auth
|
|
1318
|
+
});
|
|
1319
|
+
}
|
|
1320
|
+
withBaseUrl(baseUrl) {
|
|
1321
|
+
return new RockskyClient({
|
|
1322
|
+
...this.optionsSnapshot(),
|
|
1323
|
+
baseUrl
|
|
1324
|
+
});
|
|
1325
|
+
}
|
|
1326
|
+
realtime(options) {
|
|
1327
|
+
return createRealtimeClient({
|
|
1328
|
+
baseUrl: this.config.baseUrl,
|
|
1329
|
+
...options
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
paginate(args) {
|
|
1333
|
+
return paginate(args);
|
|
1334
|
+
}
|
|
1335
|
+
xrpc(nsid, method = "GET", opts = {}) {
|
|
1336
|
+
return xrpcCall(this.config, nsid, method, opts);
|
|
1337
|
+
}
|
|
1338
|
+
static builder() {
|
|
1339
|
+
return new RockskyClientBuilder;
|
|
1340
|
+
}
|
|
1341
|
+
optionsSnapshot() {
|
|
1342
|
+
return {
|
|
1343
|
+
baseUrl: this.config.baseUrl,
|
|
1344
|
+
auth: this.config.auth,
|
|
1345
|
+
fetch: this.config.fetch,
|
|
1346
|
+
headers: this.config.headers,
|
|
1347
|
+
timeoutMs: this.config.timeoutMs,
|
|
1348
|
+
retries: this.config.retries,
|
|
1349
|
+
retryDelayMs: this.config.retryDelayMs
|
|
1350
|
+
};
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
class RockskyClientBuilder {
|
|
1355
|
+
opts = {};
|
|
1356
|
+
baseUrl(url) {
|
|
1357
|
+
this.opts.baseUrl = url;
|
|
1358
|
+
return this;
|
|
1359
|
+
}
|
|
1360
|
+
auth(auth) {
|
|
1361
|
+
this.opts.auth = auth;
|
|
1362
|
+
return this;
|
|
1363
|
+
}
|
|
1364
|
+
bearer(token) {
|
|
1365
|
+
this.opts.auth = token;
|
|
1366
|
+
return this;
|
|
1367
|
+
}
|
|
1368
|
+
fetch(impl) {
|
|
1369
|
+
this.opts.fetch = impl;
|
|
1370
|
+
return this;
|
|
1371
|
+
}
|
|
1372
|
+
header(key, value) {
|
|
1373
|
+
this.opts.headers = { ...this.opts.headers, [key]: value };
|
|
1374
|
+
return this;
|
|
1375
|
+
}
|
|
1376
|
+
headers(headers) {
|
|
1377
|
+
this.opts.headers = { ...this.opts.headers, ...headers };
|
|
1378
|
+
return this;
|
|
1379
|
+
}
|
|
1380
|
+
userAgent(ua) {
|
|
1381
|
+
this.opts.userAgent = ua;
|
|
1382
|
+
return this;
|
|
1383
|
+
}
|
|
1384
|
+
timeout(ms) {
|
|
1385
|
+
this.opts.timeoutMs = ms;
|
|
1386
|
+
return this;
|
|
1387
|
+
}
|
|
1388
|
+
retries(n) {
|
|
1389
|
+
this.opts.retries = n;
|
|
1390
|
+
return this;
|
|
1391
|
+
}
|
|
1392
|
+
retryDelay(ms) {
|
|
1393
|
+
this.opts.retryDelayMs = ms;
|
|
1394
|
+
return this;
|
|
1395
|
+
}
|
|
1396
|
+
build() {
|
|
1397
|
+
return new RockskyClient(this.opts);
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
function createClient(options = {}) {
|
|
1401
|
+
return new RockskyClient(options);
|
|
1402
|
+
}
|
|
1403
|
+
// src/pipe.ts
|
|
1404
|
+
function pipe(value, ...ops) {
|
|
1405
|
+
let factory = typeof value === "function" ? value : () => value;
|
|
1406
|
+
for (const op of ops)
|
|
1407
|
+
factory = op(factory);
|
|
1408
|
+
return factory();
|
|
1409
|
+
}
|
|
1410
|
+
function map(fn) {
|
|
1411
|
+
return (factory) => async () => fn(await factory());
|
|
1412
|
+
}
|
|
1413
|
+
function tap(fn) {
|
|
1414
|
+
return (factory) => async () => {
|
|
1415
|
+
const a = await factory();
|
|
1416
|
+
await fn(a);
|
|
1417
|
+
return a;
|
|
1418
|
+
};
|
|
1419
|
+
}
|
|
1420
|
+
function withRetry(times, options = {}) {
|
|
1421
|
+
const delayMs = options.delayMs ?? 200;
|
|
1422
|
+
const factor = options.factor ?? 2;
|
|
1423
|
+
const shouldRetry = options.shouldRetry ?? (() => true);
|
|
1424
|
+
return (factory) => async () => {
|
|
1425
|
+
let lastErr;
|
|
1426
|
+
for (let attempt = 0;attempt <= times; attempt++) {
|
|
1427
|
+
try {
|
|
1428
|
+
return await factory();
|
|
1429
|
+
} catch (err) {
|
|
1430
|
+
lastErr = err;
|
|
1431
|
+
if (attempt === times || !shouldRetry(err, attempt))
|
|
1432
|
+
throw err;
|
|
1433
|
+
await sleep2(delayMs * Math.pow(factor, attempt));
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
throw lastErr;
|
|
1437
|
+
};
|
|
1438
|
+
}
|
|
1439
|
+
function withTimeout(ms) {
|
|
1440
|
+
return (factory) => () => new Promise((resolve, reject) => {
|
|
1441
|
+
const timer = setTimeout(() => reject(new RockskyTimeoutError(ms)), ms);
|
|
1442
|
+
factory().then((v) => {
|
|
1443
|
+
clearTimeout(timer);
|
|
1444
|
+
resolve(v);
|
|
1445
|
+
}, (err) => {
|
|
1446
|
+
clearTimeout(timer);
|
|
1447
|
+
reject(err);
|
|
1448
|
+
});
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
function withFallback(fallback) {
|
|
1452
|
+
return (factory) => async () => {
|
|
1453
|
+
try {
|
|
1454
|
+
return await factory();
|
|
1455
|
+
} catch (err) {
|
|
1456
|
+
return typeof fallback === "function" ? await fallback(err) : fallback;
|
|
1457
|
+
}
|
|
1458
|
+
};
|
|
1459
|
+
}
|
|
1460
|
+
function catchError(handler) {
|
|
1461
|
+
return (factory) => async () => {
|
|
1462
|
+
try {
|
|
1463
|
+
return await factory();
|
|
1464
|
+
} catch (err) {
|
|
1465
|
+
return await handler(err);
|
|
1466
|
+
}
|
|
1467
|
+
};
|
|
1468
|
+
}
|
|
1469
|
+
function sleep2(ms) {
|
|
1470
|
+
return new Promise((r) => setTimeout(r, ms));
|
|
1471
|
+
}
|
|
1472
|
+
export {
|
|
1473
|
+
withTimeout,
|
|
1474
|
+
withRetry,
|
|
1475
|
+
withFallback,
|
|
1476
|
+
tap,
|
|
1477
|
+
pipe,
|
|
1478
|
+
paginate,
|
|
1479
|
+
map,
|
|
1480
|
+
createRealtimeClient,
|
|
1481
|
+
createClient,
|
|
1482
|
+
catchError,
|
|
1483
|
+
RockskyTimeoutError,
|
|
1484
|
+
RockskyHttpError,
|
|
1485
|
+
RockskyError,
|
|
1486
|
+
RockskyClientBuilder,
|
|
1487
|
+
RockskyClient,
|
|
1488
|
+
RockskyAuthError,
|
|
1489
|
+
RealtimeClientBuilder,
|
|
1490
|
+
RealtimeClient,
|
|
1491
|
+
DEFAULT_BASE_URL
|
|
1492
|
+
};
|