mixi2-js 1.2.1 → 1.3.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/README.md +16 -13
- package/dist/client-C90Zd_yq.d.cts +303 -0
- package/dist/client-DPeVTCYr.d.mts +303 -0
- package/dist/helpers/index.cjs +305 -207
- package/dist/helpers/index.d.cts +150 -65
- package/dist/helpers/index.d.mts +207 -0
- package/dist/helpers/index.mjs +304 -0
- package/dist/index.cjs +542 -750
- package/dist/index.d.cts +41 -37
- package/dist/index.d.mts +50 -0
- package/dist/index.mjs +559 -0
- package/dist/types-BrJ83qtL.mjs +92 -0
- package/dist/types-D9t_NdQ0.cjs +175 -0
- package/package.json +43 -51
- package/dist/chunk-4NKIICB5.js +0 -107
- package/dist/client-iXbbRxc-.d.cts +0 -296
- package/dist/client-iXbbRxc-.d.ts +0 -296
- package/dist/helpers/index.d.ts +0 -122
- package/dist/helpers/index.js +0 -186
- package/dist/index.d.ts +0 -46
- package/dist/index.js +0 -680
package/dist/helpers/index.cjs
CHANGED
|
@@ -1,217 +1,315 @@
|
|
|
1
|
-
"
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_types = require("../types-D9t_NdQ0.cjs");
|
|
3
|
+
//#region src/helpers/address.ts
|
|
4
|
+
/**
|
|
5
|
+
* アクセストークン取得用のエンドポイント URL です。
|
|
6
|
+
*/
|
|
7
|
+
const tokenUrl = "https://application-auth.mixi.social/oauth2/token";
|
|
8
|
+
/**
|
|
9
|
+
* API サーバーアドレスです。
|
|
10
|
+
*/
|
|
11
|
+
const apiAddress = "application-api.mixi.social";
|
|
12
|
+
/**
|
|
13
|
+
* gRPC ストリーミング接続用のサーバーアドレスです。
|
|
14
|
+
*/
|
|
15
|
+
const streamAddress = "application-stream.mixi.social";
|
|
16
|
+
//#endregion
|
|
17
|
+
//#region src/helpers/event-deduplicator.ts
|
|
18
|
+
/**
|
|
19
|
+
* 重複したイベントを検出してスキップするミドルウェア。
|
|
20
|
+
* Webhook 方式のリトライなどで同じイベントが複数回届いた場合に、
|
|
21
|
+
* 内部ハンドラへの二重処理を防ぐ。
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* const dedup = new EventDeduplicator(innerHandler);
|
|
25
|
+
* const server = new WebhookServer({ handler: dedup, ... });
|
|
26
|
+
*/
|
|
27
|
+
var EventDeduplicator = class {
|
|
28
|
+
inner;
|
|
29
|
+
maxSize;
|
|
30
|
+
maxAge;
|
|
31
|
+
seen = /* @__PURE__ */ new Map();
|
|
32
|
+
constructor(handler, options) {
|
|
33
|
+
this.inner = handler;
|
|
34
|
+
this.maxSize = options?.maxSize ?? 1e3;
|
|
35
|
+
this.maxAge = options?.maxAge ?? 3e5;
|
|
36
|
+
}
|
|
37
|
+
async handle(event) {
|
|
38
|
+
const now = Date.now();
|
|
39
|
+
this.evict(now);
|
|
40
|
+
if (this.seen.has(event.eventId)) return;
|
|
41
|
+
this.seen.set(event.eventId, now);
|
|
42
|
+
if (this.seen.size > this.maxSize) {
|
|
43
|
+
const oldest = this.seen.keys().next().value;
|
|
44
|
+
if (oldest !== void 0) this.seen.delete(oldest);
|
|
45
|
+
}
|
|
46
|
+
await this.inner.handle(event);
|
|
47
|
+
}
|
|
48
|
+
evict(now) {
|
|
49
|
+
for (const [id, ts] of this.seen) if (now - ts > this.maxAge) this.seen.delete(id);
|
|
50
|
+
else break;
|
|
51
|
+
}
|
|
9
52
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
53
|
+
//#endregion
|
|
54
|
+
//#region src/helpers/event-logger.ts
|
|
55
|
+
/**
|
|
56
|
+
* 受信したイベントをログ出力するデバッグ用ミドルウェア。
|
|
57
|
+
* 内部ハンドラへの処理はそのまま委譲する。
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* const logger = new EventLogger(router);
|
|
61
|
+
* await watcher.watch(logger);
|
|
62
|
+
*/
|
|
63
|
+
var EventLogger = class {
|
|
64
|
+
inner;
|
|
65
|
+
logger;
|
|
66
|
+
verbose;
|
|
67
|
+
constructor(handler, options) {
|
|
68
|
+
this.inner = handler;
|
|
69
|
+
this.logger = options?.logger ?? console.log;
|
|
70
|
+
this.verbose = options?.verbose ?? true;
|
|
71
|
+
}
|
|
72
|
+
async handle(event) {
|
|
73
|
+
if (this.verbose) this.logger(`[mixi2] event received: type=${event.eventType} id=${event.eventId}`);
|
|
74
|
+
else this.logger(`[mixi2] event received: type=${event.eventType}`);
|
|
75
|
+
await this.inner.handle(event);
|
|
76
|
+
}
|
|
17
77
|
};
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
MediaUploader: () => MediaUploader,
|
|
25
|
-
PostBuilder: () => PostBuilder,
|
|
26
|
-
ReasonFilter: () => ReasonFilter,
|
|
27
|
-
apiAddress: () => apiAddress,
|
|
28
|
-
streamAddress: () => streamAddress,
|
|
29
|
-
tokenUrl: () => tokenUrl
|
|
30
|
-
});
|
|
31
|
-
module.exports = __toCommonJS(helpers_exports);
|
|
32
|
-
|
|
33
|
-
// src/helpers/address.ts
|
|
34
|
-
var tokenUrl = "https://application-auth.mixi.social/oauth2/token";
|
|
35
|
-
var apiAddress = "application-api.mixi.social";
|
|
36
|
-
var streamAddress = "application-stream.mixi.social";
|
|
37
|
-
|
|
38
|
-
// src/helpers/event-router.ts
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/helpers/event-router.ts
|
|
80
|
+
/**
|
|
81
|
+
* イベントタイプ別にハンドラを登録できる EventHandler 実装。
|
|
82
|
+
* StreamWatcher.watch() や WebhookServer に直接渡して使用できる。
|
|
83
|
+
*/
|
|
39
84
|
var EventRouter = class {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
*/
|
|
78
|
-
async handle(event) {
|
|
79
|
-
const listeners = this.listeners.get(event.eventType);
|
|
80
|
-
if (!listeners) return;
|
|
81
|
-
for (const listener of listeners) {
|
|
82
|
-
await listener(event);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
+
listeners = /* @__PURE__ */ new Map();
|
|
86
|
+
/**
|
|
87
|
+
* 指定したイベントタイプのハンドラを登録する。
|
|
88
|
+
* 同じイベントタイプに複数のハンドラを登録可能(登録順に実行)。
|
|
89
|
+
*/
|
|
90
|
+
on(eventType, listener) {
|
|
91
|
+
const existing = this.listeners.get(eventType);
|
|
92
|
+
if (existing) existing.push(listener);
|
|
93
|
+
else this.listeners.set(eventType, [listener]);
|
|
94
|
+
return this;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* 指定したイベントタイプのハンドラを削除する。
|
|
98
|
+
* listener を省略した場合、そのイベントタイプのすべてのハンドラを削除する。
|
|
99
|
+
*/
|
|
100
|
+
off(eventType, listener) {
|
|
101
|
+
if (!listener) {
|
|
102
|
+
this.listeners.delete(eventType);
|
|
103
|
+
return this;
|
|
104
|
+
}
|
|
105
|
+
const existing = this.listeners.get(eventType);
|
|
106
|
+
if (existing) {
|
|
107
|
+
const filtered = existing.filter((l) => l !== listener);
|
|
108
|
+
if (filtered.length > 0) this.listeners.set(eventType, filtered);
|
|
109
|
+
else this.listeners.delete(eventType);
|
|
110
|
+
}
|
|
111
|
+
return this;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* EventHandler.handle() の実装。
|
|
115
|
+
* 登録されたリスナーに対してイベントをルーティングする。
|
|
116
|
+
*/
|
|
117
|
+
async handle(event) {
|
|
118
|
+
const listeners = this.listeners.get(event.eventType);
|
|
119
|
+
if (!listeners) return;
|
|
120
|
+
for (const listener of listeners) await listener(event);
|
|
121
|
+
}
|
|
85
122
|
};
|
|
86
|
-
|
|
87
|
-
|
|
123
|
+
//#endregion
|
|
124
|
+
//#region src/helpers/media-uploader.ts
|
|
125
|
+
/**
|
|
126
|
+
* メディアアップロードの開始 → データ送信 → 処理完了待機を簡略化するヘルパー。
|
|
127
|
+
*
|
|
128
|
+
* 通常は initiatePostMediaUpload → HTTP POST → getPostMediaStatus のポーリングが必要だが、
|
|
129
|
+
* このクラスで waitForReady() を呼ぶだけで完了まで待機できる。
|
|
130
|
+
*/
|
|
88
131
|
var MediaUploader = class {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
await new Promise((resolve) => setTimeout(resolve, this.pollInterval));
|
|
122
|
-
}
|
|
123
|
-
throw new Error(
|
|
124
|
-
`Media upload timed out after ${this.timeout}ms: ${mediaId}`
|
|
125
|
-
);
|
|
126
|
-
}
|
|
132
|
+
client;
|
|
133
|
+
pollInterval;
|
|
134
|
+
timeout;
|
|
135
|
+
constructor(client, options) {
|
|
136
|
+
this.client = client;
|
|
137
|
+
this.pollInterval = options?.pollInterval ?? 1e3;
|
|
138
|
+
this.timeout = options?.timeout ?? 6e4;
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* メディアアップロードを開始し、uploadUrl と mediaId を返す。
|
|
142
|
+
*/
|
|
143
|
+
async initiate(request) {
|
|
144
|
+
const response = await this.client.initiatePostMediaUpload(request);
|
|
145
|
+
return {
|
|
146
|
+
mediaId: response.mediaId,
|
|
147
|
+
uploadUrl: response.uploadUrl
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* メディアの処理が完了するまでポーリングして待機する。
|
|
152
|
+
* 完了時に mediaId を返す。失敗時はエラーをスローする。
|
|
153
|
+
*/
|
|
154
|
+
async waitForReady(mediaId) {
|
|
155
|
+
const startTime = Date.now();
|
|
156
|
+
while (Date.now() - startTime < this.timeout) {
|
|
157
|
+
const status = await this.client.getPostMediaStatus(mediaId);
|
|
158
|
+
if (status.status === require_types.MediaUploadStatus.COMPLETED) return mediaId;
|
|
159
|
+
if (status.status === require_types.MediaUploadStatus.FAILED) throw new Error(`Media upload failed: ${mediaId}`);
|
|
160
|
+
await new Promise((resolve) => setTimeout(resolve, this.pollInterval));
|
|
161
|
+
}
|
|
162
|
+
throw new Error(`Media upload timed out after ${this.timeout}ms: ${mediaId}`);
|
|
163
|
+
}
|
|
127
164
|
};
|
|
128
|
-
|
|
129
|
-
|
|
165
|
+
//#endregion
|
|
166
|
+
//#region src/helpers/post-builder.ts
|
|
167
|
+
/**
|
|
168
|
+
* ポスト作成リクエストをメソッドチェーンで組み立てるビルダー。
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* const request = new PostBuilder('Hello mixi2!')
|
|
172
|
+
* .reply('post-id')
|
|
173
|
+
* .media(['media-id-1'])
|
|
174
|
+
* .sensitive()
|
|
175
|
+
* .build();
|
|
176
|
+
*/
|
|
130
177
|
var PostBuilder = class {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
178
|
+
request;
|
|
179
|
+
constructor(text) {
|
|
180
|
+
this.request = { text };
|
|
181
|
+
}
|
|
182
|
+
/** 返信先ポスト ID を設定する。 */
|
|
183
|
+
reply(postId) {
|
|
184
|
+
this.request.inReplyToPostId = postId;
|
|
185
|
+
this.request.quotedPostId = void 0;
|
|
186
|
+
return this;
|
|
187
|
+
}
|
|
188
|
+
/** 引用対象ポスト ID を設定する。 */
|
|
189
|
+
quote(postId) {
|
|
190
|
+
this.request.quotedPostId = postId;
|
|
191
|
+
this.request.inReplyToPostId = void 0;
|
|
192
|
+
return this;
|
|
193
|
+
}
|
|
194
|
+
/** 添付メディア ID を設定する(最大 4 件)。 */
|
|
195
|
+
media(mediaIdList) {
|
|
196
|
+
this.request.mediaIdList = mediaIdList;
|
|
197
|
+
return this;
|
|
198
|
+
}
|
|
199
|
+
/** センシティブマスクを設定する。 */
|
|
200
|
+
sensitive(caption = "") {
|
|
201
|
+
this.request.postMask = {
|
|
202
|
+
maskType: require_types.PostMaskType.SENSITIVE,
|
|
203
|
+
caption
|
|
204
|
+
};
|
|
205
|
+
return this;
|
|
206
|
+
}
|
|
207
|
+
/** ネタバレマスクを設定する。 */
|
|
208
|
+
spoiler(caption = "") {
|
|
209
|
+
this.request.postMask = {
|
|
210
|
+
maskType: require_types.PostMaskType.SPOILER,
|
|
211
|
+
caption
|
|
212
|
+
};
|
|
213
|
+
return this;
|
|
214
|
+
}
|
|
215
|
+
/** カスタムマスクを設定する。 */
|
|
216
|
+
mask(postMask) {
|
|
217
|
+
this.request.postMask = postMask;
|
|
218
|
+
return this;
|
|
219
|
+
}
|
|
220
|
+
/** 配信設定を設定する。 */
|
|
221
|
+
publishing(type) {
|
|
222
|
+
this.request.publishingType = type;
|
|
223
|
+
return this;
|
|
224
|
+
}
|
|
225
|
+
/** CreatePostRequest オブジェクトを構築する。 */
|
|
226
|
+
build() {
|
|
227
|
+
return { ...this.request };
|
|
228
|
+
}
|
|
182
229
|
};
|
|
183
|
-
|
|
184
|
-
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/helpers/reason-filter.ts
|
|
232
|
+
/**
|
|
233
|
+
* EventReason に基づいてイベントをフィルタリングするミドルウェア。
|
|
234
|
+
* 指定した理由に一致するイベントのみを内部のハンドラに渡す。
|
|
235
|
+
*
|
|
236
|
+
* @example
|
|
237
|
+
* const filter = new ReasonFilter(innerHandler, [
|
|
238
|
+
* EventReason.POST_REPLY,
|
|
239
|
+
* EventReason.POST_MENTIONED,
|
|
240
|
+
* ]);
|
|
241
|
+
* await watcher.watch(filter);
|
|
242
|
+
*/
|
|
185
243
|
var ReasonFilter = class {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
}
|
|
202
|
-
if (event.chatMessageReceivedEvent) {
|
|
203
|
-
return event.chatMessageReceivedEvent.eventReasonList || [];
|
|
204
|
-
}
|
|
205
|
-
return [];
|
|
206
|
-
}
|
|
244
|
+
inner;
|
|
245
|
+
allowedReasons;
|
|
246
|
+
constructor(handler, reasons) {
|
|
247
|
+
this.inner = handler;
|
|
248
|
+
this.allowedReasons = new Set(reasons);
|
|
249
|
+
}
|
|
250
|
+
async handle(event) {
|
|
251
|
+
const reasons = this.getReasons(event);
|
|
252
|
+
if (reasons.length === 0 || reasons.some((r) => this.allowedReasons.has(r))) await this.inner.handle(event);
|
|
253
|
+
}
|
|
254
|
+
getReasons(event) {
|
|
255
|
+
if (event.postCreatedEvent) return event.postCreatedEvent.eventReasonList || [];
|
|
256
|
+
if (event.chatMessageReceivedEvent) return event.chatMessageReceivedEvent.eventReasonList || [];
|
|
257
|
+
return [];
|
|
258
|
+
}
|
|
207
259
|
};
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
260
|
+
//#endregion
|
|
261
|
+
//#region src/helpers/text-splitter.ts
|
|
262
|
+
/** mixi2 の 1 ポストあたりの最大文字数 */
|
|
263
|
+
const maxPostLength = 149;
|
|
264
|
+
/**
|
|
265
|
+
* 長いテキストを mixi2 の文字数制限内に収まる複数チャンクに分割するヘルパー。
|
|
266
|
+
* デフォルトは 149 文字制限(mixi2 のポスト本文上限)に準拠。
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* const splitter = new TextSplitter();
|
|
270
|
+
* const chunks = splitter.split('長いテキスト...');
|
|
271
|
+
* for (const chunk of chunks) {
|
|
272
|
+
* await client.createPost({ text: chunk });
|
|
273
|
+
* }
|
|
274
|
+
*/
|
|
275
|
+
var TextSplitter = class {
|
|
276
|
+
maxLength;
|
|
277
|
+
splitOnWord;
|
|
278
|
+
constructor(options) {
|
|
279
|
+
this.maxLength = options?.maxLength ?? 149;
|
|
280
|
+
this.splitOnWord = options?.splitOnWord ?? true;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* テキストを maxLength 以内の複数チャンクに分割して返す。
|
|
284
|
+
* テキストが maxLength 以内の場合は 1 要素の配列を返す。
|
|
285
|
+
*/
|
|
286
|
+
split(text) {
|
|
287
|
+
if (text.length <= this.maxLength) return [text];
|
|
288
|
+
const chunks = [];
|
|
289
|
+
let remaining = text;
|
|
290
|
+
while (remaining.length > this.maxLength) {
|
|
291
|
+
let splitAt = this.maxLength;
|
|
292
|
+
if (this.splitOnWord) {
|
|
293
|
+
const candidate = remaining.slice(0, this.maxLength);
|
|
294
|
+
const lastBreak = Math.max(candidate.lastIndexOf(" "), candidate.lastIndexOf(" "), candidate.lastIndexOf("、"), candidate.lastIndexOf("。"), candidate.lastIndexOf("!"), candidate.lastIndexOf("?"), candidate.lastIndexOf("!"), candidate.lastIndexOf("?"), candidate.lastIndexOf("\n"));
|
|
295
|
+
if (lastBreak > 0) splitAt = lastBreak + 1;
|
|
296
|
+
}
|
|
297
|
+
chunks.push(remaining.slice(0, splitAt).trimEnd());
|
|
298
|
+
remaining = remaining.slice(splitAt).trimStart();
|
|
299
|
+
}
|
|
300
|
+
if (remaining.length > 0) chunks.push(remaining);
|
|
301
|
+
return chunks;
|
|
302
|
+
}
|
|
303
|
+
};
|
|
304
|
+
//#endregion
|
|
305
|
+
exports.EventDeduplicator = EventDeduplicator;
|
|
306
|
+
exports.EventLogger = EventLogger;
|
|
307
|
+
exports.EventRouter = EventRouter;
|
|
308
|
+
exports.MediaUploader = MediaUploader;
|
|
309
|
+
exports.PostBuilder = PostBuilder;
|
|
310
|
+
exports.ReasonFilter = ReasonFilter;
|
|
311
|
+
exports.TextSplitter = TextSplitter;
|
|
312
|
+
exports.apiAddress = apiAddress;
|
|
313
|
+
exports.maxPostLength = maxPostLength;
|
|
314
|
+
exports.streamAddress = streamAddress;
|
|
315
|
+
exports.tokenUrl = tokenUrl;
|