n8n-nodes-feishu-lark
Version:
n8n custom nodes for n8n to interact with Feishu/Lark, including Lark Bot, Lark MCP, and Lark Trigger.
242 lines • 8.42 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.StreamingMessageManager = void 0;
exports.generateStreamingCardMessage = generateStreamingCardMessage;
exports.updateStreamingMessage = updateStreamingMessage;
exports.handleStreamingChunk = handleStreamingChunk;
exports.handleNodeStart = handleNodeStart;
exports.handleNodeComplete = handleNodeComplete;
exports.createBotMessage = createBotMessage;
exports.updateMessageInArray = updateMessageInArray;
exports.createLineParser = createLineParser;
const uuid_1 = require("uuid");
const RequestUtils_1 = __importDefault(require("./RequestUtils"));
function pThrottle(fn, wait) {
let lastTime = 0;
return (async (...args) => {
const now = Date.now();
if (now - lastTime >= wait) {
lastTime = now;
return await fn(...args);
}
else {
return Promise.resolve();
}
});
}
function generateStreamingCardMessage(content) {
return {
schema: '2.0',
config: {
update_multi: true,
streaming_mode: false,
},
body: {
direction: 'vertical',
padding: '12px 12px 12px 12px',
elements: [
{
tag: 'markdown',
content,
text_align: 'left',
text_size: 'normal',
margin: '0px 0px 0px 0px',
},
],
},
};
}
async function updateStreamingMessage(context, larkMessageId, message) {
return await RequestUtils_1.default.request.call(context, {
method: 'PATCH',
url: `/open-apis/im/v1/messages/${larkMessageId}`,
body: {
content: JSON.stringify(generateStreamingCardMessage(message)),
},
});
}
const throttledUpdateMessage = pThrottle(updateStreamingMessage, 200);
async function handleStreamingChunk(context, chunk, nodeId, streamingManager, receivedMessage, messages, larkMessageId, runIndex) {
var _a;
try {
if (chunk === '') {
return;
}
if (!nodeId) {
if (!receivedMessage) {
receivedMessage = createBotMessage(larkMessageId);
messages.push(receivedMessage);
}
const updatedMessage = {
...receivedMessage,
text: receivedMessage.text + chunk,
};
updateMessageInArray(messages, receivedMessage.id, updatedMessage);
receivedMessage = updatedMessage;
}
else {
let runMessage = streamingManager.getRunMessage(nodeId, runIndex);
if (!runMessage) {
runMessage = streamingManager.addRunToActive(nodeId, runIndex, larkMessageId);
messages.push(runMessage);
}
const updatedMessage = streamingManager.addChunkToRun(nodeId, chunk, runIndex);
if (updatedMessage) {
updateMessageInArray(messages, updatedMessage.id, updatedMessage);
}
}
throttledUpdateMessage(context, larkMessageId, (_a = messages.find((message) => message.id === larkMessageId && message.type === 'text')) === null || _a === void 0 ? void 0 : _a.text);
}
catch (error) {
context.logger.error('Error handling stream chunk:', error);
}
}
function handleNodeStart(nodeId, streamingManager, runIndex) {
streamingManager.registerRunStart(nodeId, runIndex);
}
function handleNodeComplete(nodeId, streamingManager, runIndex) {
streamingManager.removeRunFromActive(nodeId, runIndex);
}
function createBotMessage(id) {
return {
id: id !== null && id !== void 0 ? id : (0, uuid_1.v4)(),
type: 'text',
text: '',
sender: 'bot',
};
}
function updateMessageInArray(messages, messageId, updatedMessage) {
const messageIndex = messages.findIndex((msg) => msg.id === messageId);
if (messageIndex === -1) {
throw new Error(`Can't update message. No message with id ${messageId} found`);
}
messages[messageIndex] = updatedMessage;
}
function createLineParser() {
let buffer = '';
const decoder = new TextDecoder();
return new TransformStream({
transform(chunk, controller) {
var _a;
buffer += decoder.decode(chunk, { stream: true });
const lines = buffer.split('\n');
buffer = (_a = lines.pop()) !== null && _a !== void 0 ? _a : '';
for (const line of lines) {
if (line.trim()) {
try {
const parsed = JSON.parse(line);
controller.enqueue(parsed);
}
catch (error) {
controller.enqueue({
type: 'item',
content: line,
});
}
}
}
},
flush(controller) {
if (buffer.trim()) {
try {
const parsed = JSON.parse(buffer);
controller.enqueue(parsed);
}
catch (error) {
controller.enqueue({
type: 'item',
content: buffer,
});
}
}
},
});
}
class StreamingMessageManager {
constructor() {
this.nodeRuns = new Map();
this.runOrder = [];
this.activeRuns = new Set();
}
getRunKey(nodeId, runIndex) {
if (runIndex !== undefined) {
return `${nodeId}-${runIndex}`;
}
return nodeId;
}
initializeRun(nodeId, runIndex, id) {
const runKey = this.getRunKey(nodeId, runIndex);
if (!this.nodeRuns.has(runKey)) {
const message = createBotMessage(id);
this.nodeRuns.set(runKey, {
content: '',
isComplete: false,
message,
});
this.runOrder.push(runKey);
return message;
}
return this.nodeRuns.get(runKey).message;
}
registerRunStart(nodeId, runIndex) {
const runKey = this.getRunKey(nodeId, runIndex);
this.activeRuns.add(runKey);
}
addRunToActive(nodeId, runIndex, id) {
const runKey = this.getRunKey(nodeId, runIndex);
this.activeRuns.add(runKey);
return this.initializeRun(nodeId, runIndex, id);
}
removeRunFromActive(nodeId, runIndex) {
const runKey = this.getRunKey(nodeId, runIndex);
this.activeRuns.delete(runKey);
const runData = this.nodeRuns.get(runKey);
if (runData) {
runData.isComplete = true;
}
}
addChunkToRun(nodeId, chunk, runIndex) {
const runKey = this.getRunKey(nodeId, runIndex);
const runData = this.nodeRuns.get(runKey);
if (runData) {
runData.content += chunk;
const updatedMessage = {
...runData.message,
text: runData.content,
};
runData.message = updatedMessage;
return updatedMessage;
}
return null;
}
getRunMessage(nodeId, runIndex) {
var _a;
const runKey = this.getRunKey(nodeId, runIndex);
const runData = this.nodeRuns.get(runKey);
return (_a = runData === null || runData === void 0 ? void 0 : runData.message) !== null && _a !== void 0 ? _a : null;
}
areAllRunsComplete() {
return Array.from(this.nodeRuns.values()).every((data) => data.isComplete);
}
getRunCount() {
return this.runOrder.length;
}
getActiveRunCount() {
return this.activeRuns.size;
}
getAllMessages() {
return this.runOrder
.map((key) => { var _a; return (_a = this.nodeRuns.get(key)) === null || _a === void 0 ? void 0 : _a.message; })
.filter((message) => message !== undefined);
}
reset() {
this.nodeRuns.clear();
this.runOrder = [];
this.activeRuns.clear();
}
}
exports.StreamingMessageManager = StreamingMessageManager;
//# sourceMappingURL=streaming.js.map