e621stream 0.0.0 → 0.0.3

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
@@ -1,9 +1,9 @@
1
1
  # e621stream
2
2
 
3
- A TypeScript client for [E621Stream](https://e621.stream), a live WebSocket stream of e621 activity. It works in Node 22+, Bun, Deno and browsers, has no dependencies, and every event type is typed down to the record it carries.
3
+ A client for [E621Stream](https://e621.stream). Works in node 22+, bun, deno & browsers, has no dependencies, and every event is typed down to the record it has.
4
4
 
5
- ```bash
6
- npm install e621stream
5
+ ```sh
6
+ npm i e621stream
7
7
  ```
8
8
 
9
9
  ```ts
@@ -18,7 +18,7 @@ stream.on("post.create", (event) => {
18
18
  console.log(event.data.post.id, event.data.post.tags.general);
19
19
  });
20
20
  stream.on("post.update", (event) => {
21
- // only the fields that changed, tags per category
21
+ // only what changed, tags are per category
22
22
  console.log(event.data.changes?.["tags.general"]?.added);
23
23
  });
24
24
  stream.on("comment.update", (event) => {
@@ -28,12 +28,20 @@ stream.on("error", err => console.error(err));
28
28
  stream.connect();
29
29
  ```
30
30
 
31
- - **Events:** `on("<event type>", ...)` for one type, typed to its data, or `on("dispatch", ...)` for everything, narrowed by checking `event.type`. See [Events](https://e621.stream/events/) for what each one is.
32
- - **Reconnecting:** the connection is reopened with backoff when it drops, and resumes from the last event it got, so nothing is missed. It isn't reopened after a close retrying won't fix, like bad credentials. `reconnect: false` turns it off.
33
- - **Resuming:** pass `cursor` (an event id, or a millisecond timestamp) to replay from there. `stream.cursor` is the last event received.
34
- - **Changing subscriptions:** `stream.subscribe([...])`.
35
- - **Private events:** like `dmail.create`, these are polled with your own credentials and have to be subscribed to by name.
36
- - **Other events:** `ready`, `replayComplete`, `subscribed`, `reconnecting`, `close` and `error`.
37
- - **Older Node:** pass a WebSocket implementation, like the `ws` package, as the `WebSocket` option.
31
+ Listen for an event type with `on("post.create", ...)`, or everything with `on("dispatch", ...)` (check `event.type` to narrow it). The others are `ready`, `replayComplete`, `subscribed`, `reconnecting`, `close` and `error`. See [Events](https://e621.stream/events/) for what each event is.
38
32
 
39
- Event data comes from the [e621 module](https://www.npmjs.com/package/e621)'s types, so records like `LegacyPost`, `Comment` and `ForumTopic` are exported here too. Mod action events are typed per action: checking `event.data.action` narrows `event.data.values`.
33
+ #### Options
34
+ | Option | Type | Default | Description |
35
+ |:---:|:---:|:---:|:---:|
36
+ | `subscriptions` | Array | | what to subscribe to, `stream.subscribe([...])` changes it later |
37
+ | `auth` | Object | None | `{ username, apiKey }`, or `{ token }` from [/authorize](https://e621.stream/authorize) |
38
+ | `cursor` | String \| Number | None | an event id or ms timestamp to replay from, `stream.cursor` is the last event you got |
39
+ | `reconnect` | Boolean | `true` | reconnect when the connection drops (not after things like bad credentials) |
40
+ | `client` | String | None | shown in the server's logs |
41
+ | `url` | String | `https://e621.stream` | the websocket url comes from its `/info`, a `ws://` or `wss://` url is connected to directly |
42
+ | `fetch` | Function | global `fetch` | used for `/info` |
43
+ | `WebSocket` | WebSocket | global | for older node, the `ws` package works |
44
+
45
+ Private events like `dmail.create` have to be subscribed to by name.
46
+
47
+ Records like `LegacyPost`, `Comment` and `ForumTopic` come from the [e621 module](https://www.npmjs.com/package/e621)'s types, and are exported here too. Mod action events are typed per action, so checking `event.data.action` narrows `event.data.values`.
@@ -1,24 +1,29 @@
1
1
  import Emitter from "./Emitter.ts";
2
2
  import { type EventType, type PrivateEventType, type StreamEvent, type Subscription } from "./events.ts";
3
3
  export interface Options {
4
- /** your e621 username and an api key, from Account > Manage API Access */
4
+ /** Your e621 username & api key, or a token from https://e621.stream/authorize. */
5
5
  auth?: {
6
6
  apiKey: string;
7
7
  username: string;
8
+ } | {
9
+ token: string;
8
10
  };
9
- /** a name for your client, shown in the server's logs */
11
+ /** Shown in the server's logs. */
10
12
  client?: string;
11
- /** an event id (or a millisecond timestamp) to replay from. after that, reconnecting resumes from the last event */
13
+ /** An event id or millisecond timestamp to replay from. */
12
14
  cursor?: number | string;
13
- /** reconnects with backoff when the connection drops, unless the server closed it for something retrying won't fix */
15
+ /** Used to get the websocket url from `/info`. */
16
+ fetch?: typeof fetch;
17
+ /** Reconnect when the connection drops. */
14
18
  reconnect?: boolean;
15
19
  subscriptions: Array<Subscription>;
20
+ /** The site, the websocket url comes from its `/info`. A `ws://` or `wss://` url is connected to directly. */
16
21
  url?: string;
17
- /** for runtimes without a global WebSocket, like node before 22 (the `ws` package works) */
22
+ /** For runtimes without a global WebSocket (node < 22), the `ws` package works. */
18
23
  WebSocket?: typeof WebSocket;
19
24
  }
20
25
  export interface Ready {
21
- /** when replaying, set if the cursor was older than anything still kept */
26
+ /** If the cursor was older than anything still kept. */
22
27
  cursor_expired?: boolean;
23
28
  replaying: boolean;
24
29
  session_id: string;
@@ -36,7 +41,7 @@ export interface ClientEvents {
36
41
  reason: string;
37
42
  reconnecting: boolean;
38
43
  }];
39
- /** every event, public or private */
44
+ /** Every event, public or private. */
40
45
  dispatch: [StreamEvent];
41
46
  error: [Error];
42
47
  ready: [Ready];
@@ -44,7 +49,6 @@ export interface ClientEvents {
44
49
  attempt: number;
45
50
  delayMS: number;
46
51
  }];
47
- /** replay is done, live events follow */
48
52
  replayComplete: [{
49
53
  cursor: string | null;
50
54
  events: number;
@@ -59,8 +63,8 @@ export declare class StreamError extends Error {
59
63
  constructor(code: number, message: string);
60
64
  }
61
65
  /**
62
- * a connection to E621Stream, see https://e621.stream
63
- *
66
+ * A connection to E621Stream, see https://e621.stream
67
+ * @example
64
68
  * ```ts
65
69
  * const stream = new E621Stream({ auth: { username, apiKey }, subscriptions: ["post.create"] });
66
70
  * stream.on("post.create", event => console.log(event.data.post.id));
@@ -70,12 +74,12 @@ export declare class StreamError extends Error {
70
74
  export declare class E621Stream extends Emitter<Listeners> {
71
75
  private attempt;
72
76
  private closing;
77
+ private connecting;
73
78
  private heartbeat;
74
79
  private lastError;
75
- private lastMessage;
80
+ private lastHeartbeatAck;
76
81
  private reconnectTimer;
77
82
  private socket;
78
- /** the newest event received, which reconnecting resumes from */
79
83
  cursor: string | null;
80
84
  readonly options: Options & {
81
85
  url: string;
@@ -83,13 +87,15 @@ export declare class E621Stream extends Emitter<Listeners> {
83
87
  constructor(options: Options);
84
88
  private handle;
85
89
  private onClose;
90
+ private open;
86
91
  private send;
87
92
  private startHeartbeat;
88
93
  private stopHeartbeat;
89
- /** closes the connection for good */
94
+ private websocketURL;
95
+ /** Close the connection. */
90
96
  close(): void;
91
97
  connect(): this;
92
- /** replaces the current subscriptions, and keeps them for reconnecting */
98
+ /** Replace the current subscriptions. */
93
99
  subscribe(subscriptions: Array<Subscription>): void;
94
100
  }
95
101
  export {};
@@ -8,7 +8,6 @@ export class StreamError extends Error {
8
8
  this.name = "StreamError";
9
9
  }
10
10
  }
11
- // closing for any of these again would just get the same result
12
11
  const FATAL = new Set([
13
12
  CloseCodes.UNKNOWN_OP,
14
13
  CloseCodes.DECODE_ERROR,
@@ -17,14 +16,14 @@ const FATAL = new Set([
17
16
  CloseCodes.INVALID_SUBSCRIPTION,
18
17
  CloseCodes.INVALID_CURSOR,
19
18
  CloseCodes.AUTHENTICATION_EXPIRED,
19
+ CloseCodes.DISCONNECTED,
20
+ CloseCodes.BANNED,
20
21
  ]);
21
22
  const MAX_DELAY_MS = 60_000;
22
23
  const HEARTBEAT_MS = 30_000;
23
- // the server answers heartbeats and pings, nothing for this long means the connection is gone without having closed
24
- const SILENT_MS = 75_000;
25
24
  /**
26
- * a connection to E621Stream, see https://e621.stream
27
- *
25
+ * A connection to E621Stream, see https://e621.stream
26
+ * @example
28
27
  * ```ts
29
28
  * const stream = new E621Stream({ auth: { username, apiKey }, subscriptions: ["post.create"] });
30
29
  * stream.on("post.create", event => console.log(event.data.post.id));
@@ -34,25 +33,24 @@ const SILENT_MS = 75_000;
34
33
  export class E621Stream extends Emitter {
35
34
  attempt = 0;
36
35
  closing = false;
36
+ connecting = false;
37
37
  heartbeat = null;
38
38
  lastError = null;
39
- lastMessage = 0;
39
+ lastHeartbeatAck = true;
40
40
  reconnectTimer = null;
41
41
  socket = null;
42
- /** the newest event received, which reconnecting resumes from */
43
42
  cursor;
44
43
  options;
45
44
  constructor(options) {
46
45
  super();
47
- this.options = { reconnect: true, url: "wss://e621.stream/ws", ...options };
46
+ this.options = { reconnect: true, url: "https://e621.stream", ...options };
48
47
  this.cursor = options.cursor === undefined ? null : String(options.cursor);
49
48
  }
50
49
  handle(raw) {
51
50
  if (typeof raw !== "string") {
52
- this.emit("error", new Error("got a binary message, compression isn't supported by this client"));
51
+ this.emit("error", new Error("compression isn't supported"));
53
52
  return;
54
53
  }
55
- this.lastMessage = Date.now();
56
54
  const message = JSON.parse(raw);
57
55
  switch (message.op) {
58
56
  case "hello": {
@@ -60,7 +58,7 @@ export class E621Stream extends Emitter {
60
58
  this.send({
61
59
  op: "identify",
62
60
  d: {
63
- ...(auth ? { auth: { username: auth.username, api_key: auth.apiKey } } : {}),
61
+ ...(auth ? { auth: "token" in auth ? { token: auth.token } : { username: auth.username, api_key: auth.apiKey } } : {}),
64
62
  ...(client ? { client } : {}),
65
63
  ...(this.cursor === null ? {} : { cursor: this.cursor }),
66
64
  subscriptions,
@@ -75,11 +73,10 @@ export class E621Stream extends Emitter {
75
73
  }
76
74
  case "dispatch": {
77
75
  const event = { id: message.id, type: message.type, time: message.time, data: message.data, ...(message.private ? { private: true } : {}) };
78
- // private events aren't in the stream, so they can't be resumed from
79
76
  if (!event.private)
80
77
  this.cursor = event.id;
81
78
  this.emit("dispatch", event);
82
- // typescript can't tie each type in the union to its own listener, it's the same event either way
79
+ // typescript can't narrow this
83
80
  this.emitUnchecked(event.type, event);
84
81
  break;
85
82
  }
@@ -91,6 +88,10 @@ export class E621Stream extends Emitter {
91
88
  this.emit("subscribed", message.d.subscriptions);
92
89
  break;
93
90
  }
91
+ case "heartbeat_ack": {
92
+ this.lastHeartbeatAck = true;
93
+ break;
94
+ }
94
95
  case "error": {
95
96
  const { code, message: text } = message.d;
96
97
  this.lastError = new StreamError(code, text);
@@ -110,7 +111,6 @@ export class E621Stream extends Emitter {
110
111
  if (!reconnecting)
111
112
  return;
112
113
  this.attempt++;
113
- // a server that's rate limiting this connection wants a longer break
114
114
  const base = code === CloseCodes.RATE_LIMITED ? 30_000 : 1000;
115
115
  const delayMS = Math.min(MAX_DELAY_MS, base * 2 ** (this.attempt - 1)) * (0.75 + Math.random() * 0.5);
116
116
  this.emit("reconnecting", { attempt: this.attempt, delayMS: Math.round(delayMS) });
@@ -119,18 +119,32 @@ export class E621Stream extends Emitter {
119
119
  this.connect();
120
120
  }, delayMS);
121
121
  }
122
+ open(Socket, url) {
123
+ const socket = this.socket = new Socket(url);
124
+ socket.addEventListener("open", () => { this.startHeartbeat(); });
125
+ socket.addEventListener("message", (event) => {
126
+ try {
127
+ this.handle(event.data);
128
+ }
129
+ catch (err) {
130
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
131
+ }
132
+ });
133
+ socket.addEventListener("close", (event) => { this.onClose(event.code, event.reason); });
134
+ socket.addEventListener("error", () => null);
135
+ }
122
136
  send(payload) {
123
137
  if (this.socket?.readyState === 1)
124
138
  this.socket.send(JSON.stringify(payload));
125
139
  }
126
140
  startHeartbeat() {
127
- this.lastMessage = Date.now();
141
+ this.lastHeartbeatAck = true;
128
142
  this.heartbeat = setInterval(() => {
129
- if (Date.now() - this.lastMessage > SILENT_MS) {
130
- // a client-side close code, nothing the server would send
131
- this.socket?.close(4999, "no response from the server");
143
+ if (!this.lastHeartbeatAck) {
144
+ this.socket?.close(4999, "heartbeat not acknowledged");
132
145
  return;
133
146
  }
147
+ this.lastHeartbeatAck = false;
134
148
  this.send({ op: "heartbeat" });
135
149
  }, HEARTBEAT_MS);
136
150
  }
@@ -139,7 +153,20 @@ export class E621Stream extends Emitter {
139
153
  clearInterval(this.heartbeat);
140
154
  this.heartbeat = null;
141
155
  }
142
- /** closes the connection for good */
156
+ // fetched every time, so it can move
157
+ async websocketURL() {
158
+ const { url } = this.options;
159
+ if (/^wss?:\/\//i.test(url))
160
+ return url;
161
+ const res = await (this.options.fetch ?? fetch)(new URL("/info", url));
162
+ if (!res.ok)
163
+ throw new Error(`${url}/info returned ${res.status}`);
164
+ const { websocket } = await res.json();
165
+ if (typeof websocket !== "string")
166
+ throw new Error(`${url}/info didn't have a websocket url`);
167
+ return new URL(websocket, url).href;
168
+ }
169
+ /** Close the connection. */
143
170
  close() {
144
171
  this.closing = true;
145
172
  if (this.reconnectTimer)
@@ -148,30 +175,28 @@ export class E621Stream extends Emitter {
148
175
  this.socket?.close(1000, "closed by client");
149
176
  }
150
177
  connect() {
151
- if (this.socket)
178
+ if (this.socket || this.connecting)
152
179
  return this;
153
180
  this.closing = false;
154
- // the dom types say it's always there, node before 22 doesn't have it
181
+ // not present before node 22
155
182
  const global = globalThis.WebSocket;
156
183
  const Socket = this.options.WebSocket ?? global;
157
184
  if (!Socket)
158
- throw new Error("there's no global WebSocket here, pass one as the WebSocket option");
159
- const socket = this.socket = new Socket(this.options.url);
160
- socket.addEventListener("open", () => { this.startHeartbeat(); });
161
- socket.addEventListener("message", (event) => {
162
- try {
163
- this.handle(event.data);
164
- }
165
- catch (err) {
166
- this.emit("error", err instanceof Error ? err : new Error(String(err)));
167
- }
185
+ throw new Error("no WebSocket available, pass one with the WebSocket option");
186
+ this.connecting = true;
187
+ this.websocketURL().then((url) => {
188
+ this.connecting = false;
189
+ if (!this.closing)
190
+ this.open(Socket, url);
191
+ }, (err) => {
192
+ this.connecting = false;
193
+ this.emit("error", err instanceof Error ? err : new Error(String(err)));
194
+ // retried the same as a dropped connection
195
+ this.onClose(1006, "couldn't get the websocket url");
168
196
  });
169
- socket.addEventListener("close", (event) => { this.onClose(event.code, event.reason); });
170
- // the close event that follows has the details
171
- socket.addEventListener("error", () => null);
172
197
  return this;
173
198
  }
174
- /** replaces the current subscriptions, and keeps them for reconnecting */
199
+ /** Replace the current subscriptions. */
175
200
  subscribe(subscriptions) {
176
201
  this.options.subscriptions = subscriptions;
177
202
  this.send({ op: "subscribe", d: { subscriptions } });
@@ -1 +1 @@
1
- {"version":3,"file":"E621Stream.js","sourceRoot":"","sources":["../lib/E621Stream.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"E621Stream.js","sourceRoot":"","sources":["../lib/E621Stream.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,UAAU,EAA8E,MAAM,aAAa,CAAC;AA0CrH,MAAM,OAAO,WAAY,SAAQ,KAAK;IACb;IAArB,YAAqB,IAAY,EAAE,OAAe;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QADE,SAAI,GAAJ,IAAI,CAAQ;QAE7B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC9B,CAAC;CACJ;AAED,MAAM,KAAK,GAAG,IAAI,GAAG,CAAS;IAC1B,UAAU,CAAC,UAAU;IACrB,UAAU,CAAC,YAAY;IACvB,UAAU,CAAC,qBAAqB;IAChC,UAAU,CAAC,kBAAkB;IAC7B,UAAU,CAAC,oBAAoB;IAC/B,UAAU,CAAC,cAAc;IACzB,UAAU,CAAC,sBAAsB;IACjC,UAAU,CAAC,YAAY;IACvB,UAAU,CAAC,MAAM;CACpB,CAAC,CAAC;AACH,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,YAAY,GAAG,MAAM,CAAC;AAE5B;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAW,SAAQ,OAAkB;IACtC,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,KAAK,CAAC;IAChB,UAAU,GAAG,KAAK,CAAC;IACnB,SAAS,GAA0C,IAAI,CAAC;IACxD,SAAS,GAAuB,IAAI,CAAC;IACrC,gBAAgB,GAAG,IAAI,CAAC;IACxB,cAAc,GAAyC,IAAI,CAAC;IAC5D,MAAM,GAAqB,IAAI,CAAC;IACxC,MAAM,CAAgB;IACb,OAAO,CAA4B;IAE5C,YAAY,OAAgB;QACxB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,qBAAqB,EAAE,GAAG,OAAO,EAAE,CAAC;QAC3E,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/E,CAAC;IAEO,MAAM,CAAC,GAAY;QACvB,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC1B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC,CAAC;YAC7D,OAAO;QACX,CAAC;QACD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAA2G,CAAC;QAC1I,QAAQ,OAAO,CAAC,EAAE,EAAE,CAAC;YACjB,KAAK,OAAO,CAAC,CAAC,CAAC;gBACX,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;gBACrD,IAAI,CAAC,IAAI,CAAC;oBACN,EAAE,EAAE,UAAU;oBACd,CAAC,EAAE;wBACC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBACtH,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC7B,GAAG,CAAC,IAAI,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC;wBACxD,aAAa;qBAChB;iBACJ,CAAC,CAAC;gBACH,MAAM;YACV,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACX,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;gBACjB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAU,CAAC,CAAC;gBACvC,MAAM;YACV,CAAC;YACD,KAAK,UAAU,CAAC,CAAC,CAAC;gBACd,MAAM,KAAK,GAAG,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAiB,CAAC;gBAC3J,IAAI,CAAC,KAAK,CAAC,OAAO;oBAAE,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC,EAAE,CAAC;gBAC3C,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;gBAC7B,+BAA+B;gBAC/B,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;gBACtC,MAAM;YACV,CAAC;YACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;gBACrB,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAA8C,CAAC,CAAC;gBACpF,MAAM;YACV,CAAC;YACD,KAAK,YAAY,CAAC,CAAC,CAAC;gBAChB,IAAI,CAAC,IAAI,CAAC,YAAY,EAAG,OAAO,CAAC,CAA4C,CAAC,aAAa,CAAC,CAAC;gBAC7F,MAAM;YACV,CAAC;YACD,KAAK,eAAe,CAAC,CAAC,CAAC;gBACnB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;gBAC7B,MAAM;YACV,CAAC;YACD,KAAK,OAAO,CAAC,CAAC,CAAC;gBACX,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,CAAsC,CAAC;gBAC/E,IAAI,CAAC,SAAS,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBAC7C,MAAM;YACV,CAAC;QACL,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,IAAY,EAAE,MAAc;QACxC,IAAI,CAAC,aAAa,EAAE,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;QACtB,MAAM,YAAY,GAAG,CAAC,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC3F,IAAI,KAAK;YAAE,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACrC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,IAAI,MAAM,EAAE,YAAY,EAAE,CAAC,CAAC;QAC7E,IAAI,CAAC,YAAY;YAAE,OAAO;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,KAAK,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;QAC9D,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,IAAI,CAAC,MAAM,EAAE,GAAG,GAAG,CAAC,CAAC;QACtG,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC,cAAc,GAAG,UAAU,CAAC,GAAG,EAAE;YAClC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;YAC3B,IAAI,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC,EAAE,OAAO,CAAC,CAAC;IAChB,CAAC;IAEO,IAAI,CAAC,MAAwB,EAAE,GAAW;QAC9C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7C,MAAM,CAAC,gBAAgB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;QAClE,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,CAAC,KAAmB,EAAE,EAAE;YACvD,IAAI,CAAC;gBACD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5B,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC5E,CAAC;QACL,CAAC,CAAC,CAAC;QACH,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,KAAiB,EAAE,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACrG,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;IACjD,CAAC;IAEO,IAAI,CAAC,OAAe;QACxB,IAAI,IAAI,CAAC,MAAM,EAAE,UAAU,KAAK,CAAC;YAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACjF,CAAC;IAEO,cAAc;QAClB,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC;QAC7B,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAC9B,IAAI,CAAC,IAAI,CAAC,gBAAgB,EAAE,CAAC;gBACzB,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,4BAA4B,CAAC,CAAC;gBACvD,OAAO;YACX,CAAC;YACD,IAAI,CAAC,gBAAgB,GAAG,KAAK,CAAC;YAC9B,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,CAAC;QACnC,CAAC,EAAE,YAAY,CAAC,CAAC;IACrB,CAAC;IAEO,aAAa;QACjB,IAAI,IAAI,CAAC,SAAS;YAAE,aAAa,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC;IAC1B,CAAC;IAED,qCAAqC;IAC7B,KAAK,CAAC,YAAY;QACtB,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;QACxC,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,EAAE;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,kBAAkB,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC;QACnE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,GAAG,CAAC,IAAI,EAA6B,CAAC;QAClE,IAAI,OAAO,SAAS,KAAK,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,GAAG,mCAAmC,CAAC,CAAC;QAC9F,OAAO,IAAI,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC;IACxC,CAAC;IAED,4BAA4B;IAC5B,KAAK;QACD,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,IAAI,CAAC,cAAc;YAAE,YAAY,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC3B,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;IACjD,CAAC;IAED,OAAO;QACH,IAAI,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO,IAAI,CAAC;QAChD,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,6BAA6B;QAC7B,MAAM,MAAM,GAAI,UAA4D,CAAC,SAAS,CAAC;QACvF,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC;QAChD,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAC;QAC3F,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;QACvB,IAAI,CAAC,YAAY,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;YAC7B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC,EAAE,CAAC,GAAY,EAAE,EAAE;YAChB,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxE,2CAA2C;YAC3C,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,gCAAgC,CAAC,CAAC;QACzD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,yCAAyC;IACzC,SAAS,CAAC,aAAkC;QACxC,IAAI,CAAC,OAAO,CAAC,aAAa,GAAG,aAAa,CAAC;QAC3C,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,EAAE,aAAa,EAAE,EAAE,CAAC,CAAC;IACzD,CAAC;CACJ"}
package/dist/Emitter.d.ts CHANGED
@@ -4,7 +4,6 @@ export default class Emitter<Events extends {
4
4
  }> {
5
5
  private listeners;
6
6
  protected emit<K extends keyof Events>(event: K, ...args: Events[K]): void;
7
- /** for an event name only known at runtime, whose listeners' arguments can't be checked */
8
7
  protected emitUnchecked(event: keyof Events, ...args: Array<unknown>): void;
9
8
  off<K extends keyof Events>(event: K, listener: NoInfer<Listener<Events[K]>>): this;
10
9
  on<K extends keyof Events>(event: K, listener: NoInfer<Listener<Events[K]>>): this;
package/dist/Emitter.js CHANGED
@@ -1,12 +1,9 @@
1
- // a minimal typed event emitter, so the client has no dependencies and works anywhere
2
1
  export default class Emitter {
3
- // listeners of every event share one map, so they're stored without their argument types
4
2
  listeners = new Map();
5
3
  emit(event, ...args) {
6
4
  for (const listener of this.listeners.get(event) ?? [])
7
5
  listener(...args);
8
6
  }
9
- /** for an event name only known at runtime, whose listeners' arguments can't be checked */
10
7
  emitUnchecked(event, ...args) {
11
8
  for (const listener of this.listeners.get(event) ?? [])
12
9
  listener(...args);
@@ -1 +1 @@
1
- {"version":3,"file":"Emitter.js","sourceRoot":"","sources":["../lib/Emitter.ts"],"names":[],"mappings":"AAAA,sFAAsF;AAItF,MAAM,CAAC,OAAO,OAAO,OAAO;IACxB,yFAAyF;IACjF,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEhD,IAAI,CAAyB,KAAQ,EAAE,GAAG,IAAe;QAC/D,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YAAG,QAAgC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvG,CAAC;IAED,2FAA2F;IACjF,aAAa,CAAC,KAAmB,EAAE,GAAG,IAAoB;QAChE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YAAG,QAAqC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5G,CAAC;IAED,GAAG,CAAyB,KAAQ,EAAE,QAAsC;QACxE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,EAAE,CAAyB,KAAQ,EAAE,QAAsC;QACvE,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAyB,KAAQ,EAAE,QAAsC;QACzE,MAAM,OAAO,GAAwB,CAAC,GAAG,IAAI,EAAE,EAAE;YAC7C,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACzB,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;CACJ"}
1
+ {"version":3,"file":"Emitter.js","sourceRoot":"","sources":["../lib/Emitter.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,OAAO,OAAO,OAAO;IAChB,SAAS,GAAG,IAAI,GAAG,EAA8B,CAAC;IAEhD,IAAI,CAAyB,KAAQ,EAAE,GAAG,IAAe;QAC/D,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YAAG,QAAgC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvG,CAAC;IAES,aAAa,CAAC,KAAmB,EAAE,GAAG,IAAoB;QAChE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE;YAAG,QAAqC,CAAC,GAAG,IAAI,CAAC,CAAC;IAC5G,CAAC;IAED,GAAG,CAAyB,KAAQ,EAAE,QAAsC;QACxE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC5C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,EAAE,CAAyB,KAAQ,EAAE,QAAsC;QACvE,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC,GAAG;YAAE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,IAAI,GAAG,EAAE,CAAC,CAAC;QACrD,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClB,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,IAAI,CAAyB,KAAQ,EAAE,QAAsC;QACzE,MAAM,OAAO,GAAwB,CAAC,GAAG,IAAI,EAAE,EAAE;YAC7C,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;YACzB,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC;QACF,OAAO,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACnC,CAAC;CACJ"}
package/dist/changes.d.ts CHANGED
@@ -1,21 +1,19 @@
1
1
  import type { LegacyPost } from "./generated.ts";
2
- /** a field's value before and after */
2
+ /** A field's old and new value. */
3
3
  export interface ValueChange<T> {
4
4
  new: T;
5
5
  old: T;
6
6
  }
7
- /** what was added to and removed from a list */
8
7
  export interface SetChange<T> {
9
8
  added: Array<T>;
10
9
  removed: Array<T>;
11
10
  }
12
- /** what changed on a record, only the fields that did */
13
11
  export type Changes<R, Field extends keyof R> = Partial<{
14
12
  [K in Field]: ValueChange<R[K]>;
15
13
  }>;
16
14
  export type TagCategoryName = "artist" | "character" | "contributor" | "copyright" | "general" | "invalid" | "lore" | "meta" | "species";
17
15
  export type PostFlagName = Extract<keyof LegacyPost["flags"], string>;
18
- /** what changed on a post, only the fields that did. tags are per category, so a category change shows up as a move */
16
+ /** Tags are split by category, so moving a tag between categories shows up as a remove & add. */
19
17
  export type PostChanges = Partial<Record<`tags.${TagCategoryName}`, SetChange<string>> & Record<`flags.${PostFlagName}`, ValueChange<boolean>> & {
20
18
  approver_id: ValueChange<number | null>;
21
19
  children: SetChange<number>;
@@ -28,3 +26,37 @@ export type PostChanges = Partial<Record<`tags.${TagCategoryName}`, SetChange<st
28
26
  rating: ValueChange<LegacyPost["rating"]>;
29
27
  sources: SetChange<string>;
30
28
  }>;
29
+ /** What was last known of a post, only `id` is guaranteed. */
30
+ export type PostSnapshot = Partial<{
31
+ approver_id: number | null;
32
+ change_seq: number;
33
+ children: Array<number>;
34
+ description: string;
35
+ flags: LegacyPost["flags"];
36
+ has_notes: boolean;
37
+ locked_tags: Array<string>;
38
+ md5: string;
39
+ parent_id: number | null;
40
+ pools: Array<number>;
41
+ rating: LegacyPost["rating"];
42
+ sources: Array<string>;
43
+ tags: Partial<Record<TagCategoryName, Array<string>>>;
44
+ } & Omit<PostStats, "changes" | "post_id">> & {
45
+ id: number;
46
+ };
47
+ export interface PostScore {
48
+ down: number;
49
+ total: number;
50
+ up: number;
51
+ }
52
+ export interface PostStats {
53
+ changes: Partial<{
54
+ comment_count: ValueChange<number>;
55
+ fav_count: ValueChange<number>;
56
+ score: ValueChange<PostScore>;
57
+ }>;
58
+ comment_count: number;
59
+ fav_count: number;
60
+ post_id: number;
61
+ score: PostScore;
62
+ }
package/dist/events.d.ts CHANGED
@@ -1,25 +1,21 @@
1
1
  import type { EventDataMap } from "./generated.ts";
2
- export declare const EVENT_TYPES: readonly ["artist.create", "artist.delete", "artist.update", "artist_url.create", "artist_version.create", "avoid_posting.create", "avoid_posting.delete", "avoid_posting.destroy", "avoid_posting.undelete", "avoid_posting.update", "avoid_posting_version.create", "ban.create", "ban.delete", "ban.update", "blip.create", "bulk_update_request.create", "bulk_update_request.update", "comment.create", "comment.delete", "comment.hide", "comment.unhide", "comment.update", "forum_post.create", "forum_post.delete", "forum_post.hide", "forum_post.unhide", "forum_post.update", "forum_topic.create", "forum_topic.delete", "forum_topic.hide", "forum_topic.unhide", "forum_topic.update", "help_page.create", "help_page.update", "mod_action.create", "news_update.create", "news_update.update", "note.create", "note.update", "note_version.create", "pool.add_posts", "pool.create", "pool.delete", "pool.remove_posts", "pool.update", "pool_version.create", "post.create", "post.update", "post_approval.create", "post_event.create", "post_flag.create", "post_flag.update", "post_replacement.create", "post_set.add_posts", "post_set.create", "post_set.delete", "post_set.remove_posts", "post_set.update", "post_version.create", "post_version.hide", "post_version.unhide", "tag.create", "tag.delete", "tag.update", "tag_alias.create", "tag_alias.update", "tag_implication.create", "tag_implication.update", "tag_type_version.create", "takedown.create", "takedown.delete", "takedown.update", "upload_karma_event.create", "user.create", "user.delete", "user.update", "user_feedback.create", "user_feedback.delete", "user_feedback.destroy", "user_feedback.undelete", "user_feedback.update", "wiki_page.create", "wiki_page.delete", "wiki_page.update", "wiki_page_version.create"];
2
+ export declare const EVENT_TYPES: readonly ["artist.create", "artist.delete", "artist.update", "artist_url.create", "artist_version.create", "avoid_posting.create", "avoid_posting.delete", "avoid_posting.destroy", "avoid_posting.undelete", "avoid_posting.update", "avoid_posting_version.create", "ban.create", "ban.delete", "ban.update", "blip.create", "bulk_update_request.create", "bulk_update_request.update", "comment.create", "comment.delete", "comment.hide", "comment.unhide", "comment.update", "forum_post.create", "forum_post.delete", "forum_post.hide", "forum_post.unhide", "forum_post.update", "forum_topic.create", "forum_topic.delete", "forum_topic.hide", "forum_topic.unhide", "forum_topic.update", "help_page.create", "help_page.update", "mod_action.create", "news_update.create", "news_update.update", "note.create", "note.update", "note_version.create", "pool.add_posts", "pool.create", "pool.delete", "pool.remove_posts", "pool.update", "pool_version.create", "post.create", "post.destroy", "post.stats", "post.update", "post_approval.create", "post_event.create", "post_flag.create", "post_flag.update", "post_replacement.create", "post_replacement.destroy", "post_replacement.update", "post_set.add_posts", "post_set.create", "post_set.delete", "post_set.remove_posts", "post_set.update", "post_version.create", "post_version.hide", "post_version.unhide", "tag.create", "tag.delete", "tag.update", "tag_alias.create", "tag_alias.update", "tag_implication.create", "tag_implication.update", "tag_type_version.create", "takedown.create", "takedown.delete", "takedown.update", "upload_karma_event.create", "user.create", "user.delete", "user.update", "user_feedback.create", "user_feedback.delete", "user_feedback.destroy", "user_feedback.undelete", "user_feedback.update", "wiki_page.create", "wiki_page.delete", "wiki_page.update", "wiki_page_version.create"];
3
3
  export type EventType = typeof EVENT_TYPES[number];
4
- /** polled with your own credentials and only sent to you, they have to be subscribed to by name */
5
- export declare const PRIVATE_EVENT_TYPES: readonly ["dmail.create"];
4
+ /** Polled with your own credentials, these need to be subscribed to by name. */
5
+ export declare const PRIVATE_EVENT_TYPES: readonly ["dmail.create", "private_post_set.add_posts", "private_post_set.remove_posts"];
6
6
  export type PrivateEventType = typeof PRIVATE_EVENT_TYPES[number];
7
- /** events whose data is the mod action they come from */
8
7
  export declare const MOD_ACTION_EVENT_TYPES: readonly ["artist.delete", "avoid_posting.delete", "avoid_posting.destroy", "avoid_posting.undelete", "ban.delete", "ban.update", "comment.delete", "comment.hide", "comment.unhide", "forum_post.delete", "forum_post.hide", "forum_post.unhide", "forum_topic.delete", "forum_topic.hide", "forum_topic.unhide", "pool.delete", "post_set.delete", "post_version.hide", "post_version.unhide", "tag.delete", "takedown.delete", "user.delete", "user.update", "user_feedback.delete", "user_feedback.destroy", "user_feedback.undelete", "user_feedback.update", "wiki_page.delete"];
9
- /** updates whose data is the version record they come from */
10
8
  export declare const VERSION_EVENT_TYPES: readonly ["artist.update", "avoid_posting.update", "note.update", "pool.update", "tag.update", "wiki_page.update"];
11
9
  export type ModActionEventType = typeof MOD_ACTION_EVENT_TYPES[number];
12
10
  export type VersionEventType = typeof VERSION_EVENT_TYPES[number];
13
- /** what an event type's `data` is, see https://e621.stream/events/ */
11
+ /** The data for each event type, see https://e621.stream/events/ */
14
12
  export type EventData<T extends EventType | PrivateEventType> = EventDataMap[T];
15
- /** one event from the stream, narrowed to its type's data by checking `type` */
16
13
  export type StreamEvent<T extends EventType | PrivateEventType = EventType | PrivateEventType> = T extends EventType | PrivateEventType ? {
17
14
  data: EventData<T>;
18
- /** the event's cursor, pass it as `cursor` to resume after it. private events have no cursor */
15
+ /** Pass this as `cursor` to resume after this event. Private events don't have one. */
19
16
  id: string;
20
- /** only for private events, which are polled with your own credentials and never stored */
21
17
  private?: true;
22
- /** when it happened on e621 */
18
+ /** When it happened on e621. */
23
19
  time: string;
24
20
  type: T;
25
21
  } : never;
@@ -28,12 +24,11 @@ export interface Filter {
28
24
  pool_ids?: Array<number>;
29
25
  post_ids?: Array<number>;
30
26
  set_ids?: Array<number>;
31
- /** e621 style tag query, supports `tag`, `-tag`, `~tag` and `rating:<s|q|e>` */
27
+ /** An e621 style tag query, supporting `tag`, `-tag`, `~tag` and `rating:`. */
32
28
  tags?: string;
33
29
  topic_ids?: Array<number>;
34
30
  user_ids?: Array<number>;
35
31
  }
36
- /** an event type, `<resource>.*`, `*`, or one of those with a filter */
37
32
  export type Subscription = string | {
38
33
  filter?: Filter;
39
34
  type: string;
@@ -51,4 +46,6 @@ export declare const CloseCodes: {
51
46
  readonly SLOW_CONSUMER: 4009;
52
47
  readonly TOO_MANY_CONNECTIONS: 4010;
53
48
  readonly AUTHENTICATION_EXPIRED: 4011;
49
+ readonly DISCONNECTED: 4012;
50
+ readonly BANNED: 4013;
54
51
  };
package/dist/events.js CHANGED
@@ -1,4 +1,4 @@
1
- // kept identical to the server's src/events.ts, the repository's tests check it
1
+ // keep in sync with src/events.ts
2
2
  export const EVENT_TYPES = [
3
3
  "artist.create",
4
4
  "artist.delete",
@@ -47,12 +47,16 @@ export const EVENT_TYPES = [
47
47
  "pool.update",
48
48
  "pool_version.create",
49
49
  "post.create",
50
+ "post.destroy",
51
+ "post.stats",
50
52
  "post.update",
51
53
  "post_approval.create",
52
54
  "post_event.create",
53
55
  "post_flag.create",
54
56
  "post_flag.update",
55
57
  "post_replacement.create",
58
+ "post_replacement.destroy",
59
+ "post_replacement.update",
56
60
  "post_set.add_posts",
57
61
  "post_set.create",
58
62
  "post_set.delete",
@@ -86,9 +90,12 @@ export const EVENT_TYPES = [
86
90
  "wiki_page.update",
87
91
  "wiki_page_version.create",
88
92
  ];
89
- /** polled with your own credentials and only sent to you, they have to be subscribed to by name */
90
- export const PRIVATE_EVENT_TYPES = ["dmail.create"];
91
- /** events whose data is the mod action they come from */
93
+ /** Polled with your own credentials, these need to be subscribed to by name. */
94
+ export const PRIVATE_EVENT_TYPES = [
95
+ "dmail.create",
96
+ "private_post_set.add_posts",
97
+ "private_post_set.remove_posts",
98
+ ];
92
99
  export const MOD_ACTION_EVENT_TYPES = [
93
100
  "artist.delete",
94
101
  "avoid_posting.delete",
@@ -119,8 +126,14 @@ export const MOD_ACTION_EVENT_TYPES = [
119
126
  "user_feedback.update",
120
127
  "wiki_page.delete",
121
128
  ];
122
- /** updates whose data is the version record they come from */
123
- export const VERSION_EVENT_TYPES = ["artist.update", "avoid_posting.update", "note.update", "pool.update", "tag.update", "wiki_page.update"];
129
+ export const VERSION_EVENT_TYPES = [
130
+ "artist.update",
131
+ "avoid_posting.update",
132
+ "note.update",
133
+ "pool.update",
134
+ "tag.update",
135
+ "wiki_page.update",
136
+ ];
124
137
  export const CloseCodes = {
125
138
  UNKNOWN_ERROR: 4000,
126
139
  UNKNOWN_OP: 4001,
@@ -134,5 +147,7 @@ export const CloseCodes = {
134
147
  SLOW_CONSUMER: 4009,
135
148
  TOO_MANY_CONNECTIONS: 4010,
136
149
  AUTHENTICATION_EXPIRED: 4011,
150
+ DISCONNECTED: 4012,
151
+ BANNED: 4013,
137
152
  };
138
153
  //# sourceMappingURL=events.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"events.js","sourceRoot":"","sources":["../lib/events.ts"],"names":[],"mappings":"AAEA,gFAAgF;AAEhF,MAAM,CAAC,MAAM,WAAW,GAAG;IACvB,eAAe;IACf,eAAe;IACf,eAAe;IACf,mBAAmB;IACnB,uBAAuB;IACvB,sBAAsB;IACtB,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,8BAA8B;IAC9B,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,aAAa;IACb,4BAA4B;IAC5B,4BAA4B;IAC5B,gBAAgB;IAChB,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,gBAAgB;IAChB,mBAAmB;IACnB,mBAAmB;IACnB,iBAAiB;IACjB,mBAAmB;IACnB,mBAAmB;IACnB,oBAAoB;IACpB,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;IACpB,oBAAoB;IACpB,kBAAkB;IAClB,kBAAkB;IAClB,mBAAmB;IACnB,oBAAoB;IACpB,oBAAoB;IACpB,aAAa;IACb,aAAa;IACb,qBAAqB;IACrB,gBAAgB;IAChB,aAAa;IACb,aAAa;IACb,mBAAmB;IACnB,aAAa;IACb,qBAAqB;IACrB,aAAa;IACb,aAAa;IACb,sBAAsB;IACtB,mBAAmB;IACnB,kBAAkB;IAClB,kBAAkB;IAClB,yBAAyB;IACzB,oBAAoB;IACpB,iBAAiB;IACjB,iBAAiB;IACjB,uBAAuB;IACvB,iBAAiB;IACjB,qBAAqB;IACrB,mBAAmB;IACnB,qBAAqB;IACrB,YAAY;IACZ,YAAY;IACZ,YAAY;IACZ,kBAAkB;IAClB,kBAAkB;IAClB,wBAAwB;IACxB,wBAAwB;IACxB,yBAAyB;IACzB,iBAAiB;IACjB,iBAAiB;IACjB,iBAAiB;IACjB,2BAA2B;IAC3B,aAAa;IACb,aAAa;IACb,aAAa;IACb,sBAAsB;IACtB,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,kBAAkB;IAClB,kBAAkB;IAClB,kBAAkB;IAClB,0BAA0B;CACpB,CAAC;AAIX,mGAAmG;AAEnG,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,cAAc,CAAU,CAAC;AAI7D,yDAAyD;AAEzD,MAAM,CAAC,MAAM,sBAAsB,GAAG;IAClC,eAAe;IACf,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB;IACxB,YAAY;IACZ,YAAY;IACZ,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,mBAAmB;IACnB,iBAAiB;IACjB,mBAAmB;IACnB,oBAAoB;IACpB,kBAAkB;IAClB,oBAAoB;IACpB,aAAa;IACb,iBAAiB;IACjB,mBAAmB;IACnB,qBAAqB;IACrB,YAAY;IACZ,iBAAiB;IACjB,aAAa;IACb,aAAa;IACb,sBAAsB;IACtB,uBAAuB;IACvB,wBAAwB;IACxB,sBAAsB;IACtB,kBAAkB;CACZ,CAAC;AAEX,8DAA8D;AAE9D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,eAAe,EAAE,sBAAsB,EAAE,aAAa,EAAE,aAAa,EAAE,YAAY,EAAE,kBAAkB,CAAU,CAAC;AAkCtJ,MAAM,CAAC,MAAM,UAAU,GAAG;IACtB,aAAa,EAAE,IAAI;IACnB,UAAU,EAAE,IAAI;IAChB,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,IAAI;IACpB,qBAAqB,EAAE,IAAI;IAC3B,kBAAkB,EAAE,IAAI;IACxB,oBAAoB,EAAE,IAAI;IAC1B,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE,IAAI;IAClB,aAAa,EAAE,IAAI;IACnB,oBAAoB,EAAE,IAAI;IAC1B,sBAAsB,EAAE,IAAI;CACtB,CAAC"}
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../lib/events.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import type { Changes, PostChanges } from "./changes.ts";
1
+ import type { Changes, PostChanges, PostSnapshot, PostStats } from "./changes.ts";
2
2
  export type PoolCategory = 'collection' | 'series';
3
3
  export type PostEventAction = 'deleted' | 'undeleted' | 'approved' | 'unapproved' | 'flag_created' | 'flag_removed' | 'favorites_moved' | 'favorites_received' | 'rating_locked' | 'rating_unlocked' | 'status_locked' | 'status_unlocked' | 'note_locked' | 'note_unlocked' | 'comment_locked' | 'comment_unlocked' | 'replacement_accepted' | 'replacement_rejected' | 'replacement_promoted' | 'replacement_deleted' | 'expunged' | 'changed_bg_color' | 'replacement_penalty_changed' | 'owner_changed' | 'replacement_moved';
4
4
  export type PostReplacementStatus = 'promoted' | 'approved' | 'rejected' | 'pending' | 'original';
@@ -1084,21 +1084,21 @@ export interface ModActionValues {
1084
1084
  };
1085
1085
  }
1086
1086
  export type ModActionName = keyof ModActionValues;
1087
- /** one variant per action, so checking `action` narrows `values` */
1087
+ /** Checking `action` narrows `values`. */
1088
1088
  export type ModAction<A extends ModActionName = ModActionName> = A extends ModActionName ? {
1089
1089
  action: A;
1090
1090
  created_at: string;
1091
1091
  creator_id: number;
1092
1092
  id: number;
1093
1093
  updated_at: string;
1094
- /** what the action applies to */
1094
+ /** What the action applies to. */
1095
1095
  values: ModActionValues[A];
1096
1096
  } : never;
1097
- /** a record wrapped under its resource name with what changed, `changes` is null when its previous state isn't known */
1097
+ /** `changes` is null when the previous state isn't known. */
1098
1098
  export type Update<Resource extends string, R, Field extends keyof R & string> = Record<Resource, R> & {
1099
1099
  changes: Changes<R, Field> | null;
1100
1100
  };
1101
- /** what each event type's `data` is */
1101
+ /** The `data` each event type is sent with. */
1102
1102
  export interface EventDataMap {
1103
1103
  "artist.create": Artist;
1104
1104
  "artist.delete": ModAction<"artist_delete">;
@@ -1155,6 +1155,11 @@ export interface EventDataMap {
1155
1155
  "post.create": {
1156
1156
  post: LegacyPost;
1157
1157
  };
1158
+ "post.destroy": {
1159
+ post: PostSnapshot;
1160
+ post_event: PostEvent;
1161
+ };
1162
+ "post.stats": PostStats;
1158
1163
  "post.update": {
1159
1164
  changes: PostChanges | null;
1160
1165
  post: LegacyPost;
@@ -1164,6 +1169,11 @@ export interface EventDataMap {
1164
1169
  "post_flag.create": PostFlag;
1165
1170
  "post_flag.update": Update<"post_flag", PostFlag, "is_resolved">;
1166
1171
  "post_replacement.create": PostReplacement;
1172
+ "post_replacement.destroy": {
1173
+ post_event: PostEvent;
1174
+ post_replacement: Pick<PostReplacement, "id" | "status" | "approver_id" | "reason" | "post_id">;
1175
+ };
1176
+ "post_replacement.update": Update<"post_replacement", PostReplacement, "status" | "approver_id" | "reason" | "post_id">;
1167
1177
  "post_set.add_posts": Record<"post_set", PostSet> & {
1168
1178
  post_ids: Array<number>;
1169
1179
  };
@@ -1201,4 +1211,12 @@ export interface EventDataMap {
1201
1211
  "wiki_page.update": WikiPageVersion;
1202
1212
  "wiki_page_version.create": WikiPageVersion;
1203
1213
  "dmail.create": DMail;
1214
+ "private_post_set.add_posts": {
1215
+ post_ids: Array<number>;
1216
+ post_set: PostSet;
1217
+ };
1218
+ "private_post_set.remove_posts": {
1219
+ post_ids: Array<number>;
1220
+ post_set: PostSet;
1221
+ };
1204
1222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "e621stream",
3
- "version": "0.0.0",
3
+ "version": "0.0.3",
4
4
  "description": "A client for E621Stream, a live WebSocket stream of e621 activity",
5
5
  "license": "MIT",
6
6
  "author": "Donovan_DMC <hewwo@yiff.rocks>",