<commit_before>var Fritzbox = require("fritzbox"),
http = require("http"),
xml2js = require("xml2js");

var Promise = require("bluebird");
var request = require("request");

var parser = xml2js.Parser({explicitRoot: false, explicitArray: false});

module.exports = function(RED) {

	RED.httpAdmin.get('/fritzbox/services', function(req, res, next) {
		var url = req.query.url;
		var config = {
			host: req.query.url
		};

		var fritzbox = new Fritzbox.Fritzbox(config);

		Promise.all([fritzbox.initIGDDevice(), fritzbox.initTR064Device()])
			.then(function() {
				var services = Object.keys(fritzbox.services);
				res.end(JSON.stringify(services));
			}).catch(function(error) {
				res.end();
			});
	});

	RED.httpAdmin.get('/fritzbox/actions', function(req, res, next) {
		var service = req.query.service;

		var config = {
			host: req.query.url
		};

		var fritzbox = new Fritzbox.Fritzbox(config);

		Promise.all([fritzbox.initIGDDevice(), fritzbox.initTR064Device()])
			.then(function() {
				var actions = fritzbox.services[service].actionsInfo;
				res.end(JSON.stringify(actions));
			}).catch(function(error) {
				res.end();
			});
	});

	function FritzboxConfig(n) {
		RED.nodes.createNode(this, n);
		var node = this;
		node.host = n.host;
		node.timer = null;
		node.state = null;

		if(!node.host) return;

		var config = {
			host: n.host,
			user: node.credentials.username,
			password: <PASSWORD>.credentials.password,
			port: n.port,
			ssl: n.ssl
		};

		node.fritzbox = new Fritzbox.Fritzbox(config);

		node.reinit = function() {
			Promise.all([node.fritzbox.initIGDDevice(), node.fritzbox.initTR064Device()])
				.then(function() {
					updateStatus("ready");
				}).catch(function(error) {
					node.error(`Initialization of device failed ${error}. Check configuration.`);
					updateStatus("error");
				});
		};

		var updateStatus = function(status) {
			node.state = status;
			switch(status) {
				case "init":
					node.emit("statusUpdate", {fill:"yellow",shape:"ring",text:"Initializing device ..."});
					break;
				case "ready":
					node.emit("statusUpdate", {fill:"green",shape:"dot",text:"Ready"});
					break;
				case "error":
					node.emit("statusUpdate", {fill:"red",shape:"ring",text:"Error"});
					break;
			}
		};
		node.reinit();
	}
	RED.nodes.registerType("fritzbox-config", FritzboxConfig, {
		credentials: {
			username: {type: "text"},
			password: {type: "password"}
		}
	});


	function FritzboxIn(n) {
		RED.nodes.createNode(this,n);
		var node = this;
		node.service = n.service;
		node.action = n.action;
		node.config = RED.nodes.getNode(n.device);

		node.config.on('statusUpdate', node.status);

		node.on('input', function(msg) {
			if(node.config.state === "ready" && node.config.fritzbox) {
				var service = msg.service ? msg.service : node.service;
				var action = msg.action ? msg.action : node.action;

				node.config.fritzbox.services[service].actions[action](msg.payload)
					.then(function(result) {
						msg.payload = result;
						node.send(msg);
					}).catch(function(error) {
						node.error(`Action failed with error: ${error}`, msg);
					});
			} else {
				node.warn("Device not ready.");
				node.config.reinit();
			}
		});

		node.on('close', function() {
			node.config.removeListener('statusUpdate', node.status);
		});
	}
	RED.nodes.registerType("fritzbox-in", FritzboxIn);

	function FritzboxList(n) {
		RED.nodes.createNode(this,n);
		var node = this;
		node.max = n.max;
		node.maxdays = n.maxdays;
		node.action = n.action;
		node.listurl = n.listurl;
		node.phonebookId = n.id;
		node.config = RED.nodes.getNode(n.device);

		node.config.on('statusUpdate', node.status);

		node.on('input', function(msg) {
			if(node.config.state === "ready" && node.config.fritzbox) {
				var args = {};
				var action = n.action;
				var query = "";
				var urlkey = n.listurl;

				switch (action) {
					case "GetCallList":
						if(n.maxdays) {
							query += "&days=" + n.maxdays;
						}
						if(n.max) {
							query += "&max=" + n.max;
						}
					break;
					case "GetPhonebook":
						if (typeof msg.payload === "object" && msg.payload.NewPhonebookID) {
							args = msg.payload;
						} else {
							args = {
								NewPhonebookID: node.phonebookId ? node.phonebookId : 0
							}
						}
					break;
				}
				node.config.fritzbox.services["urn:dslforum-org:service:X_AVM-DE_OnTel:1"].actions[action](args)
					.then(function(response) {
						var url = response[urlkey];
						url += query;
						return Promise.promisify(request, {multiArgs: true})({uri: url, rejectUnauthorized: false});
					}).then(function(result) {
						var body = result[1];
						return Promise.promisify(parser.parseString)(body);
					}).then(function(result) {
						msg.payload = result;
						node.send(msg);
					}).catch(function(error) {
						node.error(`Receiving Calllist / Phonebook failed. Error: ${error}`, msg);
					});
			} else {
				node.warn("Device not ready.");
				node.config.reinit();
			}
		});

		node.on('close', function() {
			node.config.removeListener('statusUpdate', node.status);
		});
	}
	RED.nodes.registerType("fritzbox-calllist", FritzboxList);
	RED.nodes.registerType("fritzbox-phonebook", FritzboxList);

};
<commit_msg>Allow IGD or TR064 to fail, fixes #29<commit_after>var Fritzbox = require("fritzbox"),
http = require("http"),
xml2js = require("xml2js");

var Promise = require("bluebird");
var request = require("request");

var parser = xml2js.Parser({explicitRoot: false, explicitArray: false});

module.exports = function(RED) {

	RED.httpAdmin.get('/fritzbox/services', function(req, res, next) {
		var url = req.query.url;
		var config = {
			host: req.query.url
		};

		var fritzbox = new Fritzbox.Fritzbox(config);

		Promise.all([fritzbox.initIGDDevice(), fritzbox.initTR064Device()].map(p => p.catch(error => null)))
			.then(function() {
				var services = Object.keys(fritzbox.services);
				res.end(JSON.stringify(services));
			}).catch(function(error) {
				res.end();
			});
	});

	RED.httpAdmin.get('/fritzbox/actions', function(req, res, next) {
		var service = req.query.service;

		var config = {
			host: req.query.url
		};

		var fritzbox = new Fritzbox.Fritzbox(config);

		Promise.all([fritzbox.initIGDDevice(), fritzbox.initTR064Device()].map(p => p.catch(error => null)))
			.then(function() {
				var actions = fritzbox.services[service].actionsInfo;
				res.end(JSON.stringify(actions));
			}).catch(function(error) {
				res.end();
			});
	});

	function FritzboxConfig(n) {
		RED.nodes.createNode(this, n);
		var node = this;
		node.host = n.host;
		node.timer = null;
		node.state = null;

		if(!node.host) return;

		var config = {
			host: n.host,
			user: node.credentials.username,
			password: <PASSWORD>,
			port: n.port,
			ssl: n.ssl
		};

		node.fritzbox = new Fritzbox.Fritzbox(config);

		node.reinit = function() {
			Promise.all([fritzbox.initIGDDevice(), fritzbox.initTR064Device()].map(p => p.catch(error => null)))
			.then(function() {
					updateStatus("ready");
				}).catch(function(error) {
					node.error(`Initialization of device failed ${error}. Check configuration.`);
					updateStatus("error");
				});
		};

		var updateStatus = function(status) {
			node.state = status;
			switch(status) {
				case "init":
					node.emit("statusUpdate", {fill:"yellow",shape:"ring",text:"Initializing device ..."});
					break;
				case "ready":
					node.emit("statusUpdate", {fill:"green",shape:"dot",text:"Ready"});
					break;
				case "error":
					node.emit("statusUpdate", {fill:"red",shape:"ring",text:"Error"});
					break;
			}
		};
		node.reinit();
	}
	RED.nodes.registerType("fritzbox-config", FritzboxConfig, {
		credentials: {
			username: {type: "text"},
			password: {type: "password"}
		}
	});


	function FritzboxIn(n) {
		RED.nodes.createNode(this,n);
		var node = this;
		node.service = n.service;
		node.action = n.action;
		node.config = RED.nodes.getNode(n.device);

		node.config.on('statusUpdate', node.status);

		node.on('input', function(msg) {
			if(node.config.state === "ready" && node.config.fritzbox) {
				var service = msg.service ? msg.service : node.service;
				var action = msg.action ? msg.action : node.action;

				node.config.fritzbox.services[service].actions[action](msg.payload)
					.then(function(result) {
						msg.payload = result;
						node.send(msg);
					}).catch(function(error) {
						node.error(`Action failed with error: ${error}`, msg);
					});
			} else {
				node.warn("Device not ready.");
				node.config.reinit();
			}
		});

		node.on('close', function() {
			node.config.removeListener('statusUpdate', node.status);
		});
	}
	RED.nodes.registerType("fritzbox-in", FritzboxIn);

	function FritzboxList(n) {
		RED.nodes.createNode(this,n);
		var node = this;
		node.max = n.max;
		node.maxdays = n.maxdays;
		node.action = n.action;
		node.listurl = n.listurl;
		node.phonebookId = n.id;
		node.config = RED.nodes.getNode(n.device);

		node.config.on('statusUpdate', node.status);

		node.on('input', function(msg) {
			if(node.config.state === "ready" && node.config.fritzbox) {
				var args = {};
				var action = n.action;
				var query = "";
				var urlkey = n.listurl;

				switch (action) {
					case "GetCallList":
						if(n.maxdays) {
							query += "&days=" + n.maxdays;
						}
						if(n.max) {
							query += "&max=" + n.max;
						}
					break;
					case "GetPhonebook":
						if (typeof msg.payload === "object" && msg.payload.NewPhonebookID) {
							args = msg.payload;
						} else {
							args = {
								NewPhonebookID: node.phonebookId ? node.phonebookId : 0
							}
						}
					break;
				}
				node.config.fritzbox.services["urn:dslforum-org:service:X_AVM-DE_OnTel:1"].actions[action](args)
					.then(function(response) {
						var url = response[urlkey];
						url += query;
						return Promise.promisify(request, {multiArgs: true})({uri: url, rejectUnauthorized: false});
					}).then(function(result) {
						var body = result[1];
						return Promise.promisify(parser.parseString)(body);
					}).then(function(result) {
						msg.payload = result;
						node.send(msg);
					}).catch(function(error) {
						node.error(`Receiving Calllist / Phonebook failed. Error: ${error}`, msg);
					});
			} else {
				node.warn("Device not ready.");
				node.config.reinit();
			}
		});

		node.on('close', function() {
			node.config.removeListener('statusUpdate', node.status);
		});
	}
	RED.nodes.registerType("fritzbox-calllist", FritzboxList);
	RED.nodes.registerType("fritzbox-phonebook", FritzboxList);

};

{'fraction_non_alphanumeric': 0.17389660712598054, 'fraction_numerical': 0.003307815896418108, 'mean_word_length': 3.296386520503451, 'pattern_counts': {'":': 10, '<': 5, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 6}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2379494', 'n_tokens_mistral': 4462, 'n_tokens_neox': 3578, 'n_words': 627}