alemonjs 2.1.6 → 2.1.8
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/lib/cbp/core/connection-manager.d.ts +18 -0
- package/lib/cbp/core/connection-manager.js +67 -0
- package/lib/cbp/core/constants.d.ts +19 -0
- package/lib/cbp/core/constants.js +23 -0
- package/lib/cbp/core/load-balancer.d.ts +37 -0
- package/lib/cbp/core/load-balancer.js +118 -0
- package/lib/cbp/processor/request-handler.d.ts +17 -0
- package/lib/cbp/processor/request-handler.js +65 -0
- package/lib/cbp/server/main.js +4 -8
- package/lib/main.js +1 -1
- package/lib/types/event/channal/index.d.ts +1 -1
- package/lib/types/event/map.d.ts +1 -1
- package/package.json +3 -2
- package/lib/adapter.js +0 -111
- package/lib/app/load.d.ts +0 -14
- package/lib/app/load.js +0 -167
- package/lib/cbp/actions.js +0 -48
- package/lib/cbp/api.js +0 -48
- package/lib/cbp/client.d.ts +0 -10
- package/lib/cbp/client.js +0 -159
- package/lib/cbp/config.js +0 -43
- package/lib/cbp/connect.d.ts +0 -27
- package/lib/cbp/connect.js +0 -62
- package/lib/cbp/hello.html.js +0 -47
- package/lib/cbp/platform.d.ts +0 -18
- package/lib/cbp/platform.js +0 -170
- package/lib/cbp/processor/hello.html.d.ts +0 -1
- package/lib/cbp/processor/hello.html.js +0 -47
- package/lib/cbp/router.js +0 -297
- package/lib/cbp/routers/middleware.d.ts +0 -2
- package/lib/cbp/routers/middleware.js +0 -40
- package/lib/cbp/routers/utils.d.ts +0 -2
- package/lib/cbp/routers/utils.js +0 -39
- package/lib/cbp/server.d.ts +0 -8
- package/lib/cbp/server.js +0 -449
- package/lib/cbp/testone.js +0 -288
- package/lib/core/code.d.ts +0 -16
- package/lib/core/code.js +0 -17
- package/lib/datastructure/SinglyLinkedList.d.ts +0 -17
- package/lib/datastructure/SinglyLinkedList.js +0 -73
- package/lib/typing/actions.d.ts +0 -93
- package/lib/typing/apis.d.ts +0 -18
- package/lib/typing/client/index.d.ts +0 -67
- package/lib/typing/cycle/index.d.ts +0 -42
- package/lib/typing/event/actions.d.ts +0 -37
- package/lib/typing/event/actions.js +0 -72
- package/lib/typing/event/base/expansion.d.ts +0 -5
- package/lib/typing/event/base/guild.d.ts +0 -18
- package/lib/typing/event/base/message.d.ts +0 -28
- package/lib/typing/event/base/platform.d.ts +0 -16
- package/lib/typing/event/base/user.d.ts +0 -34
- package/lib/typing/event/channal/index.d.ts +0 -13
- package/lib/typing/event/guild/index.d.ts +0 -13
- package/lib/typing/event/index.d.ts +0 -94
- package/lib/typing/event/interaction/index.d.ts +0 -14
- package/lib/typing/event/map.d.ts +0 -36
- package/lib/typing/event/member/index.d.ts +0 -14
- package/lib/typing/event/message/message.d.ts +0 -23
- package/lib/typing/event/message/private.message.d.ts +0 -16
- package/lib/typing/event/request/index.d.ts +0 -13
- package/lib/typing/logger/index.d.ts +0 -49
- package/lib/typing/message/ark.d.ts +0 -46
- package/lib/typing/message/button.d.ts +0 -32
- package/lib/typing/message/image.d.ts +0 -23
- package/lib/typing/message/index.d.ts +0 -16
- package/lib/typing/message/link.d.ts +0 -12
- package/lib/typing/message/markdown.d.ts +0 -91
- package/lib/typing/message/mention.d.ts +0 -16
- package/lib/typing/message/text.d.ts +0 -12
- package/lib/typing/package/index.d.ts +0 -12
- package/lib/typing/state/index.d.ts +0 -5
- package/lib/typing/store/res.d.ts +0 -75
- package/lib/typing/subscribe/index.d.ts +0 -30
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { WebSocket } from 'ws';
|
|
2
|
+
export interface ConnectionState {
|
|
3
|
+
connections: Map<string, WebSocket>;
|
|
4
|
+
lastActivity: Map<string, number>;
|
|
5
|
+
metadata: Map<string, any>;
|
|
6
|
+
}
|
|
7
|
+
export declare const createConnectionState: () => ConnectionState;
|
|
8
|
+
export declare const addConnection: (state: ConnectionState, id: string, ws: WebSocket, metadata?: any) => ConnectionState;
|
|
9
|
+
export declare const removeConnection: (state: ConnectionState, id: string) => ConnectionState;
|
|
10
|
+
export declare const getConnection: (state: ConnectionState, id: string) => WebSocket | undefined;
|
|
11
|
+
export declare const getHealthyConnectionIds: (state: ConnectionState) => string[];
|
|
12
|
+
export declare const getConnectionStats: (state: ConnectionState) => {
|
|
13
|
+
total: number;
|
|
14
|
+
healthy: number;
|
|
15
|
+
unhealthy: number;
|
|
16
|
+
lastUpdate: number;
|
|
17
|
+
};
|
|
18
|
+
export declare const clearAllConnections: (state: ConnectionState) => ConnectionState;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { WebSocket } from 'ws';
|
|
2
|
+
|
|
3
|
+
const createConnectionState = () => ({
|
|
4
|
+
connections: new Map(),
|
|
5
|
+
lastActivity: new Map(),
|
|
6
|
+
metadata: new Map()
|
|
7
|
+
});
|
|
8
|
+
const addConnection = (state, id, ws, metadata) => {
|
|
9
|
+
const newState = {
|
|
10
|
+
connections: new Map(state.connections),
|
|
11
|
+
lastActivity: new Map(state.lastActivity),
|
|
12
|
+
metadata: new Map(state.metadata)
|
|
13
|
+
};
|
|
14
|
+
newState.connections.set(id, ws);
|
|
15
|
+
newState.lastActivity.set(id, Date.now());
|
|
16
|
+
if (metadata) {
|
|
17
|
+
newState.metadata.set(id, metadata);
|
|
18
|
+
}
|
|
19
|
+
return newState;
|
|
20
|
+
};
|
|
21
|
+
const removeConnection = (state, id) => {
|
|
22
|
+
const newState = {
|
|
23
|
+
connections: new Map(state.connections),
|
|
24
|
+
lastActivity: new Map(state.lastActivity),
|
|
25
|
+
metadata: new Map(state.metadata)
|
|
26
|
+
};
|
|
27
|
+
const ws = newState.connections.get(id);
|
|
28
|
+
if (ws && ws.readyState === WebSocket.OPEN) {
|
|
29
|
+
ws.close();
|
|
30
|
+
}
|
|
31
|
+
newState.connections.delete(id);
|
|
32
|
+
newState.lastActivity.delete(id);
|
|
33
|
+
newState.metadata.delete(id);
|
|
34
|
+
return newState;
|
|
35
|
+
};
|
|
36
|
+
const getConnection = (state, id) => {
|
|
37
|
+
return state.connections.get(id);
|
|
38
|
+
};
|
|
39
|
+
const getHealthyConnectionIds = (state) => {
|
|
40
|
+
const healthyIds = [];
|
|
41
|
+
for (const [id, ws] of state.connections.entries()) {
|
|
42
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
43
|
+
healthyIds.push(id);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return healthyIds;
|
|
47
|
+
};
|
|
48
|
+
const getConnectionStats = (state) => {
|
|
49
|
+
const total = state.connections.size;
|
|
50
|
+
const healthy = getHealthyConnectionIds(state).length;
|
|
51
|
+
return {
|
|
52
|
+
total,
|
|
53
|
+
healthy,
|
|
54
|
+
unhealthy: total - healthy,
|
|
55
|
+
lastUpdate: Date.now()
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
const clearAllConnections = (state) => {
|
|
59
|
+
for (const ws of state.connections.values()) {
|
|
60
|
+
if (ws.readyState === WebSocket.OPEN) {
|
|
61
|
+
ws.close();
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return createConnectionState();
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export { addConnection, clearAllConnections, createConnectionState, getConnection, getConnectionStats, getHealthyConnectionIds, removeConnection };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export declare const USER_AGENT_HEADER = "user-agent";
|
|
2
|
+
export declare const DEVICE_ID_HEADER = "x-device-id";
|
|
3
|
+
export declare const FULL_RECEIVE_HEADER = "x-full-receive";
|
|
4
|
+
export declare const USER_AGENT_HEADER_VALUE_MAP: {
|
|
5
|
+
readonly platform: "platform";
|
|
6
|
+
readonly client: "client";
|
|
7
|
+
readonly testone: "testone";
|
|
8
|
+
};
|
|
9
|
+
export declare const TIME_CONFIG: {
|
|
10
|
+
readonly TIMEOUT: number;
|
|
11
|
+
readonly RECONNECT_INTERVAL: number;
|
|
12
|
+
readonly HEARTBEAT_INTERVAL: number;
|
|
13
|
+
};
|
|
14
|
+
export declare const HEALTH_CHECK_CONFIG: {
|
|
15
|
+
readonly INTERVAL: 30000;
|
|
16
|
+
readonly MAX_CONSECUTIVE_FAILURES: 3;
|
|
17
|
+
readonly PING_TIMEOUT: 5000;
|
|
18
|
+
};
|
|
19
|
+
export declare const generateUniqueId: () => string;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const USER_AGENT_HEADER = 'user-agent';
|
|
2
|
+
const DEVICE_ID_HEADER = 'x-device-id';
|
|
3
|
+
const FULL_RECEIVE_HEADER = 'x-full-receive';
|
|
4
|
+
const USER_AGENT_HEADER_VALUE_MAP = {
|
|
5
|
+
platform: 'platform',
|
|
6
|
+
client: 'client',
|
|
7
|
+
testone: 'testone'
|
|
8
|
+
};
|
|
9
|
+
const TIME_CONFIG = {
|
|
10
|
+
TIMEOUT: 1000 * 60 * 3,
|
|
11
|
+
RECONNECT_INTERVAL: 1000 * 6,
|
|
12
|
+
HEARTBEAT_INTERVAL: 1000 * 18
|
|
13
|
+
};
|
|
14
|
+
const HEALTH_CHECK_CONFIG = {
|
|
15
|
+
INTERVAL: 30000,
|
|
16
|
+
MAX_CONSECUTIVE_FAILURES: 3,
|
|
17
|
+
PING_TIMEOUT: 5000
|
|
18
|
+
};
|
|
19
|
+
const generateUniqueId = () => {
|
|
20
|
+
return Date.now().toString(36) + Math.random().toString(36).substring(2);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export { DEVICE_ID_HEADER, FULL_RECEIVE_HEADER, HEALTH_CHECK_CONFIG, TIME_CONFIG, USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE_MAP, generateUniqueId };
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { ConnectionState } from './connection-manager';
|
|
2
|
+
export type LoadBalanceStrategy = 'round-robin' | 'least-connections' | 'random' | 'first-available';
|
|
3
|
+
export declare const LoadBalanceStrategyEnum: {
|
|
4
|
+
readonly ROUND_ROBIN: "round-robin";
|
|
5
|
+
readonly LEAST_CONNECTIONS: "least-connections";
|
|
6
|
+
readonly RANDOM: "random";
|
|
7
|
+
readonly FIRST_AVAILABLE: "first-available";
|
|
8
|
+
};
|
|
9
|
+
export interface LoadBalancerState {
|
|
10
|
+
strategy: LoadBalanceStrategy;
|
|
11
|
+
roundRobinIndex: number;
|
|
12
|
+
bindingCounts: Map<string, number>;
|
|
13
|
+
}
|
|
14
|
+
export declare const createLoadBalancerState: (strategy?: LoadBalanceStrategy) => LoadBalancerState;
|
|
15
|
+
export declare const selectByRoundRobin: (availableIds: string[], currentIndex: number) => {
|
|
16
|
+
selectedId: string | null;
|
|
17
|
+
nextIndex: number;
|
|
18
|
+
};
|
|
19
|
+
export declare const selectByLeastConnections: (availableIds: string[], bindingCounts: Map<string, number>) => string | null;
|
|
20
|
+
export declare const selectByRandom: (availableIds: string[]) => string | null;
|
|
21
|
+
export declare const selectFirstAvailable: (availableIds: string[]) => string | null;
|
|
22
|
+
export declare const selectConnection: (connectionState: ConnectionState, balancerState: LoadBalancerState) => {
|
|
23
|
+
selectedId: string | null;
|
|
24
|
+
newBalancerState: LoadBalancerState;
|
|
25
|
+
};
|
|
26
|
+
export declare const incrementBindingCount: (balancerState: LoadBalancerState, connectionId: string) => LoadBalancerState;
|
|
27
|
+
export declare const decrementBindingCount: (balancerState: LoadBalancerState, connectionId: string) => LoadBalancerState;
|
|
28
|
+
export declare const getLoadBalancerStats: (balancerState: LoadBalancerState) => {
|
|
29
|
+
strategy: LoadBalanceStrategy;
|
|
30
|
+
roundRobinIndex: number;
|
|
31
|
+
totalConnections: number;
|
|
32
|
+
totalBindings: number;
|
|
33
|
+
bindingCounts: {
|
|
34
|
+
[k: string]: number;
|
|
35
|
+
};
|
|
36
|
+
lastUpdate: number;
|
|
37
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { getHealthyConnectionIds } from './connection-manager.js';
|
|
2
|
+
|
|
3
|
+
const LoadBalanceStrategyEnum = {
|
|
4
|
+
ROUND_ROBIN: 'round-robin',
|
|
5
|
+
LEAST_CONNECTIONS: 'least-connections',
|
|
6
|
+
RANDOM: 'random',
|
|
7
|
+
FIRST_AVAILABLE: 'first-available'
|
|
8
|
+
};
|
|
9
|
+
const createLoadBalancerState = (strategy = 'round-robin') => ({
|
|
10
|
+
strategy,
|
|
11
|
+
roundRobinIndex: 0,
|
|
12
|
+
bindingCounts: new Map()
|
|
13
|
+
});
|
|
14
|
+
const selectByRoundRobin = (availableIds, currentIndex) => {
|
|
15
|
+
if (availableIds.length === 0) {
|
|
16
|
+
return { selectedId: null, nextIndex: currentIndex };
|
|
17
|
+
}
|
|
18
|
+
const selectedId = availableIds[currentIndex % availableIds.length];
|
|
19
|
+
const nextIndex = (currentIndex + 1) % availableIds.length;
|
|
20
|
+
return { selectedId, nextIndex };
|
|
21
|
+
};
|
|
22
|
+
const selectByLeastConnections = (availableIds, bindingCounts) => {
|
|
23
|
+
if (availableIds.length === 0) {
|
|
24
|
+
return null;
|
|
25
|
+
}
|
|
26
|
+
let selectedId = availableIds[0];
|
|
27
|
+
let minConnections = bindingCounts.get(selectedId) || 0;
|
|
28
|
+
for (let i = 1; i < availableIds.length; i++) {
|
|
29
|
+
const id = availableIds[i];
|
|
30
|
+
const connections = bindingCounts.get(id) || 0;
|
|
31
|
+
if (connections < minConnections) {
|
|
32
|
+
minConnections = connections;
|
|
33
|
+
selectedId = id;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return selectedId;
|
|
37
|
+
};
|
|
38
|
+
const selectByRandom = (availableIds) => {
|
|
39
|
+
if (availableIds.length === 0) {
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
const randomIndex = Math.floor(Math.random() * availableIds.length);
|
|
43
|
+
return availableIds[randomIndex];
|
|
44
|
+
};
|
|
45
|
+
const selectFirstAvailable = (availableIds) => {
|
|
46
|
+
return availableIds.length > 0 ? availableIds[0] : null;
|
|
47
|
+
};
|
|
48
|
+
const selectConnection = (connectionState, balancerState) => {
|
|
49
|
+
const availableIds = getHealthyConnectionIds(connectionState);
|
|
50
|
+
if (availableIds.length === 0) {
|
|
51
|
+
return { selectedId: null, newBalancerState: balancerState };
|
|
52
|
+
}
|
|
53
|
+
let selectedId = null;
|
|
54
|
+
const newBalancerState = { ...balancerState };
|
|
55
|
+
switch (balancerState.strategy) {
|
|
56
|
+
case 'round-robin': {
|
|
57
|
+
const result = selectByRoundRobin(availableIds, balancerState.roundRobinIndex);
|
|
58
|
+
selectedId = result.selectedId;
|
|
59
|
+
newBalancerState.roundRobinIndex = result.nextIndex;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
case 'least-connections': {
|
|
63
|
+
selectedId = selectByLeastConnections(availableIds, balancerState.bindingCounts);
|
|
64
|
+
break;
|
|
65
|
+
}
|
|
66
|
+
case 'random': {
|
|
67
|
+
selectedId = selectByRandom(availableIds);
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
case 'first-available': {
|
|
71
|
+
selectedId = selectFirstAvailable(availableIds);
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
default: {
|
|
75
|
+
const result = selectByRoundRobin(availableIds, balancerState.roundRobinIndex);
|
|
76
|
+
selectedId = result.selectedId;
|
|
77
|
+
newBalancerState.roundRobinIndex = result.nextIndex;
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { selectedId, newBalancerState };
|
|
82
|
+
};
|
|
83
|
+
const incrementBindingCount = (balancerState, connectionId) => {
|
|
84
|
+
const newBindingCounts = new Map(balancerState.bindingCounts);
|
|
85
|
+
const currentCount = newBindingCounts.get(connectionId) || 0;
|
|
86
|
+
newBindingCounts.set(connectionId, currentCount + 1);
|
|
87
|
+
return {
|
|
88
|
+
...balancerState,
|
|
89
|
+
bindingCounts: newBindingCounts
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
const decrementBindingCount = (balancerState, connectionId) => {
|
|
93
|
+
const newBindingCounts = new Map(balancerState.bindingCounts);
|
|
94
|
+
const currentCount = newBindingCounts.get(connectionId) || 0;
|
|
95
|
+
if (currentCount > 0) {
|
|
96
|
+
newBindingCounts.set(connectionId, currentCount - 1);
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
newBindingCounts.delete(connectionId);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
...balancerState,
|
|
103
|
+
bindingCounts: newBindingCounts
|
|
104
|
+
};
|
|
105
|
+
};
|
|
106
|
+
const getLoadBalancerStats = (balancerState) => {
|
|
107
|
+
const totalBindings = Array.from(balancerState.bindingCounts.values()).reduce((sum, count) => sum + count, 0);
|
|
108
|
+
return {
|
|
109
|
+
strategy: balancerState.strategy,
|
|
110
|
+
roundRobinIndex: balancerState.roundRobinIndex,
|
|
111
|
+
totalConnections: balancerState.bindingCounts.size,
|
|
112
|
+
totalBindings,
|
|
113
|
+
bindingCounts: Object.fromEntries(balancerState.bindingCounts),
|
|
114
|
+
lastUpdate: Date.now()
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export { LoadBalanceStrategyEnum, createLoadBalancerState, decrementBindingCount, getLoadBalancerStats, incrementBindingCount, selectByLeastConnections, selectByRandom, selectByRoundRobin, selectConnection, selectFirstAvailable };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Result } from '../../core';
|
|
2
|
+
type ResolversValue = (value: Result[]) => void;
|
|
3
|
+
export interface RequestHandlerState {
|
|
4
|
+
resolvers: Map<string, ResolversValue>;
|
|
5
|
+
timeouts: Map<string, NodeJS.Timeout>;
|
|
6
|
+
requestType: string;
|
|
7
|
+
idField: 'actionId' | 'apiId';
|
|
8
|
+
}
|
|
9
|
+
export declare const createRequestHandlerState: (requestType: string, idField: "actionId" | "apiId") => RequestHandlerState;
|
|
10
|
+
export declare const sendRequest: <T>(state: RequestHandlerState, data: T & {
|
|
11
|
+
DeviceId?: string;
|
|
12
|
+
}) => Promise<Result[]>;
|
|
13
|
+
export declare const handleRequestResponse: (state: RequestHandlerState, requestId: string, results: Result[]) => void;
|
|
14
|
+
export declare const handleRequestTimeout: (state: RequestHandlerState, requestId: string) => void;
|
|
15
|
+
export declare const getPendingRequestCount: (state: RequestHandlerState) => number;
|
|
16
|
+
export declare const destroyRequestHandler: (state: RequestHandlerState) => void;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import * as flattedJSON from 'flatted';
|
|
2
|
+
import { ResultCode } from '../../core/variable.js';
|
|
3
|
+
import 'fs';
|
|
4
|
+
import 'path';
|
|
5
|
+
import 'yaml';
|
|
6
|
+
import { createResult } from '../../core/utils.js';
|
|
7
|
+
import { deviceId, timeoutTime } from './config.js';
|
|
8
|
+
import { generateUniqueId } from '../core/constants.js';
|
|
9
|
+
|
|
10
|
+
const createRequestHandlerState = (requestType, idField) => ({
|
|
11
|
+
resolvers: new Map(),
|
|
12
|
+
timeouts: new Map(),
|
|
13
|
+
requestType,
|
|
14
|
+
idField
|
|
15
|
+
});
|
|
16
|
+
const sendRequest = (state, data) => {
|
|
17
|
+
const requestId = generateUniqueId();
|
|
18
|
+
return new Promise(resolve => {
|
|
19
|
+
data[state.idField] = requestId;
|
|
20
|
+
data.DeviceId = deviceId;
|
|
21
|
+
global.chatbotClient.send(flattedJSON.stringify(data));
|
|
22
|
+
state.resolvers.set(requestId, resolve);
|
|
23
|
+
const timeout = setTimeout(() => {
|
|
24
|
+
handleRequestTimeout(state, requestId);
|
|
25
|
+
}, timeoutTime);
|
|
26
|
+
state.timeouts.set(requestId, timeout);
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
const handleRequestResponse = (state, requestId, results) => {
|
|
30
|
+
const resolver = state.resolvers.get(requestId);
|
|
31
|
+
const timeout = state.timeouts.get(requestId);
|
|
32
|
+
if (resolver) {
|
|
33
|
+
state.resolvers.delete(requestId);
|
|
34
|
+
if (timeout) {
|
|
35
|
+
clearTimeout(timeout);
|
|
36
|
+
state.timeouts.delete(requestId);
|
|
37
|
+
}
|
|
38
|
+
resolver(results);
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
const handleRequestTimeout = (state, requestId) => {
|
|
42
|
+
const resolver = state.resolvers.get(requestId);
|
|
43
|
+
if (resolver) {
|
|
44
|
+
state.resolvers.delete(requestId);
|
|
45
|
+
state.timeouts.delete(requestId);
|
|
46
|
+
const timeoutResult = createResult(ResultCode.Fail, `${state.requestType}请求超时`, null);
|
|
47
|
+
resolver([timeoutResult]);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const getPendingRequestCount = (state) => {
|
|
51
|
+
return state.resolvers.size;
|
|
52
|
+
};
|
|
53
|
+
const destroyRequestHandler = (state) => {
|
|
54
|
+
for (const timeout of state.timeouts.values()) {
|
|
55
|
+
clearTimeout(timeout);
|
|
56
|
+
}
|
|
57
|
+
for (const [_requestId, resolver] of state.resolvers.entries()) {
|
|
58
|
+
const cancelResult = createResult(ResultCode.FailInternal, `${state.requestType}请求已取消`, null);
|
|
59
|
+
resolver([cancelResult]);
|
|
60
|
+
}
|
|
61
|
+
state.resolvers.clear();
|
|
62
|
+
state.timeouts.clear();
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export { createRequestHandlerState, destroyRequestHandler, getPendingRequestCount, handleRequestResponse, handleRequestTimeout, sendRequest };
|
package/lib/cbp/server/main.js
CHANGED
|
@@ -4,7 +4,9 @@ import * as flattedJSON from 'flatted';
|
|
|
4
4
|
import koaCors from '@koa/cors';
|
|
5
5
|
import router from '../routers/router.js';
|
|
6
6
|
import { ResultCode } from '../../core/variable.js';
|
|
7
|
-
import
|
|
7
|
+
import 'fs';
|
|
8
|
+
import 'path';
|
|
9
|
+
import 'yaml';
|
|
8
10
|
import '../../core/utils.js';
|
|
9
11
|
import { USER_AGENT_HEADER, USER_AGENT_HEADER_VALUE_MAP, DEVICE_ID_HEADER, FULL_RECEIVE_HEADER, platformClient, childrenClient, fullClient, childrenBind } from '../processor/config.js';
|
|
10
12
|
import { createTestOneController } from './testone.js';
|
|
@@ -343,15 +345,9 @@ const cbpServer = (port, listeningListener) => {
|
|
|
343
345
|
ws.send(flattedJSON.stringify({
|
|
344
346
|
active: 'sync',
|
|
345
347
|
payload: {
|
|
346
|
-
value: getConfig().value,
|
|
347
|
-
args: getConfig().argv,
|
|
348
|
-
package: {
|
|
349
|
-
version: getConfig().package?.version
|
|
350
|
-
},
|
|
351
348
|
env: {
|
|
352
349
|
login: process.env.login,
|
|
353
|
-
platform: process.env.platform
|
|
354
|
-
port: process.env.port
|
|
350
|
+
platform: process.env.platform
|
|
355
351
|
}
|
|
356
352
|
},
|
|
357
353
|
activeId: originId
|
package/lib/main.js
CHANGED
|
@@ -35,7 +35,7 @@ const startPlatform = (options) => {
|
|
|
35
35
|
if (login) {
|
|
36
36
|
process.env.login = login;
|
|
37
37
|
}
|
|
38
|
-
startPlatformAdapterWithFallback();
|
|
38
|
+
void startPlatformAdapterWithFallback();
|
|
39
39
|
};
|
|
40
40
|
const startClient = (options) => {
|
|
41
41
|
process.env.input = createOptionsByKey(options, 'input', '');
|
|
@@ -3,7 +3,7 @@ import { platform } from '../base/platform';
|
|
|
3
3
|
import { Message } from '../base/message';
|
|
4
4
|
import { Expansion } from '../base/expansion';
|
|
5
5
|
export type PublicEventChannalCreate = platform & Guild & Channel & Message & {
|
|
6
|
-
name: '
|
|
6
|
+
name: 'channel.create';
|
|
7
7
|
} & Expansion;
|
|
8
8
|
export type PublicEventChannalDelete = platform & Guild & Channel & Message & {
|
|
9
9
|
name: 'channal.delete';
|
package/lib/types/event/map.d.ts
CHANGED
|
@@ -18,7 +18,7 @@ export type Events = {
|
|
|
18
18
|
'message.delete': PublicEventMessageDelete;
|
|
19
19
|
'message.reaction.add': PublicEventMessageReactionAdd;
|
|
20
20
|
'message.reaction.remove': PublicEventMessageReactionRemove;
|
|
21
|
-
'
|
|
21
|
+
'channel.create': PublicEventChannalCreate;
|
|
22
22
|
'channal.delete': PublicEventChannalDelete;
|
|
23
23
|
'guild.join': PublicEventGuildJoin;
|
|
24
24
|
'guild.exit': PublicEventGuildExit;
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
+
"$schema": "https://json.schemastore.org/package",
|
|
2
3
|
"name": "alemonjs",
|
|
3
|
-
"version": "2.1.
|
|
4
|
+
"version": "2.1.8",
|
|
4
5
|
"description": "bot script",
|
|
5
6
|
"author": "lemonade",
|
|
6
7
|
"license": "MIT",
|
|
@@ -71,4 +72,4 @@
|
|
|
71
72
|
"type": "git",
|
|
72
73
|
"url": "https://github.com/lemonade-lab/alemonjs.git"
|
|
73
74
|
}
|
|
74
|
-
}
|
|
75
|
+
}
|
package/lib/adapter.js
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import { fork } from 'child_process';
|
|
2
|
-
import { createRequire } from 'module';
|
|
3
|
-
|
|
4
|
-
const require = createRequire(import.meta.url);
|
|
5
|
-
/**
|
|
6
|
-
* 启动平台平台连接,优先使用子进程(fork),如不支持或平台连接未响应,则自动降级为 import 动态加载。
|
|
7
|
-
* 自动兼容新老版本平台连接。
|
|
8
|
-
* @param modulePath 平台连接模块绝对路径(require.resolve 得到的)
|
|
9
|
-
* @param env 环境变量对象
|
|
10
|
-
* @param logger 日志对象(需实现 info/warn/error)
|
|
11
|
-
*/
|
|
12
|
-
function startAdapterWithFallback() {
|
|
13
|
-
let modulePath = '';
|
|
14
|
-
try {
|
|
15
|
-
modulePath = require.resolve(process.env.platform);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
void import(process.env.platform).then(res => res?.default());
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
let imported = false; // 标记 import 是否已成功,避免重复
|
|
22
|
-
const startByFork = () => {
|
|
23
|
-
if (imported) {
|
|
24
|
-
return; // 如果已经 import 成功,不再 fork
|
|
25
|
-
}
|
|
26
|
-
let restarted = false;
|
|
27
|
-
let ready = false;
|
|
28
|
-
let child;
|
|
29
|
-
const restart = () => {
|
|
30
|
-
if (restarted || imported) {
|
|
31
|
-
return;
|
|
32
|
-
}
|
|
33
|
-
restarted = true;
|
|
34
|
-
if (child) {
|
|
35
|
-
child.removeAllListeners();
|
|
36
|
-
try {
|
|
37
|
-
child.kill();
|
|
38
|
-
}
|
|
39
|
-
catch { }
|
|
40
|
-
}
|
|
41
|
-
setTimeout(() => {
|
|
42
|
-
startByFork();
|
|
43
|
-
}, 3000);
|
|
44
|
-
};
|
|
45
|
-
try {
|
|
46
|
-
child = fork(modulePath);
|
|
47
|
-
// 超时
|
|
48
|
-
const checkTimeout = async () => {
|
|
49
|
-
if (!ready && !imported) {
|
|
50
|
-
logger?.warn?.('平台连接未及时响应(未发送 ready 消息),降级为 import 加载');
|
|
51
|
-
try {
|
|
52
|
-
child?.kill();
|
|
53
|
-
}
|
|
54
|
-
catch { }
|
|
55
|
-
await startByImport();
|
|
56
|
-
}
|
|
57
|
-
};
|
|
58
|
-
const timer = setTimeout(() => void checkTimeout(), 2000);
|
|
59
|
-
child.on('exit', (code, signal) => {
|
|
60
|
-
clearTimeout(timer);
|
|
61
|
-
if (!imported) {
|
|
62
|
-
logger?.warn?.(`平台连接子进程已退出,code=${code}, signal=${signal},3秒后自动重启`);
|
|
63
|
-
restart();
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
child.on('message', msg => {
|
|
67
|
-
try {
|
|
68
|
-
const data = typeof msg === 'string' ? JSON.parse(msg) : msg;
|
|
69
|
-
if (data?.type === 'ready') {
|
|
70
|
-
ready = true;
|
|
71
|
-
clearTimeout(timer);
|
|
72
|
-
logger?.info?.('平台连接已就绪(子进程 fork 模式)');
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
logger?.error?.('平台连接进程通信数据格式错误', err);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
catch (err) {
|
|
81
|
-
logger?.warn?.('fork 启动平台连接失败,将尝试 import 加载', err);
|
|
82
|
-
void startByImport();
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
const startByImport = async () => {
|
|
86
|
-
if (imported) {
|
|
87
|
-
return;
|
|
88
|
-
}
|
|
89
|
-
imported = true;
|
|
90
|
-
try {
|
|
91
|
-
let importPath = modulePath;
|
|
92
|
-
if (!importPath.startsWith('file://')) {
|
|
93
|
-
importPath = 'file://' + importPath;
|
|
94
|
-
}
|
|
95
|
-
const mod = await import(importPath);
|
|
96
|
-
if (typeof mod.default === 'function') {
|
|
97
|
-
await mod.default();
|
|
98
|
-
logger?.info?.('通过 import 启动平台连接完成');
|
|
99
|
-
}
|
|
100
|
-
else {
|
|
101
|
-
logger?.warn?.('通过 import 启动平台连接,但未找到默认导出函数');
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
catch (err) {
|
|
105
|
-
logger?.error?.('import 启动平台连接失败', err);
|
|
106
|
-
}
|
|
107
|
-
};
|
|
108
|
-
startByFork();
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export { startAdapterWithFallback };
|
package/lib/app/load.d.ts
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* 加载子模块
|
|
3
|
-
* @param mainPath
|
|
4
|
-
* @param appName
|
|
5
|
-
* @throws {Error} - 如果 mainPath 无效,抛出错误。
|
|
6
|
-
*/
|
|
7
|
-
declare const loadChildren: (mainPath: string, appName: string) => Promise<void>;
|
|
8
|
-
/**
|
|
9
|
-
* 模块文件
|
|
10
|
-
* @param app
|
|
11
|
-
*/
|
|
12
|
-
declare const loadChildrenFile: (appName: string) => Promise<void>;
|
|
13
|
-
|
|
14
|
-
export { loadChildren, loadChildrenFile };
|