@zhin.js/adapter-icqq 1.1.18 → 1.1.20
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/CHANGELOG.md +44 -0
- package/README.md +12 -8
- package/adapters/icqq/index.js +4 -28
- package/adapters/icqq/index.ts +3 -34
- package/commands/icqq/endpoint/definition.js +3 -25
- package/commands/icqq/endpoint/definition.ts +3 -24
- package/commands/icqq/login/code/index.js +3 -3
- package/commands/icqq/login/code/index.ts +3 -3
- package/commands/icqq/login/confirm/index.js +3 -3
- package/commands/icqq/login/confirm/index.ts +3 -3
- package/commands/icqq/login/definition.js +2 -2
- package/commands/icqq/login/definition.ts +2 -2
- package/commands/icqq/login/qr/index.js +3 -3
- package/commands/icqq/login/qr/index.ts +3 -3
- package/commands/icqq/login/retry/index.js +3 -3
- package/commands/icqq/login/retry/index.ts +3 -3
- package/commands/icqq/login/status/index.js +3 -3
- package/commands/icqq/login/status/index.ts +3 -3
- package/lib/adapter.d.ts +13 -0
- package/lib/adapter.js +27 -0
- package/lib/client.d.ts +6 -9
- package/lib/client.js +1 -3
- package/lib/console-spec.js +11 -1
- package/lib/console.d.ts +1 -7
- package/lib/console.js +2 -5
- package/lib/endpoint.d.ts +6 -16
- package/lib/endpoint.js +195 -143
- package/lib/group-moderation.d.ts +6 -3
- package/lib/group-moderation.js +9 -8
- package/lib/group-scene.d.ts +3 -3
- package/lib/group-scene.js +8 -7
- package/lib/icqq-login-assist.d.ts +3 -1
- package/lib/icqq-login-assist.js +3 -1
- package/lib/icqq-login-control.d.ts +8 -2
- package/lib/icqq-login-control.js +22 -5
- package/lib/index.d.ts +2 -1
- package/lib/index.js +1 -1
- package/lib/protocol.d.ts +3 -0
- package/package.json +18 -18
- package/plugin.js +1 -8
- package/src/adapter.ts +29 -0
- package/src/client.ts +6 -11
- package/src/console-spec.ts +9 -0
- package/src/console.ts +2 -6
- package/src/endpoint.ts +205 -153
- package/src/group-moderation.ts +10 -10
- package/src/group-scene.ts +8 -8
- package/src/icqq-login-assist.ts +6 -2
- package/src/icqq-login-control.ts +20 -8
- package/src/index.ts +2 -1
- package/src/protocol.ts +3 -0
- package/lib/icqq-runtime-state.d.ts +0 -1
- package/lib/icqq-runtime-state.js +0 -6
- package/src/icqq-runtime-state.ts +0 -7
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { Client } from '@icqqjs/icqq';
|
|
2
|
-
import type
|
|
2
|
+
import { type EndpointMemberInspectionRequest, type EndpointModerationRequest, type GroupModerationMember } from 'zhin.js/adapter';
|
|
3
3
|
/** Native role/join facts stay in the adapter; the moderation plugin owns policy. */
|
|
4
|
-
export declare function inspectGroupMember(client: Client, groupId
|
|
5
|
-
export declare function moderateGroupMember(client
|
|
4
|
+
export declare function inspectGroupMember(client: Client, { groupId, userId, signal }: EndpointMemberInspectionRequest): Promise<GroupModerationMember>;
|
|
5
|
+
export declare function moderateGroupMember({ client, isActive }: {
|
|
6
|
+
readonly client: Client;
|
|
7
|
+
readonly isActive: () => boolean;
|
|
8
|
+
}, { groupId, userId, action, signal }: EndpointModerationRequest): Promise<void>;
|
package/lib/group-moderation.js
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
import { createEndpointOperation } from 'zhin.js/adapter';
|
|
1
2
|
/** Native role/join facts stay in the adapter; the moderation plugin owns policy. */
|
|
2
|
-
export async function inspectGroupMember(client, groupId, userId, signal) {
|
|
3
|
-
signal
|
|
3
|
+
export async function inspectGroupMember(client, { groupId, userId, signal }) {
|
|
4
|
+
const operation = createEndpointOperation({ signal });
|
|
4
5
|
const group = numericId(groupId);
|
|
5
6
|
const user = numericId(userId);
|
|
6
|
-
const selfLookup = client.getGroupMemberInfo(group, client.uin, true);
|
|
7
|
+
const selfLookup = operation.run(() => client.getGroupMemberInfo(group, client.uin, true));
|
|
7
8
|
const [self, member] = await Promise.all([
|
|
8
9
|
selfLookup,
|
|
9
|
-
user === client.uin ? selfLookup : client.getGroupMemberInfo(group, user, true),
|
|
10
|
+
user === client.uin ? selfLookup : operation.run(() => client.getGroupMemberInfo(group, user, true)),
|
|
10
11
|
]);
|
|
11
12
|
signal.throwIfAborted();
|
|
12
13
|
const joinedAt = member.join_time * 1000;
|
|
@@ -22,8 +23,8 @@ export async function inspectGroupMember(client, groupId, userId, signal) {
|
|
|
22
23
|
...(Number.isSafeInteger(joinedAt) && joinedAt > 0 && joinedAt <= Date.now() ? { joinedAt } : {}),
|
|
23
24
|
};
|
|
24
25
|
}
|
|
25
|
-
export async function moderateGroupMember(client, groupId, userId, action, signal
|
|
26
|
-
const member = await inspectGroupMember(client, groupId, userId, signal);
|
|
26
|
+
export async function moderateGroupMember({ client, isActive }, { groupId, userId, action, signal }) {
|
|
27
|
+
const member = await inspectGroupMember(client, { groupId: groupId, userId: userId, signal: signal });
|
|
27
28
|
signal.throwIfAborted();
|
|
28
29
|
if (!isActive() || !member.canModerate)
|
|
29
30
|
throw new Error('Group moderation permission is unavailable');
|
|
@@ -38,8 +39,8 @@ export async function moderateGroupMember(client, groupId, userId, action, signa
|
|
|
38
39
|
throw new Error('Invalid group mute duration');
|
|
39
40
|
}
|
|
40
41
|
const ok = action.type === 'kick'
|
|
41
|
-
? await client.setGroupKick(numericId(groupId), numericId(userId))
|
|
42
|
-
: await client.setGroupBan(numericId(groupId), numericId(userId), action.durationSeconds);
|
|
42
|
+
? await createEndpointOperation({ signal }).run(() => client.setGroupKick(numericId(groupId), numericId(userId)))
|
|
43
|
+
: await createEndpointOperation({ signal }).run(() => client.setGroupBan(numericId(groupId), numericId(userId), action.durationSeconds));
|
|
43
44
|
if (!ok)
|
|
44
45
|
throw new Error('Platform did not confirm the moderation action');
|
|
45
46
|
}
|
package/lib/group-scene.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { Client } from '@icqqjs/icqq';
|
|
2
|
-
import type
|
|
2
|
+
import { type EndpointGroupInspectionRequest, type EndpointMemberInspectionRequest, type GroupMemberProfile, type GroupSceneFacts } from 'zhin.js/adapter';
|
|
3
3
|
/** Listing a very large roster only to find admins is not worth the packet; adminIds stay unknown. */
|
|
4
4
|
export declare const ADMIN_SCAN_MAX_MEMBERS = 1000;
|
|
5
5
|
/**
|
|
6
6
|
* ADR 0041 scene facts: one uncached group-info read, plus (small groups only) one roster read for
|
|
7
7
|
* admins. A roster failure leaves adminIds unknown instead of failing the other facts.
|
|
8
8
|
*/
|
|
9
|
-
export declare function inspectGroupScene(client: Client, groupId
|
|
9
|
+
export declare function inspectGroupScene(client: Client, { groupId, signal }: EndpointGroupInspectionRequest): Promise<GroupSceneFacts>;
|
|
10
10
|
/** ADR 0041 member facts from one uncached lookup (same rationale as the agent `freshMember` helper). */
|
|
11
|
-
export declare function inspectGroupMemberProfile(client: Client, groupId
|
|
11
|
+
export declare function inspectGroupMemberProfile(client: Client, { groupId, userId, signal }: EndpointMemberInspectionRequest): Promise<GroupMemberProfile>;
|
package/lib/group-scene.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createEndpointOperation } from 'zhin.js/adapter';
|
|
1
2
|
/** Listing a very large roster only to find admins is not worth the packet; adminIds stay unknown. */
|
|
2
3
|
export const ADMIN_SCAN_MAX_MEMBERS = 1000;
|
|
3
4
|
const MAX_ADMIN_IDS = 20;
|
|
@@ -14,10 +15,10 @@ function numericId(value) {
|
|
|
14
15
|
* ADR 0041 scene facts: one uncached group-info read, plus (small groups only) one roster read for
|
|
15
16
|
* admins. A roster failure leaves adminIds unknown instead of failing the other facts.
|
|
16
17
|
*/
|
|
17
|
-
export async function inspectGroupScene(client, groupId, signal) {
|
|
18
|
-
signal
|
|
18
|
+
export async function inspectGroupScene(client, { groupId, signal }) {
|
|
19
|
+
const operation = createEndpointOperation({ signal });
|
|
19
20
|
const group = numericId(groupId);
|
|
20
|
-
const info = await client.getGroupInfo(group, true);
|
|
21
|
+
const info = await operation.run(() => client.getGroupInfo(group, true));
|
|
21
22
|
signal.throwIfAborted();
|
|
22
23
|
if (info.group_id !== group)
|
|
23
24
|
return {};
|
|
@@ -26,7 +27,7 @@ export async function inspectGroupScene(client, groupId, signal) {
|
|
|
26
27
|
let adminIds;
|
|
27
28
|
if (memberCount === undefined || memberCount <= ADMIN_SCAN_MAX_MEMBERS) {
|
|
28
29
|
try {
|
|
29
|
-
const roster = await client.getGroupMemberList(group);
|
|
30
|
+
const roster = await operation.run(() => client.getGroupMemberList(group));
|
|
30
31
|
signal.throwIfAborted();
|
|
31
32
|
adminIds = [...roster.values()]
|
|
32
33
|
.filter(member => member.role === 'admin' && member.group_id === group)
|
|
@@ -50,11 +51,11 @@ export async function inspectGroupScene(client, groupId, signal) {
|
|
|
50
51
|
};
|
|
51
52
|
}
|
|
52
53
|
/** ADR 0041 member facts from one uncached lookup (same rationale as the agent `freshMember` helper). */
|
|
53
|
-
export async function inspectGroupMemberProfile(client, groupId, userId, signal) {
|
|
54
|
-
signal
|
|
54
|
+
export async function inspectGroupMemberProfile(client, { groupId, userId, signal }) {
|
|
55
|
+
const operation = createEndpointOperation({ signal });
|
|
55
56
|
const group = numericId(groupId);
|
|
56
57
|
const user = numericId(userId);
|
|
57
|
-
const member = await client.getGroupMemberInfo(group, user, true);
|
|
58
|
+
const member = await operation.run(() => client.getGroupMemberInfo(group, user, true));
|
|
58
59
|
signal.throwIfAborted();
|
|
59
60
|
if (member.user_id !== user || member.group_id !== group)
|
|
60
61
|
return {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Locale } from 'zhin.js/i18n';
|
|
2
|
-
import type { LoginAssist, LoginAssistType } from '@zhin.js/core';
|
|
2
|
+
import type { LoginAssist, LoginAssistEndpointIdentity, LoginAssistType } from '@zhin.js/core';
|
|
3
3
|
type IcqqLoginClient = {
|
|
4
4
|
login(password?: string): Promise<unknown>;
|
|
5
5
|
submitSlider(ticket: string): Promise<unknown>;
|
|
@@ -21,6 +21,8 @@ export declare function runIcqqLoginAssistStep(input: {
|
|
|
21
21
|
adapter: string;
|
|
22
22
|
endpointKey: string;
|
|
23
23
|
owner: object;
|
|
24
|
+
signal?: AbortSignal;
|
|
25
|
+
endpointIdentity?: LoginAssistEndpointIdentity;
|
|
24
26
|
logger: Logger;
|
|
25
27
|
step: LoginAssistType;
|
|
26
28
|
event: unknown;
|
package/lib/icqq-login-assist.js
CHANGED
|
@@ -17,6 +17,7 @@ export async function runIcqqLoginAssistStep(input) {
|
|
|
17
17
|
...(typeof payload.url === 'string' ? { url: payload.url } : {}),
|
|
18
18
|
}));
|
|
19
19
|
try {
|
|
20
|
+
input.signal?.throwIfAborted();
|
|
20
21
|
if (step === 'device') {
|
|
21
22
|
try {
|
|
22
23
|
await client.sendSmsCode();
|
|
@@ -29,7 +30,8 @@ export async function runIcqqLoginAssistStep(input) {
|
|
|
29
30
|
}));
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
|
-
const value = await assist.waitForInput(adapter, endpointKey, step, payload, { owner });
|
|
33
|
+
const value = await assist.waitForInput(adapter, endpointKey, step, payload, { owner, signal: input.signal, endpointIdentity: input.endpointIdentity });
|
|
34
|
+
input.signal?.throwIfAborted();
|
|
33
35
|
const text = normalizeSubmitValue(value);
|
|
34
36
|
switch (step) {
|
|
35
37
|
case 'qrcode':
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FeatureId, PluginId } from 'zhin.js';
|
|
1
2
|
import type { PendingLoginTask } from '@zhin.js/core';
|
|
2
3
|
export interface IcqqLoginControlState {
|
|
3
4
|
readonly endpointId: string;
|
|
@@ -14,5 +15,10 @@ export interface IcqqLoginControl {
|
|
|
14
15
|
submit(taskId: string, value: string | Record<string, unknown>): boolean;
|
|
15
16
|
cancel(taskId: string, reason?: string): boolean;
|
|
16
17
|
}
|
|
17
|
-
/**
|
|
18
|
-
export declare
|
|
18
|
+
/** Read the owning Adapter's actual incarnations; this projection retains no independent directory. */
|
|
19
|
+
export declare function icqqLoginControls(context: Readonly<{
|
|
20
|
+
owner: PluginId | Readonly<{
|
|
21
|
+
id: PluginId;
|
|
22
|
+
}>;
|
|
23
|
+
project<T>(id: FeatureId): T;
|
|
24
|
+
}>): ReadonlyMap<string, IcqqLoginControl>;
|
|
@@ -1,8 +1,25 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* ICQQ login control surface exposed to the Plugin Runtime, Console and the
|
|
3
|
-
* recovery command.
|
|
4
|
-
*
|
|
3
|
+
* recovery command. Controls are projected from actual current incarnations in
|
|
4
|
+
* the owning IcqqAdapter; no plugin resource keeps a second Endpoint directory.
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
import { adapterFeatureId, isAdapterIndex } from 'zhin.js/adapter';
|
|
7
|
+
import { IcqqAdapter } from './adapter.js';
|
|
8
|
+
/** Read the owning Adapter's actual incarnations; this projection retains no independent directory. */
|
|
9
|
+
export function icqqLoginControls(context) {
|
|
10
|
+
const index = context.project(adapterFeatureId);
|
|
11
|
+
if (!isAdapterIndex(index))
|
|
12
|
+
throw new Error('ICQQ Adapter projection is unavailable');
|
|
13
|
+
const owner = typeof context.owner === 'string' ? context.owner : context.owner.id;
|
|
14
|
+
const controls = new Map();
|
|
15
|
+
for (const adapter of index.forOwner(owner).adapters()) {
|
|
16
|
+
if (!(adapter instanceof IcqqAdapter))
|
|
17
|
+
continue;
|
|
18
|
+
for (const row of adapter.list()) {
|
|
19
|
+
const endpoint = adapter.getEndpoint(row.instanceId);
|
|
20
|
+
if (endpoint)
|
|
21
|
+
controls.set(row.endpointId, endpoint.loginControl);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return controls;
|
|
25
|
+
}
|
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { Actions, formatInboundContent, formatOutboundBody, formatOutboundMessages, formatOutboundMessageParts, icqqInboundConversation, icqqOutboundTarget, type ActionResult, type IcqqEndpointConfig, type IcqqInboundMessage, type IcqqWireSegment, type IcqqOutboundMessagePart, type ParsedIcqqSendTarget, type ResolvedIcqqConfig, } from './protocol.js';
|
|
2
2
|
export { IcqqEndpoint, type IcqqEndpointOptions, } from './endpoint.js';
|
|
3
3
|
export * from './types.js';
|
|
4
|
-
export {
|
|
4
|
+
export { type IcqqClient, type IcqqClientEventMap, } from './client.js';
|
|
5
5
|
export { resolveIcqqInboundMessageId, } from './icqq-inbound.js';
|
|
6
|
+
export { IcqqAdapter } from './adapter.js';
|
package/lib/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { Actions, formatInboundContent, formatOutboundBody, formatOutboundMessages, formatOutboundMessageParts, icqqInboundConversation, icqqOutboundTarget, } from './protocol.js';
|
|
2
2
|
export { IcqqEndpoint, } from './endpoint.js';
|
|
3
3
|
export * from './types.js';
|
|
4
|
-
export { icqqClient, } from './client.js';
|
|
5
4
|
export { resolveIcqqInboundMessageId, } from './icqq-inbound.js';
|
|
5
|
+
export { IcqqAdapter } from './adapter.js';
|
package/lib/protocol.d.ts
CHANGED
|
@@ -205,6 +205,9 @@ export interface IcqqWireSegment {
|
|
|
205
205
|
readonly platform?: Readonly<Record<string, unknown>>;
|
|
206
206
|
}
|
|
207
207
|
export interface IcqqInboundMessage {
|
|
208
|
+
/** Exact SDK callback object, operation-local and never a persisted projection. */
|
|
209
|
+
readonly event?: unknown;
|
|
210
|
+
readonly platformSentAt?: number;
|
|
208
211
|
readonly id: string;
|
|
209
212
|
readonly conversation: ConversationRef;
|
|
210
213
|
readonly content: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zhin.js/adapter-icqq",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.20",
|
|
4
4
|
"description": "Zhin.js ICQQ adapter — direct connection to @icqqjs/icqq",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -33,27 +33,27 @@
|
|
|
33
33
|
"directory": "plugins/adapters/icqq"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@zhin.js/adapter": "1.1.
|
|
37
|
-
"@zhin.js/agent-feature": "1.1.
|
|
38
|
-
"@zhin.js/client": "1.1.
|
|
36
|
+
"@zhin.js/adapter": "1.1.26",
|
|
37
|
+
"@zhin.js/agent-feature": "1.1.11",
|
|
38
|
+
"@zhin.js/client": "1.1.22",
|
|
39
39
|
"@zhin.js/console-contract": "1.1.3",
|
|
40
|
-
"@zhin.js/core": "1.1.
|
|
41
|
-
"@zhin.js/feature-kit": "1.1.
|
|
40
|
+
"@zhin.js/core": "1.1.54",
|
|
41
|
+
"@zhin.js/feature-kit": "1.1.10",
|
|
42
42
|
"@zhin.js/im-contract": "1.1.9",
|
|
43
43
|
"@zhin.js/logger": "1.1.2",
|
|
44
|
-
"@zhin.js/page": "1.1.
|
|
45
|
-
"@zhin.js/permission": "1.1.
|
|
46
|
-
"@zhin.js/skill": "1.1.
|
|
47
|
-
"@zhin.js/tool": "1.1.
|
|
44
|
+
"@zhin.js/page": "1.1.12",
|
|
45
|
+
"@zhin.js/permission": "1.1.10",
|
|
46
|
+
"@zhin.js/skill": "1.1.11",
|
|
47
|
+
"@zhin.js/tool": "1.1.13"
|
|
48
48
|
},
|
|
49
49
|
"peerDependencies": {
|
|
50
50
|
"@icqqjs/icqq": "^1.12.2",
|
|
51
51
|
"zod": "^4.0.0",
|
|
52
|
-
"@zhin.js/adapter": "^1.1.
|
|
53
|
-
"@zhin.js/command": "^1.1.
|
|
54
|
-
"@zhin.js/core": "^1.1.
|
|
55
|
-
"@zhin.js/prompt-section": "^1.1.
|
|
56
|
-
"zhin.js": "^1.1.
|
|
52
|
+
"@zhin.js/adapter": "^1.1.26",
|
|
53
|
+
"@zhin.js/command": "^1.1.12",
|
|
54
|
+
"@zhin.js/core": "^1.1.54",
|
|
55
|
+
"@zhin.js/prompt-section": "^1.1.10",
|
|
56
|
+
"zhin.js": "^1.1.19"
|
|
57
57
|
},
|
|
58
58
|
"peerDependenciesMeta": {
|
|
59
59
|
"@icqqjs/icqq": {
|
|
@@ -78,8 +78,8 @@
|
|
|
78
78
|
"typescript": "^6.0.3",
|
|
79
79
|
"vitest": "^4.1.10",
|
|
80
80
|
"zod": "^4.4.3",
|
|
81
|
-
"@zhin.js/prompt-section": "1.1.
|
|
82
|
-
"zhin.js": "1.1.
|
|
81
|
+
"@zhin.js/prompt-section": "1.1.10",
|
|
82
|
+
"zhin.js": "1.1.19"
|
|
83
83
|
},
|
|
84
84
|
"files": [
|
|
85
85
|
"adapters",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"features": [
|
|
112
112
|
{
|
|
113
113
|
"package": "@zhin.js/adapter",
|
|
114
|
-
"api": "^
|
|
114
|
+
"api": "^2.0.0"
|
|
115
115
|
},
|
|
116
116
|
{
|
|
117
117
|
"package": "@zhin.js/command",
|
package/plugin.js
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
// Generated by build-plugin-runtime-entries.mjs. Do not edit.
|
|
2
|
-
import { createEndpointRuntimeState } from 'zhin.js/adapter';
|
|
3
2
|
import { definePlugin, pluginConsoleRpcToken } from 'zhin.js';
|
|
4
3
|
import { permissionHostToken, createSceneRolePlatformChecker } from '@zhin.js/permission';
|
|
5
|
-
import { icqqRuntimeStateToken } from "./lib/icqq-runtime-state.js";
|
|
6
|
-
import { icqqLoginControlToken } from "./lib/icqq-login-control.js";
|
|
7
4
|
import { createIcqqConsoleRpc } from "./lib/console.js";
|
|
8
5
|
export default definePlugin({
|
|
9
6
|
name: 'icqq',
|
|
@@ -11,11 +8,7 @@ export default definePlugin({
|
|
|
11
8
|
displayName: 'ICQQ Adapter',
|
|
12
9
|
},
|
|
13
10
|
setup(context) {
|
|
14
|
-
|
|
15
|
-
context.resources.provide(icqqRuntimeStateToken, createEndpointRuntimeState());
|
|
16
|
-
// 掉线恢复命令用:当前 generation 每个 UIN 的登录控制面
|
|
17
|
-
context.resources.provide(icqqLoginControlToken, new Map());
|
|
18
|
-
context.resources.provide(pluginConsoleRpcToken, createIcqqConsoleRpc(context.resources, () => context.config.get()));
|
|
11
|
+
context.resources.provide(pluginConsoleRpcToken, createIcqqConsoleRpc(() => context.config.get()));
|
|
19
12
|
const disposePlatform = context.resources.has(permissionHostToken)
|
|
20
13
|
? context.resources.use(permissionHostToken).registerPlatform('icqq', createSceneRolePlatformChecker())
|
|
21
14
|
: undefined;
|
package/src/adapter.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Adapter, createAdapterOutageNotifier, type AdapterContext, type EndpointCreationContext } from 'zhin.js/adapter';
|
|
2
|
+
import { projectLocaleToken } from 'zhin.js/i18n';
|
|
3
|
+
import { loginAssistToken } from '@zhin.js/core/runtime';
|
|
4
|
+
import { outboundHostToken } from 'zhin.js';
|
|
5
|
+
import { IcqqEndpoint } from './endpoint.js';
|
|
6
|
+
import { resolveIcqqConfig, type IcqqEndpointConfig } from './protocol.js';
|
|
7
|
+
import type { IcqqClientEventMap } from './client.js';
|
|
8
|
+
|
|
9
|
+
/** ICQQ account construction and actual SDK ownership belong to this Adapter. */
|
|
10
|
+
export class IcqqAdapter extends Adapter<IcqqEndpoint, IcqqEndpointConfig, IcqqClientEventMap> {
|
|
11
|
+
override get configurationIdentityFields(): readonly string[] { return ['id']; }
|
|
12
|
+
override get configurationUpdateFields(): readonly string[] {
|
|
13
|
+
return ['password', 'platform', 'ver', 'dataDir', 'signApiAddr', 'autoReconnect', 'autoServer', 'qqnt', 'ntLogin'];
|
|
14
|
+
}
|
|
15
|
+
readonly #context: AdapterContext<IcqqEndpointConfig>;
|
|
16
|
+
constructor(context: AdapterContext<IcqqEndpointConfig>) { super(); this.#context = context; }
|
|
17
|
+
protected override validateConfiguration(config: IcqqEndpointConfig): void { resolveIcqqConfig(config); }
|
|
18
|
+
protected createEndpoint(input: IcqqEndpointConfig, execution: EndpointCreationContext): IcqqEndpoint {
|
|
19
|
+
const context = this.#context;
|
|
20
|
+
const config = resolveIcqqConfig(input);
|
|
21
|
+
const outbound = context.has?.(outboundHostToken) ? context.use(outboundHostToken) : undefined;
|
|
22
|
+
const endpoint = new IcqqEndpoint({ id: execution.canonicalId, config,
|
|
23
|
+
signal: execution.signal, endpointIdentity: { canonicalId: execution.canonicalId, instanceId: execution.instanceId, epoch: execution.epoch, incarnationId: execution.incarnationId },
|
|
24
|
+
loginAssist: context.use(loginAssistToken), locale: context.use(projectLocaleToken),
|
|
25
|
+
notifier: createAdapterOutageNotifier(outbound, config.notify),
|
|
26
|
+
});
|
|
27
|
+
return endpoint;
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/client.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { IcqqAdapter } from './adapter.js';
|
|
2
|
+
import type { IcqqEndpoint } from './endpoint.js';
|
|
3
|
+
import type { EventMap } from '@icqqjs/icqq';
|
|
3
4
|
|
|
4
5
|
type EventPayload<TListener> = TListener extends (
|
|
5
6
|
event: infer TEvent,
|
|
@@ -9,7 +10,7 @@ type EventPayload<TListener> = TListener extends (
|
|
|
9
10
|
: never;
|
|
10
11
|
|
|
11
12
|
/** The actual ICQQ SDK instance exposed by every ICQQ Endpoint event. */
|
|
12
|
-
export type IcqqClient =
|
|
13
|
+
export type IcqqClient = IcqqEndpoint;
|
|
13
14
|
|
|
14
15
|
/** Native ICQQ event-name → first public event payload, derived from the SDK SSOT. */
|
|
15
16
|
export type IcqqClientEventMap = {
|
|
@@ -17,13 +18,7 @@ export type IcqqClientEventMap = {
|
|
|
17
18
|
};
|
|
18
19
|
|
|
19
20
|
declare module '@zhin.js/feature-kit' {
|
|
20
|
-
interface
|
|
21
|
-
readonly icqq:
|
|
22
|
-
readonly client: IcqqClient;
|
|
23
|
-
readonly events: IcqqClientEventMap;
|
|
24
|
-
};
|
|
21
|
+
interface AdapterRegistry {
|
|
22
|
+
readonly icqq: IcqqAdapter;
|
|
25
23
|
}
|
|
26
24
|
}
|
|
27
|
-
|
|
28
|
-
/** Typed, generation-checked identity used by handlers, commands, tools and schedules. */
|
|
29
|
-
export const icqqClient = defineEndpointClient<IcqqClient, IcqqClientEventMap>('icqq');
|
package/src/console-spec.ts
CHANGED
|
@@ -7,6 +7,15 @@ export const icqqConsoleSpec = {
|
|
|
7
7
|
adapterKey: 'icqq',
|
|
8
8
|
adapterDisplayName: 'ICQQ',
|
|
9
9
|
fields: [
|
|
10
|
+
{ key: 'password', env: true, description: 'QQ password; leave blank to retain the saved credential' },
|
|
11
|
+
{ key: 'platform', type: 'number', description: 'ICQQ platform number' },
|
|
12
|
+
{ key: 'ver', description: 'ICQQ protocol version' },
|
|
13
|
+
{ key: 'dataDir', description: 'ICQQ device and session directory' },
|
|
14
|
+
{ key: 'signApiAddr', description: 'ICQQ signing service URL' },
|
|
15
|
+
{ key: 'autoReconnect', type: 'boolean', description: 'ICQQ reconnect setting' },
|
|
16
|
+
{ key: 'autoServer', type: 'boolean', description: 'ICQQ automatic server selection' },
|
|
17
|
+
{ key: 'qqnt', type: 'boolean', description: 'QQNT protocol' },
|
|
18
|
+
{ key: 'ntLogin', type: 'boolean', description: 'QQNT login' },
|
|
10
19
|
] as readonly AdapterConsoleField[],
|
|
11
20
|
docsUrl: 'https://zhin.js.org/adapters/icqq',
|
|
12
21
|
readPermission: 'icqq:read',
|
package/src/console.ts
CHANGED
|
@@ -3,19 +3,15 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 页面绑定 `pages/index`,读取 / 写入分别要求 `<adapter>:read` / `<adapter>:write`。
|
|
5
5
|
*/
|
|
6
|
-
import { createAdapterConsoleRpc
|
|
6
|
+
import { createAdapterConsoleRpc } from 'zhin.js/adapter';
|
|
7
7
|
import type { PluginConsoleRpc } from 'zhin.js';
|
|
8
|
-
import { icqqRuntimeStateToken } from './icqq-runtime-state.js';
|
|
9
8
|
import { icqqConsoleSpec } from './console-spec.js';
|
|
10
9
|
|
|
11
10
|
export function createIcqqConsoleRpc(
|
|
12
|
-
resources: AdapterConsoleResources,
|
|
13
11
|
getConfig: () => unknown,
|
|
14
12
|
): PluginConsoleRpc {
|
|
15
|
-
const state = resources.use(icqqRuntimeStateToken);
|
|
16
13
|
return createAdapterConsoleRpc({
|
|
17
14
|
...icqqConsoleSpec,
|
|
18
|
-
running: () => state.endpoints.values(),
|
|
19
15
|
getConfig,
|
|
20
|
-
}
|
|
16
|
+
});
|
|
21
17
|
}
|