Intial Commit
This commit is contained in:
239
nodered/rootfs/data/node_modules/node-red-contrib-telegrambot-home/nodes/switch/switch.html
generated
vendored
Normal file
239
nodered/rootfs/data/node_modules/node-red-contrib-telegrambot-home/nodes/switch/switch.html
generated
vendored
Normal file
@@ -0,0 +1,239 @@
|
||||
<script type="text/javascript">
|
||||
// Configuration inspired by node-red's switch node
|
||||
// https://github.com/node-red/node-red/blob/master/nodes/core/logic/10-switch.html
|
||||
var timeoutIdx = 99999;
|
||||
|
||||
RED.nodes.registerType("telegrambot-switch", {
|
||||
category: "telegram",
|
||||
paletteLabel: "switch",
|
||||
color: "#3babdd",
|
||||
icon: "switch.png",
|
||||
defaults: {
|
||||
name: { value: "" },
|
||||
bot: { value: "", type: "telegrambot-config", required: true },
|
||||
chatId: { value: "", required: false },
|
||||
question: { value: "" },
|
||||
answers: { value: [] },
|
||||
outputs: { value: 1 },
|
||||
autoAnswerCallback: { value: true, required: false },
|
||||
timeoutValue: { value: null },
|
||||
timeoutUnits: { value: null }
|
||||
},
|
||||
inputs: 1,
|
||||
outputs: 1,
|
||||
label: function() {
|
||||
return this.name || "telegram switch";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
},
|
||||
outputLabels: function(index) {
|
||||
if (index < this.answers.length) {
|
||||
var answer = this.answers[index];
|
||||
return (answer.length > 15) ? `${answer.substring(0,15)}...` : answer;
|
||||
} else {
|
||||
return "timeout";
|
||||
}
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var node = this;
|
||||
var outputCount = $("#node-input-outputs").val("{}");
|
||||
|
||||
$("#node-input-timeoutUnits").change(function(){
|
||||
if ($(this).val() == "") {
|
||||
$("#node-input-timeoutValue").val("");
|
||||
$("#node-input-timeoutValue").prop("disabled", true);
|
||||
|
||||
var currentOutputs = JSON.parse(outputCount.val() || "{}");
|
||||
delete currentOutputs[timeoutIdx];
|
||||
outputCount.val(JSON.stringify(currentOutputs));
|
||||
} else {
|
||||
$("#node-input-timeoutValue").prop("disabled", false);
|
||||
|
||||
var currentOutputs = JSON.parse(outputCount.val() || "{}");
|
||||
currentOutputs[timeoutIdx] = timeoutIdx;
|
||||
outputCount.val(JSON.stringify(currentOutputs));
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-answer-container").css("min-height","250px").css("min-width","450px").editableList({
|
||||
addItem: function(container, i, opt) {
|
||||
container.css({
|
||||
overflow: "hidden",
|
||||
whiteSpace: "nowrap"
|
||||
});
|
||||
|
||||
if (!opt.hasOwnProperty("answer")) {
|
||||
opt.answer = "";
|
||||
}
|
||||
|
||||
if (!opt.hasOwnProperty("idx")) {
|
||||
opt._idx = Math.floor((0x99999-0x10000)*Math.random()).toString();
|
||||
}
|
||||
|
||||
var answer = opt.answer;
|
||||
var row = $("<div/>").appendTo(container);
|
||||
var valueField = $("<input/>",{class:"node-input-answer-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:"str",types:["str"]});
|
||||
var finalspan = $("<span/>",{style:"float: right;margin-top: 6px;"}).appendTo(row);
|
||||
finalspan.append(` → <span class="node-input-answer-index">${(i+1)}</span> `);
|
||||
|
||||
if (typeof answer != "undefined") {
|
||||
valueField.typedInput("value", answer)
|
||||
}
|
||||
|
||||
var currentOutputs = JSON.parse(outputCount.val() || "{}");
|
||||
currentOutputs[opt.hasOwnProperty("idx") ? opt.idx : opt._idx] = i;
|
||||
outputCount.val(JSON.stringify(currentOutputs));
|
||||
},
|
||||
removeItem: function(opt){
|
||||
var currentOutputs = JSON.parse(outputCount.val() || "{}");
|
||||
|
||||
if (opt.hasOwnProperty("idx")) {
|
||||
currentOutputs[opt.idx] = -1;
|
||||
} else {
|
||||
delete currentOutputs[opt._idx];
|
||||
}
|
||||
|
||||
var answers = $("#node-input-answer-container").editableList("items");
|
||||
answers.each(function(i) {
|
||||
$(this).find(".node-input-answer-index").html(i + 1);
|
||||
var data = $(this).data("data");
|
||||
currentOutputs[data.hasOwnProperty("idx") ? data.idx : data._idx] = i;
|
||||
});
|
||||
outputCount.val(JSON.stringify(currentOutputs));
|
||||
},
|
||||
sortItems: function(answers) {
|
||||
var currentOutputs = JSON.parse(outputCount.val() || "{}");
|
||||
var answers = $("#node-input-answer-container").editableList("items");
|
||||
answers.each(function(i) {
|
||||
$(this).find(".node-input-answer-index").html(i + 1);
|
||||
var data = $(this).data("data");
|
||||
currentOutputs[data.hasOwnProperty("idx")? data.idx : data._idx] = i;
|
||||
});
|
||||
outputCount.val(JSON.stringify(currentOutputs));
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
|
||||
for (var i=0; i < this.answers.length; i++) {
|
||||
var answer = this.answers[i];
|
||||
$("#node-input-answer-container").editableList("addItem", { idx: i, answer: answer });
|
||||
}
|
||||
},
|
||||
oneditsave: function() {
|
||||
var answers = $("#node-input-answer-container").editableList("items");
|
||||
var node = this;
|
||||
|
||||
node.answers = [];
|
||||
|
||||
answers.each(function(i){
|
||||
var answerData = $(this).data("data");
|
||||
var answer = $(this);
|
||||
var value = answer.find(".node-input-answer-value").typedInput("value");
|
||||
|
||||
node.answers.push(value);
|
||||
});
|
||||
},
|
||||
oneditresize: function(size) {
|
||||
var rows = $("#dialog-form>div:not(.node-input-answer-container-row)");
|
||||
var height = size.height;
|
||||
|
||||
for (var i = 0; i < rows.size(); i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
|
||||
var editorRow = $("#dialog-form>div.node-input-answer-container-row");
|
||||
height -= (parseInt(editorRow.css("marginTop")) + parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-answer-container").editableList("height",height);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="telegrambot-switch">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-bot">Bot</label>
|
||||
<input type="text" id="node-input-bot" placeholder="Bot">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-chatId">Chat ID</label>
|
||||
<input type="text" id="node-input-chatId" placeholder="(e.g. 1234)">
|
||||
</div>
|
||||
<div class="form-row node-type-duration">
|
||||
<label>Timeout</label>
|
||||
<input type="text" id="node-input-timeoutValue" style="text-align:end; width:70px !important">
|
||||
<select id="node-input-timeoutUnits" style="width:140px !important">
|
||||
<option value="">disabled</option>
|
||||
<option value="ms">milliseconds</option>
|
||||
<option value="s">seconds</option>
|
||||
<option value="min">minutes</option>
|
||||
<option value="hr">hours</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-autoAnswerCallback">Auto-Answer</label>
|
||||
<input type="checkbox" id="node-input-autoAnswerCallback" style="display:inline-block; width:auto; vertical-align:top;">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-question">Question</label>
|
||||
<input type="text" id="node-input-question" placeholder="(e.g. Should I continue?)">
|
||||
</div>
|
||||
<div class="form-row node-input-answer-container-row">
|
||||
<input type="hidden" id="node-input-outputs"/>
|
||||
<ol id="node-input-answer-container"></ol>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="telegrambot-switch">
|
||||
<p>Route messages based on a response from a user via Telegram</p>
|
||||
|
||||
<h3>Details</h3>
|
||||
<p>When a message arrives, a message will be sent to the specified Telegram bot + chat ID with
|
||||
the configured answers presented as quick reply options. When the user selects a reply, the
|
||||
message will be forwarded to the corresponding output.</p>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>Name <span class="property-type">string</span></dt>
|
||||
<dd>Label for this node for easy reference</dd>
|
||||
|
||||
<dt>Bot <span class="property-type">string</span></dt>
|
||||
<dd>Telegram bot configuration for sending the message</dd>
|
||||
|
||||
<dt class="optional">Chat ID <span class="property-type">int</span></dt>
|
||||
<dd>Optional. Telegram chat ID to send the message. Specify a value to have this node send to the same chat every time. Leave blank to allow passing in the chat ID via <code>msg.telegram.chat.id</code>.</dd>
|
||||
|
||||
<dt class="optional">Auto-Answer <span class="property-type">list</span></dt>
|
||||
<dd>When enabled, automatically respond to the Telegram callback to resolve it as finished. Otherwise, you will have to send a payload to Telegram yourself to mark the request as complete.</dd>
|
||||
|
||||
<dt class="optional">Timeout <span class="property-type">int</span></dt>
|
||||
<dd>If provided, the message will time out after the specific time in milliseconds and the reply options will be removed from the chat.</dd>
|
||||
|
||||
<dt class="optional">Question <span class="property-type">string</span></dt>
|
||||
<dd>Question to ask the user. If not provided, <code>msg.payload</code> will be used.</dd>
|
||||
|
||||
<dt>Answers <span class="property-type">list</span></dt>
|
||||
<dd>The answer choices to present the user. Each answer will correspond to its designated output.</dd>
|
||||
</dl>
|
||||
|
||||
<h3>Outputs</h3>
|
||||
|
||||
<dl class="message-properties">
|
||||
<dt>payload</dt>
|
||||
<dd>The original message that entered the node.</dd>
|
||||
|
||||
<dt>telegram</dt>
|
||||
<dd>Telegram metadata of the sent message.</dd>
|
||||
|
||||
<dt>chatId <span class="property-type">deprecated</span></dt>
|
||||
<dd>The chat ID the messages are being sent/received in. Use <code>msg.telegram.chat.id</code> instead.</dd>
|
||||
|
||||
<dt>messageId <span class="property-type">deprecated</span></dt>
|
||||
<dd>The ID of the message that was sent prompting for a response. Use <code>msg.telegram.message_id</code> instead.</dd>
|
||||
</dl>
|
||||
|
||||
<p>In the case of a timeout, the original message is sent to the last output labeled "timeout". Please note that in the case that Node-RED restarts, the timeout will silently fail.</p>
|
||||
</script>
|
||||
181
nodered/rootfs/data/node_modules/node-red-contrib-telegrambot-home/nodes/switch/switch.js
generated
vendored
Normal file
181
nodered/rootfs/data/node_modules/node-red-contrib-telegrambot-home/nodes/switch/switch.js
generated
vendored
Normal file
@@ -0,0 +1,181 @@
|
||||
var utils = require('../../lib/utils.js');
|
||||
|
||||
module.exports = function(RED) {
|
||||
function SwitchNode(config) {
|
||||
RED.nodes.createNode(this, config);
|
||||
var node = this;
|
||||
|
||||
// Get base configuration
|
||||
this.bot = RED.nodes.getNode(config.bot);
|
||||
this.chatId = parseInt(config.chatId);
|
||||
this.question = config.question || "";
|
||||
this.answers = config.answers || [];
|
||||
this.timeoutValue = config.timeoutValue || null;
|
||||
this.timeoutUnits = config.timeoutUnits || null;
|
||||
this.timeoutCallback = null;
|
||||
this.autoAnswerCallback = config.autoAnswerCallback;
|
||||
|
||||
// Initialize bot
|
||||
utils.initializeBot(node);
|
||||
|
||||
// Verify inputs
|
||||
if (isNaN(this.chatId)) {
|
||||
this.chatId = null;
|
||||
}
|
||||
|
||||
if (this.timeoutValue !== null) {
|
||||
if (this.timeoutUnits === null) {
|
||||
utils.updateNodeStatusFailed(node, "timeout units not provided");
|
||||
return;
|
||||
}
|
||||
|
||||
this.timeoutDuration = utils.timeUnits(parseInt(this.timeoutValue, 10), this.timeoutUnits);
|
||||
|
||||
if (this.timeoutDuration === NaN) {
|
||||
utils.updateNodeStatusFailed(node, "timeout not parsable");
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timeoutDuration <= 0) {
|
||||
utils.updateNodeStatusFailed(node, "timeout should be greater than 0");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Compute output ports
|
||||
var portCount = (this.timeoutValue === null) ? this.answers.length : this.answers.length + 1;
|
||||
var ports = new Array(portCount);
|
||||
|
||||
for (var i = 0; i < portCount; i++) {
|
||||
ports[i] = null;
|
||||
}
|
||||
|
||||
this.on("input", function(msg){
|
||||
if (!utils.validateChatId(node, msg)) {
|
||||
utils.updateNodeStatusFailed(node, "message has no chatID");
|
||||
return;
|
||||
}
|
||||
|
||||
var chatId = node.chatId || msg.telegram.chat.id;
|
||||
var question = node.question || msg.payload;
|
||||
var answers = node.answers || [];
|
||||
|
||||
if (question && answers.length > 0) {
|
||||
var listener = function(botMsg){
|
||||
var username = botMsg.from.username;
|
||||
var fromChatId = botMsg.message.chat.id;
|
||||
var messageId = botMsg.message.message_id;
|
||||
var callbackQueryId = botMsg.id;
|
||||
|
||||
if (botMsg.data && fromChatId === chatId && messageId === msg.telegram.messageId) {
|
||||
if (node.bot.isAuthorized(chatId, username)) {
|
||||
// Remove this listener since we got our reply
|
||||
node.telegramBot.removeListener("callback_query", listener);
|
||||
|
||||
// Clear the timeout
|
||||
if (node.timeoutCallback) {
|
||||
clearTimeout(node.timeoutCallback);
|
||||
}
|
||||
|
||||
// Update node status
|
||||
utils.updateNodeStatusSuccess(node);
|
||||
|
||||
if (node.autoAnswerCallback) {
|
||||
// Answer the callback so progress can stop showing
|
||||
node.telegramBot.answerCallbackQuery(callbackQueryId).then(function(sent){
|
||||
// nothing to do here
|
||||
});
|
||||
|
||||
// Remove quick reply options
|
||||
node.telegramBot.editMessageReplyMarkup("{}", { chat_id: chatId, message_id: messageId }).then(function(sent){
|
||||
// nothing to do here
|
||||
});
|
||||
}
|
||||
|
||||
// Augment original message with additional Telegram info
|
||||
msg.telegram.callbackQueryId = callbackQueryId;
|
||||
|
||||
// Continue with the original message
|
||||
var outPorts = ports.slice(0);
|
||||
var outputPort = parseInt(botMsg.data);
|
||||
|
||||
if (!isNaN(outputPort) && outputPort < portCount) {
|
||||
outPorts[outputPort] = msg;
|
||||
node.send(outPorts);
|
||||
} else {
|
||||
node.warn("invalid callback data received from telegram");
|
||||
}
|
||||
} else {
|
||||
node.warn(`received callback in ${chatId} from '${username}' was unauthorized`);
|
||||
}
|
||||
} else {
|
||||
// This is not the listener you are looking for
|
||||
}
|
||||
};
|
||||
|
||||
var timeoutListener = function(sentMsg){
|
||||
utils.updateNodeStatus(node, "yellow", "dot", "timed out waiting for reply");
|
||||
|
||||
// Remove this listener
|
||||
node.telegramBot.removeListener("callback_query", listener);
|
||||
|
||||
var messageId = sentMsg.message_id;
|
||||
var sentChatId = sentMsg.chat.id;
|
||||
|
||||
// Remove reply keyboard from message
|
||||
if (messageId && sentChatId) {
|
||||
node.telegramBot.editMessageReplyMarkup("{}", { chat_id: sentChatId, message_id: messageId }).then(function(sent){
|
||||
// nothing to do here
|
||||
});
|
||||
}
|
||||
|
||||
// output to timeout
|
||||
var outPorts = ports.slice(0);
|
||||
var outputPort = portCount - 1;
|
||||
outPorts[outputPort] = msg;
|
||||
node.send(outPorts);
|
||||
};
|
||||
|
||||
|
||||
var chunkSize = 4000;
|
||||
var answerOpts = answers.map(function(answer, idx){
|
||||
return { text: answer, callback_data: idx };
|
||||
});
|
||||
var options = {
|
||||
reply_markup: {
|
||||
inline_keyboard: [answerOpts]
|
||||
}
|
||||
};
|
||||
|
||||
if (question.length > chunkSize) {
|
||||
utils.updateNodeStatusFailed(node, "message larger than allowed chunk size");
|
||||
} else {
|
||||
node.telegramBot.sendMessage(chatId, question, options).then(function(sent){
|
||||
// Store sent message so we know how to respond later
|
||||
msg.telegram = sent;
|
||||
msg.telegram.chatId = chatId; // deprecated
|
||||
msg.telegram.messageId = sent.message_id; // deprecated
|
||||
|
||||
if (node.timeoutDuration > 0) {
|
||||
node.timeoutCallback = setTimeout(function(){
|
||||
timeoutListener(sent);
|
||||
}, node.timeoutDuration);
|
||||
utils.updateNodeStatusPending(node, `waiting for reply (${node.timeoutValue}${node.timeoutUnits})`);
|
||||
} else {
|
||||
utils.updateNodeStatusPending(node, "waiting for reply");
|
||||
}
|
||||
});
|
||||
|
||||
node.telegramBot.on("callback_query", listener);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.on("close", function(){
|
||||
node.telegramBot.off("message");
|
||||
node.status({});
|
||||
});
|
||||
};
|
||||
|
||||
RED.nodes.registerType("telegrambot-switch", SwitchNode);
|
||||
};
|
||||
Reference in New Issue
Block a user