e621stream 0.0.0 → 0.0.2

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,19 @@ 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 }` |
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 | `wss://e621.stream/ws` | |
42
+ | `WebSocket` | WebSocket | global | for older node, the `ws` package works |
43
+
44
+ Private events like `dmail.create` have to be subscribed to by name.
45
+
46
+ 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,24 @@
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. */
5
5
  auth?: {
6
6
  apiKey: string;
7
7
  username: string;
8
8
  };
9
- /** a name for your client, shown in the server's logs */
9
+ /** Shown in the server's logs. */
10
10
  client?: string;
11
- /** an event id (or a millisecond timestamp) to replay from. after that, reconnecting resumes from the last event */
11
+ /** An event id or millisecond timestamp to replay from. */
12
12
  cursor?: number | string;
13
- /** reconnects with backoff when the connection drops, unless the server closed it for something retrying won't fix */
13
+ /** Reconnect when the connection drops. */
14
14
  reconnect?: boolean;
15
15
  subscriptions: Array<Subscription>;
16
16
  url?: string;
17
- /** for runtimes without a global WebSocket, like node before 22 (the `ws` package works) */
17
+ /** For runtimes without a global WebSocket (node < 22), the `ws` package works. */
18
18
  WebSocket?: typeof WebSocket;
19
19
  }
20
20
  export interface Ready {
21
- /** when replaying, set if the cursor was older than anything still kept */
21
+ /** If the cursor was older than anything still kept. */
22
22
  cursor_expired?: boolean;
23
23
  replaying: boolean;
24
24
  session_id: string;
@@ -36,7 +36,7 @@ export interface ClientEvents {
36
36
  reason: string;
37
37
  reconnecting: boolean;
38
38
  }];
39
- /** every event, public or private */
39
+ /** Every event, public or private. */
40
40
  dispatch: [StreamEvent];
41
41
  error: [Error];
42
42
  ready: [Ready];
@@ -44,7 +44,6 @@ export interface ClientEvents {
44
44
  attempt: number;
45
45
  delayMS: number;
46
46
  }];
47
- /** replay is done, live events follow */
48
47
  replayComplete: [{
49
48
  cursor: string | null;
50
49
  events: number;
@@ -59,8 +58,8 @@ export declare class StreamError extends Error {
59
58
  constructor(code: number, message: string);
60
59
  }
61
60
  /**
62
- * a connection to E621Stream, see https://e621.stream
63
- *
61
+ * A connection to E621Stream, see https://e621.stream
62
+ * @example
64
63
  * ```ts
65
64
  * const stream = new E621Stream({ auth: { username, apiKey }, subscriptions: ["post.create"] });
66
65
  * stream.on("post.create", event => console.log(event.data.post.id));
@@ -72,10 +71,9 @@ export declare class E621Stream extends Emitter<Listeners> {
72
71
  private closing;
73
72
  private heartbeat;
74
73
  private lastError;
75
- private lastMessage;
74
+ private lastHeartbeatAck;
76
75
  private reconnectTimer;
77
76
  private socket;
78
- /** the newest event received, which reconnecting resumes from */
79
77
  cursor: string | null;
80
78
  readonly options: Options & {
81
79
  url: string;
@@ -86,10 +84,10 @@ export declare class E621Stream extends Emitter<Listeners> {
86
84
  private send;
87
85
  private startHeartbeat;
88
86
  private stopHeartbeat;
89
- /** closes the connection for good */
87
+ /** Close the connection. */
90
88
  close(): void;
91
89
  connect(): this;
92
- /** replaces the current subscriptions, and keeps them for reconnecting */
90
+ /** Replace the current subscriptions. */
93
91
  subscribe(subscriptions: Array<Subscription>): void;
94
92
  }
95
93
  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));
@@ -36,10 +35,9 @@ export class E621Stream extends Emitter {
36
35
  closing = false;
37
36
  heartbeat = null;
38
37
  lastError = null;
39
- lastMessage = 0;
38
+ lastHeartbeatAck = true;
40
39
  reconnectTimer = null;
41
40
  socket = null;
42
- /** the newest event received, which reconnecting resumes from */
43
41
  cursor;
44
42
  options;
45
43
  constructor(options) {
@@ -49,10 +47,9 @@ export class E621Stream extends Emitter {
49
47
  }
50
48
  handle(raw) {
51
49
  if (typeof raw !== "string") {
52
- this.emit("error", new Error("got a binary message, compression isn't supported by this client"));
50
+ this.emit("error", new Error("compression isn't supported"));
53
51
  return;
54
52
  }
55
- this.lastMessage = Date.now();
56
53
  const message = JSON.parse(raw);
57
54
  switch (message.op) {
58
55
  case "hello": {
@@ -75,11 +72,10 @@ export class E621Stream extends Emitter {
75
72
  }
76
73
  case "dispatch": {
77
74
  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
75
  if (!event.private)
80
76
  this.cursor = event.id;
81
77
  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
78
+ // typescript can't narrow this
83
79
  this.emitUnchecked(event.type, event);
84
80
  break;
85
81
  }
@@ -91,6 +87,10 @@ export class E621Stream extends Emitter {
91
87
  this.emit("subscribed", message.d.subscriptions);
92
88
  break;
93
89
  }
90
+ case "heartbeat_ack": {
91
+ this.lastHeartbeatAck = true;
92
+ break;
93
+ }
94
94
  case "error": {
95
95
  const { code, message: text } = message.d;
96
96
  this.lastError = new StreamError(code, text);
@@ -110,7 +110,6 @@ export class E621Stream extends Emitter {
110
110
  if (!reconnecting)
111
111
  return;
112
112
  this.attempt++;
113
- // a server that's rate limiting this connection wants a longer break
114
113
  const base = code === CloseCodes.RATE_LIMITED ? 30_000 : 1000;
115
114
  const delayMS = Math.min(MAX_DELAY_MS, base * 2 ** (this.attempt - 1)) * (0.75 + Math.random() * 0.5);
116
115
  this.emit("reconnecting", { attempt: this.attempt, delayMS: Math.round(delayMS) });
@@ -124,13 +123,13 @@ export class E621Stream extends Emitter {
124
123
  this.socket.send(JSON.stringify(payload));
125
124
  }
126
125
  startHeartbeat() {
127
- this.lastMessage = Date.now();
126
+ this.lastHeartbeatAck = true;
128
127
  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");
128
+ if (!this.lastHeartbeatAck) {
129
+ this.socket?.close(4999, "heartbeat not acknowledged");
132
130
  return;
133
131
  }
132
+ this.lastHeartbeatAck = false;
134
133
  this.send({ op: "heartbeat" });
135
134
  }, HEARTBEAT_MS);
136
135
  }
@@ -139,7 +138,7 @@ export class E621Stream extends Emitter {
139
138
  clearInterval(this.heartbeat);
140
139
  this.heartbeat = null;
141
140
  }
142
- /** closes the connection for good */
141
+ /** Close the connection. */
143
142
  close() {
144
143
  this.closing = true;
145
144
  if (this.reconnectTimer)
@@ -151,11 +150,11 @@ export class E621Stream extends Emitter {
151
150
  if (this.socket)
152
151
  return this;
153
152
  this.closing = false;
154
- // the dom types say it's always there, node before 22 doesn't have it
153
+ // not present before node 22
155
154
  const global = globalThis.WebSocket;
156
155
  const Socket = this.options.WebSocket ?? global;
157
156
  if (!Socket)
158
- throw new Error("there's no global WebSocket here, pass one as the WebSocket option");
157
+ throw new Error("no WebSocket available, pass one with the WebSocket option");
159
158
  const socket = this.socket = new Socket(this.options.url);
160
159
  socket.addEventListener("open", () => { this.startHeartbeat(); });
161
160
  socket.addEventListener("message", (event) => {
@@ -167,11 +166,10 @@ export class E621Stream extends Emitter {
167
166
  }
168
167
  });
169
168
  socket.addEventListener("close", (event) => { this.onClose(event.code, event.reason); });
170
- // the close event that follows has the details
171
169
  socket.addEventListener("error", () => null);
172
170
  return this;
173
171
  }
174
- /** replaces the current subscriptions, and keeps them for reconnecting */
172
+ /** Replace the current subscriptions. */
175
173
  subscribe(subscriptions) {
176
174
  this.options.subscriptions = subscriptions;
177
175
  this.send({ op: "subscribe", d: { subscriptions } });
@@ -1 +1 @@
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;AAwCrH,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,gEAAgE;AAChE,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;CACpC,CAAC,CAAC;AACH,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,MAAM,YAAY,GAAG,MAAM,CAAC;AAC5B,oHAAoH;AACpH,MAAM,SAAS,GAAG,MAAM,CAAC;AAEzB;;;;;;;;GAQG;AACH,MAAM,OAAO,UAAW,SAAQ,OAAkB;IACtC,OAAO,GAAG,CAAC,CAAC;IACZ,OAAO,GAAG,KAAK,CAAC;IAChB,SAAS,GAA0C,IAAI,CAAC;IACxD,SAAS,GAAuB,IAAI,CAAC;IACrC,WAAW,GAAG,CAAC,CAAC;IAChB,cAAc,GAAyC,IAAI,CAAC;IAC5D,MAAM,GAAqB,IAAI,CAAC;IACxC,iEAAiE;IACjE,MAAM,CAAgB;IACb,OAAO,CAA4B;IAE5C,YAAY,OAAgB;QACxB,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,EAAE,sBAAsB,EAAE,GAAG,OAAO,EAAE,CAAC;QAC5E,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,kEAAkE,CAAC,CAAC,CAAC;YAClG,OAAO;QACX,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,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,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;wBAC5E,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,qEAAqE;gBACrE,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,kGAAkG;gBAClG,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,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,qEAAqE;QACrE,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,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,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAC9B,IAAI,CAAC,SAAS,GAAG,WAAW,CAAC,GAAG,EAAE;YAC9B,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,WAAW,GAAG,SAAS,EAAE,CAAC;gBAC5C,0DAA0D;gBAC1D,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,EAAE,6BAA6B,CAAC,CAAC;gBACxD,OAAO;YACX,CAAC;YACD,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;IACrC,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;YAAE,OAAO,IAAI,CAAC;QAC7B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC;QACrB,sEAAsE;QACtE,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,oEAAoE,CAAC,CAAC;QACnG,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1D,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,+CAA+C;QAC/C,MAAM,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC;IAChB,CAAC;IAED,0EAA0E;IAC1E,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"}
1
+ {"version":3,"file":"E621Stream.js","sourceRoot":"","sources":["../lib/E621Stream.ts"],"names":[],"mappings":"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"}
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.2",
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>",