@krischoichoi/channel-weixin 0.6.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 +101 -0
- package/lib/adapter.d.ts +90 -0
- package/lib/adapter.d.ts.map +1 -0
- package/lib/adapter.js +247 -0
- package/lib/adapter.js.map +1 -0
- package/lib/auth/account-store.d.ts +60 -0
- package/lib/auth/account-store.d.ts.map +1 -0
- package/lib/auth/account-store.js +84 -0
- package/lib/auth/account-store.js.map +1 -0
- package/lib/auth/login.d.ts +83 -0
- package/lib/auth/login.d.ts.map +1 -0
- package/lib/auth/login.js +202 -0
- package/lib/auth/login.js.map +1 -0
- package/lib/config.d.ts +52 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +36 -0
- package/lib/config.js.map +1 -0
- package/lib/definition.d.ts +59 -0
- package/lib/definition.d.ts.map +1 -0
- package/lib/definition.js +146 -0
- package/lib/definition.js.map +1 -0
- package/lib/ilink/base-info.d.ts +22 -0
- package/lib/ilink/base-info.d.ts.map +1 -0
- package/lib/ilink/base-info.js +11 -0
- package/lib/ilink/base-info.js.map +1 -0
- package/lib/ilink/client.d.ts +110 -0
- package/lib/ilink/client.d.ts.map +1 -0
- package/lib/ilink/client.js +308 -0
- package/lib/ilink/client.js.map +1 -0
- package/lib/ilink/constants.d.ts +59 -0
- package/lib/ilink/constants.d.ts.map +1 -0
- package/lib/ilink/constants.js +59 -0
- package/lib/ilink/constants.js.map +1 -0
- package/lib/ilink/errors.d.ts +79 -0
- package/lib/ilink/errors.d.ts.map +1 -0
- package/lib/ilink/errors.js +121 -0
- package/lib/ilink/errors.js.map +1 -0
- package/lib/ilink/headers.d.ts +40 -0
- package/lib/ilink/headers.d.ts.map +1 -0
- package/lib/ilink/headers.js +70 -0
- package/lib/ilink/headers.js.map +1 -0
- package/lib/ilink/schema.d.ts +154 -0
- package/lib/ilink/schema.d.ts.map +1 -0
- package/lib/ilink/schema.js +140 -0
- package/lib/ilink/schema.js.map +1 -0
- package/lib/ilink/types.d.ts +235 -0
- package/lib/ilink/types.d.ts.map +1 -0
- package/lib/ilink/types.js +21 -0
- package/lib/ilink/types.js.map +1 -0
- package/lib/index.d.ts +50 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +91 -0
- package/lib/index.js.map +1 -0
- package/lib/manifest.d.ts +54 -0
- package/lib/manifest.d.ts.map +1 -0
- package/lib/manifest.js +32 -0
- package/lib/manifest.js.map +1 -0
- package/lib/media/decrypt.d.ts +3 -0
- package/lib/media/decrypt.d.ts.map +1 -0
- package/lib/media/decrypt.js +16 -0
- package/lib/media/decrypt.js.map +1 -0
- package/lib/media/download.d.ts +22 -0
- package/lib/media/download.d.ts.map +1 -0
- package/lib/media/download.js +62 -0
- package/lib/media/download.js.map +1 -0
- package/lib/media/encrypt.d.ts +3 -0
- package/lib/media/encrypt.d.ts.map +1 -0
- package/lib/media/encrypt.js +16 -0
- package/lib/media/encrypt.js.map +1 -0
- package/lib/media/send-media.d.ts +41 -0
- package/lib/media/send-media.d.ts.map +1 -0
- package/lib/media/send-media.js +52 -0
- package/lib/media/send-media.js.map +1 -0
- package/lib/media/silk-transcode.d.ts +38 -0
- package/lib/media/silk-transcode.d.ts.map +1 -0
- package/lib/media/silk-transcode.js +88 -0
- package/lib/media/silk-transcode.js.map +1 -0
- package/lib/media/upload.d.ts +38 -0
- package/lib/media/upload.d.ts.map +1 -0
- package/lib/media/upload.js +122 -0
- package/lib/media/upload.js.map +1 -0
- package/lib/messaging/dedup.d.ts +87 -0
- package/lib/messaging/dedup.d.ts.map +1 -0
- package/lib/messaging/dedup.js +127 -0
- package/lib/messaging/dedup.js.map +1 -0
- package/lib/messaging/mapper.d.ts +26 -0
- package/lib/messaging/mapper.d.ts.map +1 -0
- package/lib/messaging/mapper.js +107 -0
- package/lib/messaging/mapper.js.map +1 -0
- package/lib/messaging/monitor.d.ts +109 -0
- package/lib/messaging/monitor.d.ts.map +1 -0
- package/lib/messaging/monitor.js +234 -0
- package/lib/messaging/monitor.js.map +1 -0
- package/lib/messaging/quote.d.ts +9 -0
- package/lib/messaging/quote.d.ts.map +1 -0
- package/lib/messaging/quote.js +35 -0
- package/lib/messaging/quote.js.map +1 -0
- package/lib/messaging/send.d.ts +54 -0
- package/lib/messaging/send.d.ts.map +1 -0
- package/lib/messaging/send.js +173 -0
- package/lib/messaging/send.js.map +1 -0
- package/lib/messaging/typing.d.ts +34 -0
- package/lib/messaging/typing.d.ts.map +1 -0
- package/lib/messaging/typing.js +56 -0
- package/lib/messaging/typing.js.map +1 -0
- package/lib/storage/context-token.d.ts +26 -0
- package/lib/storage/context-token.d.ts.map +1 -0
- package/lib/storage/context-token.js +26 -0
- package/lib/storage/context-token.js.map +1 -0
- package/lib/storage/sync-cursor.d.ts +27 -0
- package/lib/storage/sync-cursor.d.ts.map +1 -0
- package/lib/storage/sync-cursor.js +25 -0
- package/lib/storage/sync-cursor.js.map +1 -0
- package/lib/transport.d.ts +38 -0
- package/lib/transport.d.ts.map +1 -0
- package/lib/transport.js +68 -0
- package/lib/transport.js.map +1 -0
- package/lib/upstream/compat.d.ts +54 -0
- package/lib/upstream/compat.d.ts.map +1 -0
- package/lib/upstream/compat.js +54 -0
- package/lib/upstream/compat.js.map +1 -0
- package/lib/upstream/config-manager.d.ts +35 -0
- package/lib/upstream/config-manager.d.ts.map +1 -0
- package/lib/upstream/config-manager.js +91 -0
- package/lib/upstream/config-manager.js.map +1 -0
- package/lib/upstream/index.d.ts +42 -0
- package/lib/upstream/index.d.ts.map +1 -0
- package/lib/upstream/index.js +13 -0
- package/lib/upstream/index.js.map +1 -0
- package/lib/upstream/port.d.ts +153 -0
- package/lib/upstream/port.d.ts.map +1 -0
- package/lib/upstream/port.js +15 -0
- package/lib/upstream/port.js.map +1 -0
- package/lib/upstream/tencent-upstream.d.ts +116 -0
- package/lib/upstream/tencent-upstream.d.ts.map +1 -0
- package/lib/upstream/tencent-upstream.js +518 -0
- package/lib/upstream/tencent-upstream.js.map +1 -0
- package/package.json +48 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* compat.ts — glue that maps between the official upstream shapes and the
|
|
3
|
+
* `WeixinUpstream` port.
|
|
4
|
+
*
|
|
5
|
+
* THIS FILE CONTAINS SHAPE MAPPING ONLY — no protocol logic, no AES, no token /
|
|
6
|
+
* retry / reconnect / upload-algorithm implementation. Those rules live behind
|
|
7
|
+
* `upstream-gap` markers in tencent-upstream.ts. If a mapping needs real
|
|
8
|
+
* protocol behavior, it delegates to that implementation — it never
|
|
9
|
+
* reimplements a wire rule here.
|
|
10
|
+
*/
|
|
11
|
+
import type { WeixinMediaRef, WeixinDownloadResult } from './port.js';
|
|
12
|
+
import type { ILinkCDNMedia } from '../ilink/types.js';
|
|
13
|
+
/**
|
|
14
|
+
* Standardize a media download reference into the neutral `WeixinMediaRef`.
|
|
15
|
+
* Accepts both the port shape (from the adapter) and a raw iLink CDN media
|
|
16
|
+
* reference (from the monitor's mapped item) so callers stay shape-agnostic.
|
|
17
|
+
*/
|
|
18
|
+
export interface NormalizedMediaRef {
|
|
19
|
+
cdnBaseUrl?: string;
|
|
20
|
+
fullUrl?: string;
|
|
21
|
+
encryptQueryParam?: string;
|
|
22
|
+
/** 16-byte raw AES key (already decoded hex → bytes). */
|
|
23
|
+
aesKey?: Buffer | string;
|
|
24
|
+
/** base64 AES key as carried on the wire. */
|
|
25
|
+
aesKeyBase64?: string;
|
|
26
|
+
mimeType?: string;
|
|
27
|
+
}
|
|
28
|
+
/** Convert a raw iLink CDN media reference + item aeskey into a normalized ref. */
|
|
29
|
+
export declare function normalizeMediaRef(media: ILinkCDNMedia | undefined, aesKeyHex: string | undefined, opts?: {
|
|
30
|
+
cdnBaseUrl?: string;
|
|
31
|
+
mimeType?: string;
|
|
32
|
+
}): NormalizedMediaRef | undefined;
|
|
33
|
+
/** Map a normalized ref back to the port `WeixinMediaRef`. */
|
|
34
|
+
export declare function toPortMediaRef(ref: NormalizedMediaRef): WeixinMediaRef;
|
|
35
|
+
/**
|
|
36
|
+
* Normalize a decoded download into the port result, preferring the supplied
|
|
37
|
+
* MIME hint when the underlying fetch had none.
|
|
38
|
+
*/
|
|
39
|
+
export declare function toDownloadResult(data: Buffer, mimeHint: string | undefined): WeixinDownloadResult;
|
|
40
|
+
/**
|
|
41
|
+
* Build the CDN media reference embedded into an iLink sendmessage item from an
|
|
42
|
+
* uploaded file's returned fields. Pure shape mapping of the wire reference
|
|
43
|
+
* (Tencent 2.4.6 carries base64 of the ASCII hex key on outbound).
|
|
44
|
+
*/
|
|
45
|
+
export declare function toSendMediaRef(uploaded: {
|
|
46
|
+
downloadEncryptedQueryParam?: string;
|
|
47
|
+
aeskey?: string;
|
|
48
|
+
fullUrl?: string;
|
|
49
|
+
}): {
|
|
50
|
+
encrypt_query_param?: string;
|
|
51
|
+
aes_key?: string;
|
|
52
|
+
full_url?: string;
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=compat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.d.ts","sourceRoot":"","sources":["../../src/upstream/compat.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,6CAA6C;IAC7C,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,mFAAmF;AACnF,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,aAAa,GAAG,SAAS,EAChC,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,IAAI,GAAE;IAAE,UAAU,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GACpD,kBAAkB,GAAG,SAAS,CAchC;AAED,8DAA8D;AAC9D,wBAAgB,cAAc,CAAC,GAAG,EAAE,kBAAkB,GAAG,cAAc,CAStE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GAAG,SAAS,GAC3B,oBAAoB,CAEtB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE;IACvC,2BAA2B,CAAC,EAAE,MAAM,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG;IAAE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAE,CAUxE"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/** Convert a raw iLink CDN media reference + item aeskey into a normalized ref. */
|
|
2
|
+
export function normalizeMediaRef(media, aesKeyHex, opts = {}) {
|
|
3
|
+
if (!media)
|
|
4
|
+
return undefined;
|
|
5
|
+
const encryptQueryParam = media.encrypt_query_param;
|
|
6
|
+
const fullUrl = media.full_url;
|
|
7
|
+
if (!fullUrl && !encryptQueryParam)
|
|
8
|
+
return undefined;
|
|
9
|
+
return {
|
|
10
|
+
cdnBaseUrl: opts.cdnBaseUrl,
|
|
11
|
+
fullUrl,
|
|
12
|
+
encryptQueryParam,
|
|
13
|
+
// item aeskey (hex, preferred) beats media aes_key (base64).
|
|
14
|
+
aesKey: aesKeyHex,
|
|
15
|
+
aesKeyBase64: media.aes_key,
|
|
16
|
+
mimeType: opts.mimeType,
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/** Map a normalized ref back to the port `WeixinMediaRef`. */
|
|
20
|
+
export function toPortMediaRef(ref) {
|
|
21
|
+
return {
|
|
22
|
+
cdnBaseUrl: ref.cdnBaseUrl,
|
|
23
|
+
fullUrl: ref.fullUrl,
|
|
24
|
+
encryptQueryParam: ref.encryptQueryParam,
|
|
25
|
+
aesKeyHex: typeof ref.aesKey === 'string' ? ref.aesKey : undefined,
|
|
26
|
+
aesKeyBase64: ref.aesKeyBase64,
|
|
27
|
+
mimeType: ref.mimeType,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Normalize a decoded download into the port result, preferring the supplied
|
|
32
|
+
* MIME hint when the underlying fetch had none.
|
|
33
|
+
*/
|
|
34
|
+
export function toDownloadResult(data, mimeHint) {
|
|
35
|
+
return { data: new Uint8Array(data), mimeType: mimeHint };
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Build the CDN media reference embedded into an iLink sendmessage item from an
|
|
39
|
+
* uploaded file's returned fields. Pure shape mapping of the wire reference
|
|
40
|
+
* (Tencent 2.4.6 carries base64 of the ASCII hex key on outbound).
|
|
41
|
+
*/
|
|
42
|
+
export function toSendMediaRef(uploaded) {
|
|
43
|
+
const ref = {};
|
|
44
|
+
if (uploaded.downloadEncryptedQueryParam) {
|
|
45
|
+
ref.encrypt_query_param = uploaded.downloadEncryptedQueryParam;
|
|
46
|
+
}
|
|
47
|
+
if (uploaded.aeskey) {
|
|
48
|
+
ref.aes_key = Buffer.from(uploaded.aeskey, 'ascii').toString('base64');
|
|
49
|
+
}
|
|
50
|
+
if (uploaded.fullUrl)
|
|
51
|
+
ref.full_url = uploaded.fullUrl;
|
|
52
|
+
return ref;
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=compat.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compat.js","sourceRoot":"","sources":["../../src/upstream/compat.ts"],"names":[],"mappings":"AA6BA,mFAAmF;AACnF,MAAM,UAAU,iBAAiB,CAC/B,KAAgC,EAChC,SAA6B,EAC7B,OAAmD,EAAE;IAErD,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,MAAM,iBAAiB,GAAG,KAAK,CAAC,mBAAmB,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC;IAC/B,IAAI,CAAC,OAAO,IAAI,CAAC,iBAAiB;QAAE,OAAO,SAAS,CAAC;IACrD,OAAO;QACL,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO;QACP,iBAAiB;QACjB,6DAA6D;QAC7D,MAAM,EAAE,SAAS;QACjB,YAAY,EAAE,KAAK,CAAC,OAAO;QAC3B,QAAQ,EAAE,IAAI,CAAC,QAAQ;KACxB,CAAC;AACJ,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,cAAc,CAAC,GAAuB;IACpD,OAAO;QACL,UAAU,EAAE,GAAG,CAAC,UAAU;QAC1B,OAAO,EAAE,GAAG,CAAC,OAAO;QACpB,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;QACxC,SAAS,EAAE,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAClE,YAAY,EAAE,GAAG,CAAC,YAAY;QAC9B,QAAQ,EAAE,GAAG,CAAC,QAAQ;KACvB,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,IAAY,EACZ,QAA4B;IAE5B,OAAO,EAAE,IAAI,EAAE,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAI9B;IACC,MAAM,GAAG,GAA0E,EAAE,CAAC;IACtF,IAAI,QAAQ,CAAC,2BAA2B,EAAE,CAAC;QACzC,GAAG,CAAC,mBAAmB,GAAG,QAAQ,CAAC,2BAA2B,CAAC;IACjE,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;QACpB,GAAG,CAAC,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,QAAQ,CAAC,OAAO;QAAE,GAAG,CAAC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC;IACtD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export interface WeixinConfigManagerOptions {
|
|
2
|
+
/** Fetches peer config from iLink. The response is untrusted. */
|
|
3
|
+
fetchConfig(peer: string): Promise<unknown>;
|
|
4
|
+
/** Injectable clock and entropy source for deterministic tests. */
|
|
5
|
+
now?: () => number;
|
|
6
|
+
rand?: () => number;
|
|
7
|
+
/** Defaults match Tencent's bounded refresh/backoff policy. */
|
|
8
|
+
minRefreshMs?: number;
|
|
9
|
+
refreshJitterMs?: number;
|
|
10
|
+
initialRetryDelayMs?: number;
|
|
11
|
+
maxRetryDelayMs?: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Per-peer iLink config cache. Typing remains best-effort: it uses a prior
|
|
15
|
+
* ticket during a failed refresh and retries unavailable config with backoff.
|
|
16
|
+
*/
|
|
17
|
+
export declare class WeixinConfigManager {
|
|
18
|
+
private readonly fetchConfig;
|
|
19
|
+
private readonly now;
|
|
20
|
+
private readonly rand;
|
|
21
|
+
private readonly minRefreshMs;
|
|
22
|
+
private readonly refreshJitterMs;
|
|
23
|
+
private readonly initialRetryDelayMs;
|
|
24
|
+
private readonly maxRetryDelayMs;
|
|
25
|
+
private readonly cache;
|
|
26
|
+
private readonly pending;
|
|
27
|
+
constructor(options: WeixinConfigManagerOptions);
|
|
28
|
+
/** Resolve a valid ticket, preserving a prior ticket while a refresh backs off. */
|
|
29
|
+
resolveTypingTicket(peer: string | undefined): Promise<string | undefined>;
|
|
30
|
+
/** Clear one peer or all entries after a credential or base URL transition. */
|
|
31
|
+
clear(peer?: string): void;
|
|
32
|
+
private refresh;
|
|
33
|
+
private nextRefreshDelay;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=config-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.d.ts","sourceRoot":"","sources":["../../src/upstream/config-manager.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,0BAA0B;IACzC,iEAAiE;IACjE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC5C,mEAAmE;IACnE,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IACpB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAcD;;;GAGG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqC;IACjE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAe;IACpC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAS;IACtC,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAS;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;IAC7D,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAkD;gBAE9D,OAAO,EAAE,0BAA0B;IAU/C,mFAAmF;IAC7E,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC;IAiBhF,+EAA+E;IAC/E,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI;YAWZ,OAAO;IA6BrB,OAAO,CAAC,gBAAgB;CAIzB"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
const getConfigResponseSchema = z.object({
|
|
3
|
+
typing_ticket: z.string().trim().min(1).max(4096).optional(),
|
|
4
|
+
}).passthrough();
|
|
5
|
+
const DEFAULT_MIN_REFRESH_MS = 12 * 60 * 60 * 1000;
|
|
6
|
+
const DEFAULT_REFRESH_JITTER_MS = 12 * 60 * 60 * 1000;
|
|
7
|
+
const DEFAULT_INITIAL_RETRY_DELAY_MS = 2_000;
|
|
8
|
+
const DEFAULT_MAX_RETRY_DELAY_MS = 60 * 60 * 1000;
|
|
9
|
+
/**
|
|
10
|
+
* Per-peer iLink config cache. Typing remains best-effort: it uses a prior
|
|
11
|
+
* ticket during a failed refresh and retries unavailable config with backoff.
|
|
12
|
+
*/
|
|
13
|
+
export class WeixinConfigManager {
|
|
14
|
+
fetchConfig;
|
|
15
|
+
now;
|
|
16
|
+
rand;
|
|
17
|
+
minRefreshMs;
|
|
18
|
+
refreshJitterMs;
|
|
19
|
+
initialRetryDelayMs;
|
|
20
|
+
maxRetryDelayMs;
|
|
21
|
+
cache = new Map();
|
|
22
|
+
pending = new Map();
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.fetchConfig = options.fetchConfig;
|
|
25
|
+
this.now = options.now ?? Date.now;
|
|
26
|
+
this.rand = options.rand ?? Math.random;
|
|
27
|
+
this.minRefreshMs = options.minRefreshMs ?? DEFAULT_MIN_REFRESH_MS;
|
|
28
|
+
this.refreshJitterMs = options.refreshJitterMs ?? DEFAULT_REFRESH_JITTER_MS;
|
|
29
|
+
this.initialRetryDelayMs = options.initialRetryDelayMs ?? DEFAULT_INITIAL_RETRY_DELAY_MS;
|
|
30
|
+
this.maxRetryDelayMs = options.maxRetryDelayMs ?? DEFAULT_MAX_RETRY_DELAY_MS;
|
|
31
|
+
}
|
|
32
|
+
/** Resolve a valid ticket, preserving a prior ticket while a refresh backs off. */
|
|
33
|
+
async resolveTypingTicket(peer) {
|
|
34
|
+
const normalizedPeer = peer?.trim();
|
|
35
|
+
if (!normalizedPeer)
|
|
36
|
+
return undefined;
|
|
37
|
+
const current = this.cache.get(normalizedPeer);
|
|
38
|
+
if (current && this.now() < current.nextFetchAt)
|
|
39
|
+
return current.typingTicket;
|
|
40
|
+
const existing = this.pending.get(normalizedPeer);
|
|
41
|
+
if (existing)
|
|
42
|
+
return existing;
|
|
43
|
+
const request = this.refresh(normalizedPeer, current).finally(() => {
|
|
44
|
+
this.pending.delete(normalizedPeer);
|
|
45
|
+
});
|
|
46
|
+
this.pending.set(normalizedPeer, request);
|
|
47
|
+
return request;
|
|
48
|
+
}
|
|
49
|
+
/** Clear one peer or all entries after a credential or base URL transition. */
|
|
50
|
+
clear(peer) {
|
|
51
|
+
const normalizedPeer = peer?.trim();
|
|
52
|
+
if (normalizedPeer) {
|
|
53
|
+
this.cache.delete(normalizedPeer);
|
|
54
|
+
this.pending.delete(normalizedPeer);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
this.cache.clear();
|
|
58
|
+
this.pending.clear();
|
|
59
|
+
}
|
|
60
|
+
async refresh(peer, prior) {
|
|
61
|
+
const now = this.now();
|
|
62
|
+
try {
|
|
63
|
+
const parsed = getConfigResponseSchema.safeParse(await this.fetchConfig(peer));
|
|
64
|
+
if (!parsed.success || !parsed.data.typing_ticket)
|
|
65
|
+
throw new Error('typing ticket unavailable');
|
|
66
|
+
const typingTicket = parsed.data.typing_ticket;
|
|
67
|
+
this.cache.set(peer, {
|
|
68
|
+
typingTicket,
|
|
69
|
+
nextFetchAt: now + this.nextRefreshDelay(),
|
|
70
|
+
retryDelayMs: this.initialRetryDelayMs,
|
|
71
|
+
everSucceeded: true,
|
|
72
|
+
});
|
|
73
|
+
return typingTicket;
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
const retryDelayMs = Math.min(prior?.retryDelayMs ?? this.initialRetryDelayMs, this.maxRetryDelayMs);
|
|
77
|
+
this.cache.set(peer, {
|
|
78
|
+
typingTicket: prior?.typingTicket,
|
|
79
|
+
nextFetchAt: now + retryDelayMs,
|
|
80
|
+
retryDelayMs: Math.min(retryDelayMs * 2, this.maxRetryDelayMs),
|
|
81
|
+
everSucceeded: prior?.everSucceeded ?? false,
|
|
82
|
+
});
|
|
83
|
+
return prior?.typingTicket;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
nextRefreshDelay() {
|
|
87
|
+
const boundedRandom = Math.min(1, Math.max(0, this.rand()));
|
|
88
|
+
return this.minRefreshMs + Math.floor(this.refreshJitterMs * boundedRandom);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=config-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-manager.js","sourceRoot":"","sources":["../../src/upstream/config-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.ts — public surface of the Weixin upstream layer.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports the DSH-side port (`WeixinUpstream`) and the factory
|
|
5
|
+
* (`createWeixinUpstream`). Consumers (the adapter) depend only on the port;
|
|
6
|
+
* the Tencent implementation and the vendor deep-import boundary stay internal.
|
|
7
|
+
*/
|
|
8
|
+
import type { HttpTransport } from '../transport.js';
|
|
9
|
+
import type { WeixinConfig } from '../config.js';
|
|
10
|
+
import type { SecureRemoteMediaFetcher } from '@krischoichoi/channel-core';
|
|
11
|
+
import type { WeixinUpstream } from './port.js';
|
|
12
|
+
export type { WeixinUpstream, WeixinUpstreamHostEnv, WeixinQrTicket, WeixinQrAuthPoll, WeixinAuthCredential, WeixinMediaRef, WeixinDownloadResult, WeixinTextParams, WeixinImageParams, WeixinFileParams, WeixinVideoParams, WeixinSendResult, QrAuthState, } from './port.js';
|
|
13
|
+
export { UpstreamCapabilityError } from './port.js';
|
|
14
|
+
export { TencentWeixinUpstream, type WeixinUpstreamOptions } from './tencent-upstream.js';
|
|
15
|
+
export { normalizeMediaRef, toPortMediaRef, toDownloadResult, toSendMediaRef } from './compat.js';
|
|
16
|
+
export interface CreateWeixinUpstreamOptions {
|
|
17
|
+
config: WeixinConfig;
|
|
18
|
+
transport?: HttpTransport;
|
|
19
|
+
now?: () => number;
|
|
20
|
+
rand?: () => number;
|
|
21
|
+
/** Injectable fetch for media download (tests); defaults to globalThis.fetch. */
|
|
22
|
+
fetchImpl?: typeof fetch;
|
|
23
|
+
/** Injectable shared secure downloader (tests). */
|
|
24
|
+
mediaFetcher?: SecureRemoteMediaFetcher;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Create the Weixin upstream facade. Call [WeixinUpstream.extend/bind] with a
|
|
28
|
+
* host env before using startMonitor/send/download — see [WeixinUpstreamHostEnv]
|
|
29
|
+
* and [TencentWeixinUpstream.bind].
|
|
30
|
+
*/
|
|
31
|
+
export declare function createWeixinUpstream(options: CreateWeixinUpstreamOptions): WeixinUpstream & {
|
|
32
|
+
bind(env: import('./port.js').WeixinUpstreamHostEnv): void;
|
|
33
|
+
loadCredential(): Promise<boolean>;
|
|
34
|
+
startTyping(peer: string): Promise<void>;
|
|
35
|
+
stopTyping(peer: string): Promise<void>;
|
|
36
|
+
getHealthInfo(): Promise<{
|
|
37
|
+
authenticated: boolean;
|
|
38
|
+
connection: import('./tencent-upstream.js').WeixinConnectionState;
|
|
39
|
+
}>;
|
|
40
|
+
get_iLinkClient(): import('../ilink/client.js').ILinkClient | undefined;
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AACjD,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,4BAA4B,CAAC;AAE3E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAEhD,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,GACZ,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElG,MAAM,WAAW,2BAA2B;IAC1C,MAAM,EAAE,YAAY,CAAC;IACrB,SAAS,CAAC,EAAE,aAAa,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,MAAM,CAAC;IACpB,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,mDAAmD;IACnD,YAAY,CAAC,EAAE,wBAAwB,CAAC;CACzC;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,cAAc,GAAG;IAC3F,IAAI,CAAC,GAAG,EAAE,OAAO,WAAW,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAC3D,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,aAAa,IAAI,OAAO,CAAC;QAAE,aAAa,EAAE,OAAO,CAAC;QAAC,UAAU,EAAE,OAAO,uBAAuB,EAAE,qBAAqB,CAAA;KAAE,CAAC,CAAC;IACxH,eAAe,IAAI,OAAO,oBAAoB,EAAE,WAAW,GAAG,SAAS,CAAC;CACzE,CAEA"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TencentWeixinUpstream } from './tencent-upstream.js';
|
|
2
|
+
export { UpstreamCapabilityError } from './port.js';
|
|
3
|
+
export { TencentWeixinUpstream } from './tencent-upstream.js';
|
|
4
|
+
export { normalizeMediaRef, toPortMediaRef, toDownloadResult, toSendMediaRef } from './compat.js';
|
|
5
|
+
/**
|
|
6
|
+
* Create the Weixin upstream facade. Call [WeixinUpstream.extend/bind] with a
|
|
7
|
+
* host env before using startMonitor/send/download — see [WeixinUpstreamHostEnv]
|
|
8
|
+
* and [TencentWeixinUpstream.bind].
|
|
9
|
+
*/
|
|
10
|
+
export function createWeixinUpstream(options) {
|
|
11
|
+
return new TencentWeixinUpstream(options);
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/upstream/index.ts"],"names":[],"mappings":"AAUA,OAAO,EAAE,qBAAqB,EAA8B,MAAM,uBAAuB,CAAC;AAkB1F,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAA8B,MAAM,uBAAuB,CAAC;AAC1F,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAalG;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAoC;IAQvE,OAAO,IAAI,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC5C,CAAC"}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* port.ts — DSH-side minimal upstream interface.
|
|
3
|
+
*
|
|
4
|
+
* `WeixinUpstream` is the ONLY surface the Weixin adapter depends on. It is a
|
|
5
|
+
* thin, protocol-agnostic port: the adapter no longer knows AES keys,
|
|
6
|
+
* getuploadurl payloads, CDN query assembly, or iLink endpoints (plan DoD #1) —
|
|
7
|
+
* those all live inside the DSH-hosted source-port implementation
|
|
8
|
+
* (tencent-upstream.ts).
|
|
9
|
+
*
|
|
10
|
+
* Design constraints:
|
|
11
|
+
* - method count stays small — only what DSH genuinely consumes;
|
|
12
|
+
* - no token/retry/reconnect/AES/upload-algorithm logic here — pure shape;
|
|
13
|
+
* - a capability that the upstream cannot yet provide is surfaced as a
|
|
14
|
+
* typed `UpstreamCapabilityError` — NEVER faked.
|
|
15
|
+
*/
|
|
16
|
+
import type { ChannelAdapterContext } from '@krischoichoi/channel-core';
|
|
17
|
+
import type { SecretStore, ChannelStorage } from '@krischoichoi/channel-core';
|
|
18
|
+
/** Uniform upstream-facing QR state (normalizes the Weixin iLink machine). */
|
|
19
|
+
export type QrAuthState = 'pending' | 'authenticated' | 'expired' | 'failed';
|
|
20
|
+
/** A QR login ticket handed to the operator. */
|
|
21
|
+
export interface WeixinQrTicket {
|
|
22
|
+
/** Stable ticket id used by later pollQrAuth calls. */
|
|
23
|
+
id: string;
|
|
24
|
+
/** QR payload (URL or data:image) for the operator to scan/render. */
|
|
25
|
+
qrUrl?: string;
|
|
26
|
+
/** Short human instruction (e.g. "scan with WeChat"). */
|
|
27
|
+
instruction?: string;
|
|
28
|
+
/** Expiry instant (ms epoch). */
|
|
29
|
+
expiresAt?: number;
|
|
30
|
+
}
|
|
31
|
+
/** Credential produced once a QR login is confirmed. */
|
|
32
|
+
export interface WeixinAuthCredential {
|
|
33
|
+
token: string;
|
|
34
|
+
ilinkBotId: string;
|
|
35
|
+
userId?: string;
|
|
36
|
+
baseUrl: string;
|
|
37
|
+
}
|
|
38
|
+
/** One QR auth poll result. */
|
|
39
|
+
export interface WeixinQrAuthPoll {
|
|
40
|
+
state: QrAuthState;
|
|
41
|
+
detail?: string;
|
|
42
|
+
/** Present only when `state === 'authenticated'`. */
|
|
43
|
+
credential?: WeixinAuthCredential;
|
|
44
|
+
}
|
|
45
|
+
/** Context referencing a Weixin media resource for download. */
|
|
46
|
+
export interface WeixinMediaRef {
|
|
47
|
+
/** CDN base URL override (derives a download URL when no fullUrl). */
|
|
48
|
+
cdnBaseUrl?: string;
|
|
49
|
+
/** Server-returned full_url (preferred carrier). */
|
|
50
|
+
fullUrl?: string;
|
|
51
|
+
/** `encrypt_query_param` when the CDN URL must be derived. */
|
|
52
|
+
encryptQueryParam?: string;
|
|
53
|
+
/** AES-128 key as 16-byte HEX (image item `aeskey`), preferred. */
|
|
54
|
+
aesKeyHex?: string;
|
|
55
|
+
/** AES-128 key as base64 (CDN media `aes_key`). */
|
|
56
|
+
aesKeyBase64?: string;
|
|
57
|
+
/** MIME hint (image/jpeg …) when known from item metadata. */
|
|
58
|
+
mimeType?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Result of a media download. */
|
|
61
|
+
export interface WeixinDownloadResult {
|
|
62
|
+
/** Plaintext (decrypted) bytes. */
|
|
63
|
+
data: Uint8Array;
|
|
64
|
+
mimeType?: string;
|
|
65
|
+
}
|
|
66
|
+
/** Target for an outbound send + optional turn correlation. */
|
|
67
|
+
export interface WeixinSendTarget {
|
|
68
|
+
to: string;
|
|
69
|
+
contextToken?: string;
|
|
70
|
+
runId?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface WeixinTextParams extends WeixinSendTarget {
|
|
73
|
+
text: string;
|
|
74
|
+
}
|
|
75
|
+
export interface WeixinImageParams extends WeixinSendTarget {
|
|
76
|
+
/** Plaintext image bytes. */
|
|
77
|
+
data: Uint8Array;
|
|
78
|
+
mimeType?: string;
|
|
79
|
+
}
|
|
80
|
+
export interface WeixinFileParams extends WeixinSendTarget {
|
|
81
|
+
data: Uint8Array;
|
|
82
|
+
fileName: string;
|
|
83
|
+
mimeType?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface WeixinVideoParams extends WeixinSendTarget {
|
|
86
|
+
data: Uint8Array;
|
|
87
|
+
mimeType?: string;
|
|
88
|
+
}
|
|
89
|
+
/** Result of one outbound send. */
|
|
90
|
+
export interface WeixinSendResult {
|
|
91
|
+
messageId?: string;
|
|
92
|
+
delivered: boolean;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Upstream resources wired once by the host (adapter) at start. Provides the
|
|
96
|
+
* harness seam the monitor needs (emit/dispatch, signal, logger) and the store
|
|
97
|
+
* boundaries for credentials / sync-cursor / context-token / dedup.
|
|
98
|
+
*/
|
|
99
|
+
export interface WeixinUpstreamHostEnv {
|
|
100
|
+
ctx: ChannelAdapterContext;
|
|
101
|
+
secrets: SecretStore;
|
|
102
|
+
storage: ChannelStorage;
|
|
103
|
+
/** Optional connection-state callback (monitor health → adapter/heartbeat). */
|
|
104
|
+
onConnectionChange?: (state: 'connected' | 'reconnecting' | 'disconnected') => void;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* The DSH-side upstream port implemented by TencentWeixinUpstream.
|
|
108
|
+
*/
|
|
109
|
+
export interface WeixinUpstream {
|
|
110
|
+
readonly id: 'weixin';
|
|
111
|
+
/** Begin a WeChat QR login; returns a fresh ticket. */
|
|
112
|
+
beginQrAuth(): Promise<WeixinQrTicket>;
|
|
113
|
+
/** Poll the active QR ticket. */
|
|
114
|
+
pollQrAuth(ticketId: string): Promise<WeixinQrAuthPoll>;
|
|
115
|
+
/** Submit a phone-verify code for the active QR ticket (adapter-specific). */
|
|
116
|
+
submitVerifyCode(code: string): void;
|
|
117
|
+
/** Start the getUpdates monitor; requires the host env to be bound first. */
|
|
118
|
+
startMonitor(): Promise<void>;
|
|
119
|
+
/** Stop the getUpdates monitor (best effort). */
|
|
120
|
+
stopMonitor(): Promise<void>;
|
|
121
|
+
/** Send a text message. */
|
|
122
|
+
sendText(params: WeixinTextParams): Promise<WeixinSendResult>;
|
|
123
|
+
/** Send an image message (uploads plaintext bytes, sends an image item). */
|
|
124
|
+
sendImage(params: WeixinImageParams): Promise<WeixinSendResult>;
|
|
125
|
+
/** Send a file message. */
|
|
126
|
+
sendFile(params: WeixinFileParams): Promise<WeixinSendResult>;
|
|
127
|
+
/** Send a video message. */
|
|
128
|
+
sendVideo(params: WeixinVideoParams): Promise<WeixinSendResult>;
|
|
129
|
+
/** Download + decrypt an inbound image. */
|
|
130
|
+
downloadImage(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
131
|
+
/** Download + decrypt an inbound file. */
|
|
132
|
+
downloadFile(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
133
|
+
/** Download + decrypt an inbound audio attachment. */
|
|
134
|
+
downloadAudio(ref: WeixinMediaRef, options?: {
|
|
135
|
+
encodeType?: number;
|
|
136
|
+
sampleRate?: number;
|
|
137
|
+
}): Promise<WeixinDownloadResult>;
|
|
138
|
+
/** Download + decrypt an inbound video attachment. */
|
|
139
|
+
downloadVideo(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
140
|
+
/** True when the bound credential is present and non-empty. */
|
|
141
|
+
hasCredential(): boolean;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* A typed capability error: the requested operation is not (yet) provided by
|
|
145
|
+
* the upstream. Thrown instead of fabricating support ("do not fake
|
|
146
|
+
* support").
|
|
147
|
+
*/
|
|
148
|
+
export declare class UpstreamCapabilityError extends Error {
|
|
149
|
+
/** Which capability is missing. */
|
|
150
|
+
readonly capability: string;
|
|
151
|
+
constructor(capability: string, reason: string);
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=port.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/upstream/port.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A typed capability error: the requested operation is not (yet) provided by
|
|
3
|
+
* the upstream. Thrown instead of fabricating support ("do not fake
|
|
4
|
+
* support").
|
|
5
|
+
*/
|
|
6
|
+
export class UpstreamCapabilityError extends Error {
|
|
7
|
+
/** Which capability is missing. */
|
|
8
|
+
capability;
|
|
9
|
+
constructor(capability, reason) {
|
|
10
|
+
super(`weixin upstream capability '${capability}' is unavailable: ${reason}`);
|
|
11
|
+
this.name = 'UpstreamCapabilityError';
|
|
12
|
+
this.capability = capability;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=port.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/upstream/port.ts"],"names":[],"mappings":"AA+JA;;;;GAIG;AACH,MAAM,OAAO,uBAAwB,SAAQ,KAAK;IAChD,mCAAmC;IAC1B,UAAU,CAAS;IAE5B,YAAY,UAAkB,EAAE,MAAc;QAC5C,KAAK,CAAC,+BAA+B,UAAU,qBAAqB,MAAM,EAAE,CAAC,CAAC;QAC9E,IAAI,CAAC,IAAI,GAAG,yBAAyB,CAAC;QACtC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;IAC/B,CAAC;CACF"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tencent-upstream.ts — DSH-hosted Weixin iLink source-port.
|
|
3
|
+
*
|
|
4
|
+
* Tencent's published @tencent-weixin/openclaw-weixin plugin couples its
|
|
5
|
+
* runtime to OpenClaw. It is retained as a source reference only: importing
|
|
6
|
+
* its internal dist paths or installing its OpenClaw peer dependency would
|
|
7
|
+
* violate the DSH host boundary. Protocol orchestration and AES therefore stay
|
|
8
|
+
* in this adapter behind the WeixinUpstream port.
|
|
9
|
+
*
|
|
10
|
+
* ZERO-REGRESSION contract:
|
|
11
|
+
* Weixin image → localData → saveImage() → ImageBlock unchanged.
|
|
12
|
+
* downloadImage() returns the SAME decrypted bytes legacy media/download.ts
|
|
13
|
+
* produced. URL resolution keeps the legacy shape because the Tencent plugin
|
|
14
|
+
* uses a different URL form that would alter the working CDN path.
|
|
15
|
+
*/
|
|
16
|
+
import { SecureRemoteMediaFetcher } from '@krischoichoi/channel-core';
|
|
17
|
+
import type { WeixinConfig } from '../config.js';
|
|
18
|
+
import { ILinkClient } from '../ilink/client.js';
|
|
19
|
+
import type { HttpTransport } from '../transport.js';
|
|
20
|
+
import type { WeixinUpstream, WeixinUpstreamHostEnv, WeixinQrTicket, WeixinQrAuthPoll, WeixinMediaRef, WeixinDownloadResult, WeixinTextParams, WeixinImageParams, WeixinFileParams, WeixinVideoParams, WeixinSendResult } from './port.js';
|
|
21
|
+
/** Connection state surfaced to the host (mirrors the monitor's own notion). */
|
|
22
|
+
export type WeixinConnectionState = 'connected' | 'reconnecting' | 'disconnected' | 'not-started';
|
|
23
|
+
/** Options to construct a [TencentWeixinUpstream]. */
|
|
24
|
+
export interface WeixinUpstreamOptions {
|
|
25
|
+
config: WeixinConfig;
|
|
26
|
+
transport?: HttpTransport;
|
|
27
|
+
now?: () => number;
|
|
28
|
+
rand?: () => number;
|
|
29
|
+
/** Injectable fetch for media download (tests); defaults to globalThis.fetch. */
|
|
30
|
+
fetchImpl?: typeof fetch;
|
|
31
|
+
/** Injectable shared secure downloader (tests); defaults to the core boundary. */
|
|
32
|
+
mediaFetcher?: SecureRemoteMediaFetcher;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The concrete upstream implementation. Owns every protocol/media detail; the
|
|
36
|
+
* adapter depends only on the `WeixinUpstream` port.
|
|
37
|
+
*/
|
|
38
|
+
export declare class TencentWeixinUpstream implements WeixinUpstream {
|
|
39
|
+
readonly id = "weixin";
|
|
40
|
+
private readonly config;
|
|
41
|
+
private readonly now;
|
|
42
|
+
private readonly rand;
|
|
43
|
+
private readonly transport;
|
|
44
|
+
private readonly mediaFetcher;
|
|
45
|
+
private env?;
|
|
46
|
+
private client?;
|
|
47
|
+
private credentialStore?;
|
|
48
|
+
private cursorStore?;
|
|
49
|
+
private contextTokens?;
|
|
50
|
+
private qrAuth?;
|
|
51
|
+
private sender?;
|
|
52
|
+
private monitor?;
|
|
53
|
+
private typing?;
|
|
54
|
+
private configManager?;
|
|
55
|
+
private typingPeer?;
|
|
56
|
+
private connected;
|
|
57
|
+
/** Whether a credential is loaded/persisted (the adapter's "authenticated"). */
|
|
58
|
+
private authenticated;
|
|
59
|
+
/** Active QR ticket id + expiry, so pollAuth can rebuild the challenge. */
|
|
60
|
+
private activeQrId?;
|
|
61
|
+
private activeQrExpiresAt?;
|
|
62
|
+
constructor(options: WeixinUpstreamOptions);
|
|
63
|
+
/**
|
|
64
|
+
* Wire the host environment (stores + context) and build the internal
|
|
65
|
+
* protocol session. Called by the adapter at start(); idempotent.
|
|
66
|
+
*/
|
|
67
|
+
bind(env: WeixinUpstreamHostEnv): void;
|
|
68
|
+
hasCredential(): boolean;
|
|
69
|
+
/**
|
|
70
|
+
* Load the persisted credential, applying token/baseUrl to the client.
|
|
71
|
+
* Returns true when a full credential exists. This is the adapter's "have we
|
|
72
|
+
* authenticated before?" signal.
|
|
73
|
+
*/
|
|
74
|
+
loadCredential(): Promise<boolean>;
|
|
75
|
+
beginQrAuth(): Promise<WeixinQrTicket>;
|
|
76
|
+
pollQrAuth(ticketId: string): Promise<WeixinQrAuthPoll>;
|
|
77
|
+
submitVerifyCode(code: string): void;
|
|
78
|
+
startMonitor(): Promise<void>;
|
|
79
|
+
stopMonitor(): Promise<void>;
|
|
80
|
+
sendText(params: WeixinTextParams): Promise<WeixinSendResult>;
|
|
81
|
+
sendImage(params: WeixinImageParams): Promise<WeixinSendResult>;
|
|
82
|
+
sendFile(params: WeixinFileParams): Promise<WeixinSendResult>;
|
|
83
|
+
sendVideo(params: WeixinVideoParams): Promise<WeixinSendResult>;
|
|
84
|
+
downloadImage(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
85
|
+
downloadFile(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
86
|
+
downloadAudio(ref: WeixinMediaRef, options?: {
|
|
87
|
+
encodeType?: number;
|
|
88
|
+
sampleRate?: number;
|
|
89
|
+
}): Promise<WeixinDownloadResult>;
|
|
90
|
+
downloadVideo(ref: WeixinMediaRef): Promise<WeixinDownloadResult>;
|
|
91
|
+
startTyping(conversationId: string): Promise<void>;
|
|
92
|
+
stopTyping(conversationId: string): Promise<void>;
|
|
93
|
+
/** Health introspection (bound credential + connection). */
|
|
94
|
+
getHealthInfo(): Promise<{
|
|
95
|
+
authenticated: boolean;
|
|
96
|
+
connection: WeixinConnectionState;
|
|
97
|
+
}>;
|
|
98
|
+
/** Introspection for tests: the underlying client. */
|
|
99
|
+
get_iLinkClient(): ILinkClient | undefined;
|
|
100
|
+
private ensureSession;
|
|
101
|
+
private requireReady;
|
|
102
|
+
private targetOf;
|
|
103
|
+
private persistCredential;
|
|
104
|
+
/** Hydrate inbound media before the event reaches the attachment pipeline. */
|
|
105
|
+
private enrichInboundMedia;
|
|
106
|
+
/**
|
|
107
|
+
* Resolve the platform media reference, then cross the shared secure remote
|
|
108
|
+
* media boundary before applying Weixin's source-port AES decryption.
|
|
109
|
+
*/
|
|
110
|
+
private downloadAndDecrypt;
|
|
111
|
+
private resolveDownloadUrl;
|
|
112
|
+
/** Resolve the AES-128 key honoring hex (item aeskey) then base64 (media aes_key). */
|
|
113
|
+
private resolveAesKey;
|
|
114
|
+
private resolveTypingTicket;
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=tencent-upstream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tencent-upstream.d.ts","sourceRoot":"","sources":["../../src/upstream/tencent-upstream.ts"],"names":[],"mappings":"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"}
|