Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. [Skript] Wiederherstellen und Auflisten von Skripten

    NEWS

    • 15. 05. Wartungsarbeiten am ioBroker Forum

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    [Skript] Wiederherstellen und Auflisten von Skripten

    This topic has been deleted. Only users with topic management privileges can see it.
    • F
      fastfoot last edited by fastfoot

      Das Skript kann aus diversen Backupdateien

      • Skripte wiederherstellen
        • als Importdatei im Dateisystem, restoreToFilesystem im Standard false
        • direkt in die Objektdatenbank, restoreToSystemDB im Standard false
          • zur 'Sicherheit' und zum Schutz vor Überschreiben kann an den Namen das Suffix scriptSuffix angegeben werden, im Standard ist es auf '_rcvr' gesetzt
      • Skripte auflisten
        • als Datei, generateListing im Standard true, wird in outputPath gespeichert
        • als JSON Tabelle in einem Datenpunkt zur Verwendung in VIS, generateTable im Standard true
          • der DP wird in idBase und idJson angegeben und wird vom Skript erstellt falls generateTable true ist.
      • Backupdateien können sein
        • Backup der Objektdatenbank in /opt/iobroker/iobroker-data/backup-objects
        • Backupdateien des BackitUp Adapters in /opt/iobroker/backups
        • Exportdatei des Javascript Adapters
        • Einzelne Skriptdatei

      hierzu dienen verschiedene Filter-Arrays mit denen man die Ergebnisse einschränken kann. Groß- Kleinschreibung ist dabei egal, Teilausdrücke sind erlaubt, es sind reguläre Ausdrücke möglich. Die Filter können kombiniert werden

      • Namenfilter scriptFilter
        • ['wetter', '^a'] findet Skripte mit wetter im Namen oder die mit a oder A beginnen
      • Inhaltsfilter contentFilter
        • ['0_userdata.myState', 'sendTo'] findet Skripte welche im Code 0_userdata.myState oder sendTo enthalten
      • Typfilter typeFilter
        • ['Blockly', '^R'] findet nur Blockly- und Rules Skripte
      • Ordnerfilter includeFolders
        • ['tools', 'Forum'] findet nur Skripte in den Ordnern Tools und Forum und deren Unterordnern
      • Ordnerfilter excludeFolders
        • ['/'] oder ['root'] Nur Skripte welche in Ordnern sind werden gefunden
        • ['Forum', 'Tools'] Skripte in diesen Ordnern und ihren Unterordnern werden ignoriert

      Es macht keinen Sinn die beiden Ordnerfilter zu kombinieren!

      Anleitung:
      Mit den Standardsettings(inputFile = autoObjects) kann das Skript ohne weitere Einstellungen sofort gestartet werden. In einem neu aufgesetzten System funktioniert das jedoch nicht da ja noch keine Backupdateien existieren und die wohl auch keine Skripte enthalten

      • Ordner für die Backupdatei anlegen und in inputPath angeben. Standard ist /home/iobroker/scriptInput
      • Die Datei in den Ordner inputPath kopieren und in inputFile angeben. Bei Verwendung eines der drei autoxxxxxxxx Namen kann die Erstellung des inputPath entfallen
        • autoObjects - das zuletzt vom JS-Controller erstellte Backup wird verwendet
        • autoBackup - die letzte Backupdatei des BackitUp Adapters wird verwendet
        • autoScript - die letzte Backupdatei für Skripte des BackitUp Adapters wird verwendet
      • Ausgabeordner in outputPath benennen, Standard ist /home/iobroker/scriptOutput. Der Ordner wird bei Skriptstart erstellt bzw. geleert.
      • Skript starten, das Listing befindet sich in outputPath

      /**
      * Name:            scriptRecovery
      * Zweck:           Wiederherstellen/Auflisten von Skripten aus verschiedenen Quellen
      * Datum:           24.01.2023
      * Autor:           @fastfoot
      * Forum:           https://forum.iobroker.net/post/930558
      * 
      * Changelog:       24.01.2023 - verbessertes Error-Handling
      *                  21.01.2023 - Windows/Mac kompatibel
      */
      
      /*                                                        Einstellungen                                               */
      
      // zusätzliche Meldungen, dafür unbedingt auch in der JS-Instanz den Debug-Modus aktivieren!!!
      const dbg = false;
      
      // hier wird die JSON Tabelle gespeichert, der DP wird erstellt wenn generateTable true ist
      const idBase = "0_userdata.0.scriptRecovery";
      const idJson = "jsonTable";
      
      // erzeugt eine JSON Tabelle der gefundenen Skripte für eine evtl. VIS
      const generateTable = true;
      
      // erzeugt ein Listing der gefundenen Skripte(__Listingxxx.json)
      const generateListing = true;
      
      // Dateien ins Filesystem schreiben, false = brauchbar wenn man nur ein Listing will
      const restoreToFilesystem = false;
      
      // Extension für importierte Skripte, zur Unterscheidung von existierenden Skripten.
      const scriptSuffix = "_rcvr";
      
      // Skripte werden sofort ins System geladen(Endung: wie in scriptSuffix) ACHTUNG: AUF EIGENE GEFAHR!!!!
      // existierende Skripte werden nicht überschrieben
      const restoreToSystemDB = false;
      
      // Array Skriptnamen-Filter, wenn vorhanden werden nur diese  Skripte behandelt z.B. ['script 1','script 2']
      // Nur Teil-Namens sind erlaubt und Groß- Kleinschreibung ist egal
      // const scriptFilter = ['^[abc]', '[xyz0-9]$', 'script'];// Skripte beginnen mit a,b oder c oder enden mit x,y,z oder einer Zahl oder haben <<script>> im Namen
      const scriptFilter = [''];
      
      // Array Inhaltsfilter z.B. ['0_userdata.0.example_state', 'Wetter'] zum Suchen nach bestimmten Begriffen
      // const contentFilter = ['0_user', 'sql', 'sendto'];
      const contentFilter = [''];
      
      // Array - Skripte in diesen Ordnern werden nicht berücksichtigt(für rootFolder 'root' oder '/')
      // const excludeFolders = ['/','global', 'löschen'];
      const excludeFolders = [''];
      
      // Array - Nur Skripte in diesen Ordnern und deren Unterordnern werden berücksichtigt(für NUR rootFolder 'root' oder '/')
      // const includeFolders = ['/','tools', 'forum'];
      const includeFolders = [''];
      
      // Array Typ Filter um nur bestimmte Typen zu berücksichtigen (Blockly, Javascript, Rules, Typescript)
      // const typeFilter = ['Blockly','javas'];// findet Blockly- oder Javascript Skripte
      const typeFilter = [''];
      
      // hier liegt die in inputFile definierte Datei, entweder Archiv oder bereits extrahierte Datei
      let inputPath = "../../scriptInput";
      
      // hier landen die extrahierten Skripte und die Listing-Datei, wird bei Skriptstart geleert und angelegt wenn nicht vorhanden
      const outputPath = "../../scriptOutput";
      
      // Datei mit den Skripten(autoObjects = letzte objects.json[l], autoBackup = letzte backupdatei, autoScripts = letztes Skript Backup)
      let inputFile = "";
      
      //                                                       Beispiele für mögliche Dateien
      // letzte Dateien JS-Controller und BackitUp-Adapter
      inputFile = "autoObjects";
      // inputFile = "autoBackup";
      // inputFile = "autoScripts";
      
      // Backup von JS-Controller
      // inputFile = '2023-01-23_13-30_objects.jsonl.gz';
      // inputFile = "objects.jsonl";
      // inputFile = "2022-12-19_12-18_objects.json.gz";
      // inputFile = "objects.json";
      
      // BackitUp-Adapter
      // inputFile = "iobroker_2023_01_23-13_34_49_backupiobroker.tar.gz";
      // inputFile = "backup.json";
      // inputFile = "javascripts_2023_01_23-13_35_04_backupiobroker.tar.gz";
      // inputFile = "script.json";
      
      // Konsole: 'iobroker backup'
      // inputFile = "2023_01_23-13_36_02_backupiobroker.tar.gz";
      
      // JS-Adapter Export
      // inputFile = "2023-01-24-scripts.zip";
      // inputFile = "FullBackup-scripts_2023-01-11.zip";
      
      // Einzelskript
      // inputFile = 'sqlBlockly.js';
      
      /* **************************************************************************************
      * *******************                                                *******************
      * *******************       Ab hier keine Änderungen vornehmen       *******************
      * *******************                                                *******************
      * **************************************************************************************
      */
      // @ts-ignore
      const fse = require("fs-extra");
      const Path = require("path");
      // @ts-ignore
      const tar = require('tar');
      // @ts-ignore
      const JSZip = require('jszip');
      const zlib = require('node:zlib');
      const { pipeline } = require('node:stream');
      // const os = require("os");
      
      // hier werden die aus evtl. Archiven(tar.gz, gz, zip) extrahierten Skripte temporär abgelegt. Wird bei Skriptstart angelegt wenn nicht vorhanden
      const tmpRoot = '../../scriptTmp';// os.tmpdir();
      const tmpPath = Path.resolve(tmpRoot, scriptName.slice(10));
      
      // Ignoriert Fehler in der JSONL Datenbank
      const ignoreJsonlErrors = true;
      
      // komprimiere JSONL Datenbank beim Einlesen
      const compressJsonl = false;
      
      // wichtig damit der mirrorPath nicht überschrieben wird und somit alle Skripte gelöscht werden
      const mirrorPath = getObject("system.adapter.javascript.0").native.mirrorPath;
      
      start();
      
      async function start() {
         if (dbg) console.error('Debugmode aktiv, unbedingt auch in der JS-Instanz den Debug-Modus aktivieren!!!');
         fse.ensureDirSync(tmpPath);
         fse.emptyDirSync(tmpPath);
         fse.ensureDirSync(outputPath);
      
         if (outputPath != mirrorPath) {
             fse.emptyDirSync(outputPath);
         }
         try { await main(); }
         catch (e) { return console.error('Ein Fehler ist aufgetreten!') }
      
         stopScript(scriptName);
      }
      
      async function main() {
         let dataFile = '';
         let allScripts = {};
         switch (inputFile.toLocaleLowerCase()) {
             case 'autoobjects':
                 inputPath = '../../iobroker-data/backup-objects';
                 inputFile = await getNewestFile(inputPath, /objects\.jsonl\.gz/);//await getLatestObjects();
                 break;
             case 'autobackup':
                 inputPath = '../../backups';
                 inputFile = await getNewestFile(inputPath, /^[2i.+\.tar\.gz]/);//await getLatestBackup();
                 break;
             case 'autoscripts':
                 inputPath = '../../backups';
                 inputFile = await getNewestFile(inputPath, /^javascript.+\.tar\.gz/);//await getLatestScripts();
                 break;
             default:
         }
      
         if (inputFile === '' || inputFile === undefined) {
             return console.error(`[main()] - Keine Datei in ${inputPath} gefunden!`);
         }
      
         if (!(await fse.pathExists(Path.resolve(inputPath, inputFile)))) {
             return console.error(`[main()] - Die Datei ${inputFile} in ${inputPath} wurde nicht gefunden!`);
         }
      
         const fullArchiveName = Path.resolve(inputPath, inputFile);
         if (inputFile.indexOf('.tar.gz') > 0) {
             dataFile = await tarExtract(fullArchiveName);
      
             if (dataFile.endsWith('backup.json')) {
                 allScripts = await handleBackup(dataFile);
             } else if (dataFile.endsWith('script.json')) {
                 allScripts = await handleJson(dataFile);
             }
         } else if (inputFile.endsWith('backup.json')) {
             allScripts = await handleBackup(fullArchiveName);
         } else if (inputFile.endsWith('script.json')) {
             allScripts = await handleJson(fullArchiveName);
         } else if (inputFile.indexOf('.jsonl.gz') > 0) {
             dataFile = await gzipExtract(fullArchiveName);
             allScripts = await handleJsonl(dataFile);
         } else if (inputFile.endsWith('objects.jsonl')) {
             allScripts = await handleJsonl(fullArchiveName);
         } else if (inputFile.indexOf('.json.gz') > 0) {
             dataFile = await gzipExtract(fullArchiveName);
             allScripts = await handleJson(dataFile);
         } else if (inputFile.endsWith('objects.json')) {
             allScripts = await handleJson(fullArchiveName);
         } else if (inputFile.indexOf('.zip') > 0) {
             dataFile = await zipExtract(fullArchiveName);
             if (dataFile)
                 allScripts = await handleExport(dataFile);
             else
                 return console.warn('Keine passenden Dateien gefunden, Filter prüfen!');
         } else if (inputFile) {
             try {
                 let b = fse.lstatSync(fullArchiveName).isDirectory()
             } catch (e) {
                 return console.error('[main()] - Fehler: ' + e);
             }
             allScripts = await handleExport(inputFile, inputPath);
         } else {
             return console.error('[main()] - Fehler: Variable inputFile falsch belegt')
         }
         if (dbg) {
             console.debug('[main()] - datafile = ' + (dataFile != '' ? dataFile : inputFile))
         };
         handleScripts(allScripts);
      }
      
      async function handleScripts(allScripts) {
         let res = {};
         let tableData = [];
      
         for (let key in allScripts) {
             let fileExtension = "";
             let script = allScripts[key];
             const keyNew = key + scriptSuffix;
             const folder = key.replace('script.js.', '').replace(script.common.name, '').replace(/\.$/, '');
      
             // exclude Filter
             if (isExcludedFolder(folder)) continue;
             // folder Filter
             if (!isIncludedFolder(folder)) continue;
             // script Filter
             if (!isName(script.common.name)) continue;
             // Typ Filter
             if (!isType(script.common.engineType)) continue;
             // Inhalts Filter
             if (!isContent(script.common.source)) continue;
      
             script.common.enabled = false;
             script.common.debug = false;
             script.common.verbose = false;
             script.common.expert = false;
      
             if (!existsObject(keyNew) && restoreToSystemDB) {
                 if (dbg) console.debug('[handleSripts()] - Key: ' + key);
                 const oldName = script.common.name;
                 script.common.name += scriptSuffix;
                 await createScriptFolder(keyNew.slice(0, keyNew.length - script.common.name.length - 1));
                 await setObjectAsync(keyNew, { type: "script", common: script.common, native: {} });
      
                 script.common.name = oldName;
             }
             if (restoreToFilesystem) {
                 let data = script.common.source;
      
                 switch (script.common.engineType.toLowerCase()) {
                     case "blockly":
                         fileExtension = ".xml";
                         if (script.common.source.length)
                             data = handleBlockly(data);
                         else console.warn("217 Leeres Skript: " + script.common.name);
                         break;
                     case "rules":
                         fileExtension = ".js";
                         break;
                     case "javascript/js":
                         fileExtension = ".js";
                         break;
                     case "typescript/ts":
                         fileExtension = ".ts";
                         break;
                     default:
                         fileExtension = ".js";
                 }
      
                 if (data && data.length) {
                     if (dbg) console.debug('[handleSripts()] - Key: ' + key);
                     if (dbg) console.debug('[handleSripts()] - Pfad: ' + Path.resolve(outputPath, key.substring(10)));
                     let scriptName = key.split('.').pop();
                     let scriptPfad = key.slice(10, key.length - scriptName.length - 1).replace(/\./g, '/');
                     scriptPfad = Path.resolve(outputPath, scriptPfad);
                     fse.ensureDirSync(scriptPfad);
                     fse.writeFile(
                         Path.resolve(scriptPfad, scriptName) + fileExtension,
                         data,
                         (e) => {
                             if (e) console.error("[handleSripts()] - Fehler beim Schreiben der Datei:" + e.code);
                         }
                     );
                 } else {
                     if (dbg) console.debug('[handleSripts()] - No source data: ' + key);
                 }
             }
      
             if (generateTable) {
                 tableData = generateJsonTable(script, tableData);
             }
             if (dbg) console.debug('[handleSripts()] - Key: ' + key)
             res[key.substring(10)] = script.common.engineType;
         }
      
         if (generateTable) {
             if (!tableData.length) {
                 tableData.push({ Warnung: 'Keine Daten vorhanden, Filter prüfen!' });
             } else {
                 tableData.sort((a, b) => a.Name.localeCompare(b.Name));
                 let no = 0;
                 tableData.forEach(rec => rec.Nr = ++no);
             }
             if (await createDatapoints(idBase)) {
                 setState(`${idBase}.${idJson}`, JSON.stringify(tableData));
             }
         }
      
         if (generateListing) {
             let b = {};
             if (Object.keys(res).length) {
                 // sortieren
                 let a = Object.keys(res).sort();
                 for (let i = 0; i < a.length; i++) {
                     b[i + 1 + " " + a[i]] = res[a[i]];
                 }
             } else {
                 b.Warnung = 'Keine Daten vorhanden, Filter prüfen!';
             }
             const fullFileName = Path.resolve(outputPath, '__Listing_' + inputFile + ".json");
             fse.writeFile(fullFileName, JSON.stringify(b, null, 3), (e) => {
                 if (e) console.error("[handleSripts()] - Schreibfehler bei Ergebnisdatei");
             });
         }
      }
      
      /* extrahiere Skripte aus iobroker Datenbank (neueste Version JSONL)*/
      async function handleJsonl(dataFile) {
         const allScripts = {};
         // @ts-ignore
         const DB = require("@alcalzone/jsonl-db").JsonlDB;
         const dbOptions = {
             autoCompress: { onOpen: compressJsonl },
             ignoreReadErrors: ignoreJsonlErrors,
         };
         const db = new DB(dataFile, dbOptions);
         try {
             await db.open();
         } catch (e) {
             console.error(`[handleJsonl()] - Fehler beim Öffnen der Datenbank ${dataFile} in ${inputPath}` + e);
         }
         db.forEach((obj, key) => {
             if (obj.type === "script") {
                 allScripts[key] = obj;
             }
         });
         await db.close();
      
         return allScripts;
      }
      
      /* extrahiere Skripte aus iobroker Datenbank (ältere Version JSON)*/
      async function handleJson(dataFile) {
         let allData = '';
         const allScripts = [];
         let allObjects = new Object();
         try {
             allData = fse.readFileSync(dataFile, "utf8");
         } catch (e) {
             console.error(`[handleJson()] - Fehler beim Lesen von ${inputFile} in ${inputPath}: ` + e);
         }
         try {
             allObjects = JSON.parse(allData);
         } catch (e) {
             console.error("[handleJson()] - Fehlerhafte Daten: ==> " + e);
         }
         for (let prop in allObjects) {
             const obj = allObjects[prop];
             if (obj.type === "script") {
                 allScripts[prop] = obj;
             }
         }
         return allScripts;
      }
      
      /* extrahiere Skripte aus backup.json des Backitup-Adapers */
      async function handleBackup(dataFile) {
         let allData = '';
         const allScripts = {};
         let allObjects = [];
         try {
             allData = fse.readFileSync(dataFile, "utf8");
         } catch (e) {
             console.error(`[handleBackup()] - Fehler beim Lesen von ${inputFile} in ${inputPath}: ` + e);
         }
         try {
             allObjects = JSON.parse(allData).objects;
         } catch (e) {
             console.error('[handleBackup()] - Fehlerhafte Daten: ==> ' + e);
         }
      
         for (let obj of allObjects) {
             if (obj.value.type === 'script') {
                 allScripts[obj.id] = obj.value;
             }
         }
         return allScripts;
      }
      
      /* bearbeite Skripte */
      async function handleExport(scriptListx, dir = tmpPath) {
         const allScripts = {};
         const scriptList = scriptListx.trim().split(' ');
         let fileObj = {};
         let sourceData = '';
      
         scriptList.forEach((file) => {
             const scriptObj = {
                 "_id": "script.js.",
                 "common": {
                     "name": "",
                     "engineType": "JavaScript/js",
                     "engine": "system.adapter.javascript.0",
                     "source": "",
                     "enabled": false,
                     "debug": false,
                     "verbose": false
                 },
                 "type": "script",
                 "native": {},
                 "ts": 0,
             }
             const scriptNam = getFileName(file);
             if (dbg) console.debug('[handleExport()] - File: ' + file);
             if (dbg) console.debug('[handleExport()] - Name: ' + scriptNam);
             let scriptData;
             scriptData = fse.readFileSync(Path.resolve(dir, file), 'utf8');
             const regExport = new RegExp(/\/\* -- do not edit/);
             if (regExport.test(scriptData)) {
                 const regObj = new RegExp(/(\{.+\})(?:\n-- do not edit prev)/s);
                 sourceData = scriptData.substring(scriptData.indexOf('END --*/') + 9);
                 if (regObj.test(scriptData)) {
                     try {
                         fileObj = JSON.parse(regObj.exec(scriptData)[1]) || '{}';
                     } catch (e) {
                         console.error('[handleExport()] - Fehler');
                     }
                 }
             } else {
                 sourceData = scriptData;
             }
             const engineType = getEngineType(sourceData);
             if (dbg) console.debug('[handleExport()] - ' + engineType);
             if (dbg) console.debug('[handleExport()] - Type: ' + engineType);
             if (dbg) console.debug('[handleExport()] - File: ' + file);
             if (dbg) console.debug('[handleExport()] - Id: ' + file.replace(/\//g, '.').replace(/.json$/, ''));
             scriptObj._id = `script.js.${file.replace(/\//g, '.').replace(/.json$|.js$/, '')}`;
             scriptObj.ts = fileObj.ts || Date.now();
             scriptObj.common.name = scriptNam;
             scriptObj.common.source = sourceData;
             scriptObj.common.engineType = fileObj.engineType || engineType;
             scriptObj.common.engine = fileObj.engine || 'system.adapter.javascript.0';
             scriptObj.common.enabled = fileObj.enabled || false;
             scriptObj.common.debug = fileObj.debug || false;
             scriptObj.common.verbose = fileObj.verbose || false;
             if (fileObj && fileObj.engineType && fileObj.engineType.toLowerCase() === 'typescript/ts') {
                 scriptObj.common.sourceHash = fileObj.sourceHash;
                 scriptObj.common.compiled = fileObj.compiled;
             }
      
             allScripts[scriptObj._id] = scriptObj;
      
         })
      
         return allScripts;
      }
      
      function generateJsonTable(scriptData, tableData) {
         const data = scriptData.common.source;
         const dt = scriptData.ts && new Date(scriptData.ts) || 0;
      
         let Zweck = '-',
             Autor = '-',
             Datum = dt && dt.getFullYear() + '-' + dt.getMonth() + 1 + '-' + dt.getDate() || '-',
             Instance = scriptData.common.engine.split('.').pop(),
             sName = scriptData.common.name
      
         if (/(Zweck|Purpose):\s+(.*)/.test(data)) {
             if (dbg) console.debug('[generateJsonTable()] - Zweck: ' + /(Zweck|Purpose):\s+(.*)/.exec(data))
             Zweck = /(Zweck|Purpose):\s+(.*)/.exec(data)[2];
         }
         if (/(Autor|Author):\s+(.*)/.test(data)) {
             Autor = /(Autor|Author):\s+(.*)/.exec(data)[2];
         }
         if (/(Datum|Date):\s+(.*)/.test(data)) {
             Datum = /(Datum|Date):\s+(.*)/.exec(data)[2].replace(/(\d+).(\d+).(\d+)/, "$3-$2-$1");
         }
         let p = scriptData._id.lastIndexOf('.');
         let ps = '';
         if (p === 9) ps = '/';
         else ps = '/' + scriptData._id.slice(10, p);
         tableData.push({
             Nr: 0,
             Name: sName,
             Pfad: ps,
             Zweck: Zweck,
             Autor: Autor,
             Datum: Datum,
             Instanz: Instance,
             Typ: scriptData.common.engineType.split('/')[0]
         })
      
         return tableData;
      }
      
      function isName(name) {
         if (dbg) console.debug('[isName()] - Name: ' + name);
         const regExp = new RegExp(scriptFilter.slice(0).join("|"), "i");
         return regExp.test(name);
      }
      
      function isExcludedFolder(folder) {
         if (folder === '') folder = 'root/';
         const filter = excludeFolders.slice(0).join("|") || '&&&';
         if (dbg) console.debug('[isExcludedFolder()] -  Folder: ' + folder);
         if (dbg) console.debug('[isExcludedFolder()] - Filter: ' + filter);
         const regExp = new RegExp(filter, "i");
         return regExp.test(folder);
      }
      
      function isIncludedFolder(folder) {
         if (folder === '') folder = 'root/';
         const filter = includeFolders.slice(0).join("|");
         if (dbg) console.debug('[isIncludedFolder()] - Folder: ' + folder);
         if (dbg) console.debug('[isIncludedFolder()] - Filter: ' + filter);
         const regExp = new RegExp(filter, "i");
         return regExp.test(folder);
      }
      
      function isType(typ) {
         const regExp = new RegExp(typeFilter.slice(0).join("|"), "i");
         return regExp.test(typ);
      }
      
      function isContent(source) {
         const regExp = new RegExp(contentFilter.slice(0).join("|"), "i");
         return regExp.test(source);
      }
      
      function handleBlockly(source) {
         const pos = source.lastIndexOf("\n");
         if (pos !== -1) {
             source = source.substring(pos + 3);
             if (source.indexOf("JTNDeG1sJTIweG1") > -1) {
                 source = decodeURIComponent(
                     Buffer.from(source, "base64").toString("utf8")
                 );
                 return prettifyXml(source);
             }
         } else return prettifyXml(source);
      
         //from Stackoverflow
         function prettifyXml(xml) {
             var reg = /(>)\s*(<)(\/*)/g;
             xml = xml.replace(/\r|\n/g, ''); //deleting already existing whitespaces
             xml = xml.replace(reg, "$1\r\n$2$3");
             return xml;
         }
      }
      
      const tarList = async file => {
         const filenames = []
         await tar.list({
             file,
             onentry: entry => {
                 if (/script.json|backup.json/.test(entry.path)) {
                     filenames.push(entry.path)
                 }
             },
         })
         return filenames
      }
      
      const tarExtract = async archive => {
         const fileList = await tarList(archive);
         const strip = fileList.includes('backup/backup.json') ? 1 : 0;
         if (dbg) console.debug(strip + '   ' + fileList);
         const opts = {
             file: archive,
             strip,
             cwd: tmpPath
         }
         await tar.extract(opts, fileList);
         return Path.resolve(tmpPath, fileList[0].replace('backup/', ''));
      }
      
      const zipExtract = async archive => {
         return new Promise(async (resolve, reject) => {
             let fileList = [];
             const data = fse.readFileSync(archive)
             const zip = new JSZip();
             const zipObj = await zip.loadAsync(data);
             zipObj.filter((a, b) => false)
             zipObj.folder().forEach(async (fileName, entry) => {
                 const fullPath = Path.resolve(tmpPath, fileName);
                 const pos = fullPath.lastIndexOf(Path.sep) + 1;
                 const realName = fullPath.substring(pos);
                 const realPath = fullPath.substring(0, pos - 1);
                 if (!entry.dir && isName(realName) && realName.indexOf('_dir.json') < 0) {
                     if (dbg) console.debug(realPath + '  = ' + realName);
                     fse.ensureDirSync(Path.resolve(tmpPath, realPath));
                     fse.writeFileSync(fullPath, Buffer.from(entry._data.compressedContent));
                     fileList.push(fileName);
                 }
             })
             resolve(fileList.join(' '));
         })
      }
      
      const gzipExtract = async archive => {
         return new Promise(async (resolve, reject) => {
             const objectsFile = archive.split(Path.sep).pop().replace('.gz', '').substring(17);
             const gunzip = zlib.createGunzip();
             const readStream = fse.createReadStream(archive);
             const writeStream = fse.createWriteStream(Path.resolve(tmpPath, objectsFile));
             readStream.on('error', e => {
                 reject(console.error(e));
             })
             writeStream.on('error', e => {
                 reject(console.error(e));
             })
      
             pipeline(readStream, gunzip, writeStream, e => {
                 if (e) reject(console.error(e));
                 resolve(Path.resolve(tmpPath, objectsFile));
             })
         })
      }
      
      function getFileName(fullName) {
         return fullName.substring(fullName.lastIndexOf('/') + 1, fullName.lastIndexOf('.'));
      }
      
      function isBlockly(sourceData) {
         const pos = sourceData.lastIndexOf('\n');
         const testData = sourceData.substring(pos + 1);
         return /^[\/][\/]JTNDeG1sJTIwe/.test(testData);
      }
      
      function isRules(sourceData) {
         const pos = sourceData.lastIndexOf('\n');
         const testData = sourceData.substring(pos + 1);
         return /[/][/]{"triggers":/.test(testData);
      }
      
      function isTypescript(sourceData) {
         return /(let|const|var)\s*[a-zA-Z0-9]+:*(string|object|number)/.test(sourceData);
      }
      
      function getEngineType(sourceData) {
         return isBlockly(sourceData) ? 'Blockly'
             : isRules(sourceData) ? 'Rules'
                 : isTypescript(sourceData) ? 'Typescript/ts'
                     : 'Javascript/js';
      }
      
      async function getNewestFile(dir, filter) {
         return new Promise((resolve, reject) => {
             return fse.readdir(dir, (e, f) => {
                 if (e) reject(e);
                 const s = f.map(f => {
                     let t;
                     const ff = Path.resolve(dir, f);
                     try {
                         t = fse.lstatSync(ff).mtime.getTime();
                     } catch (e) {
                         reject(e)
                     }
                     return { name: f, time: t }
                 })
                     .sort((a, b) => b.time - a.time)
                     .map(v => v.name)
                     .filter(v => filter.test(v));
                 resolve(s[0]);
             })
         })
      }
      
      // create data points if not existing
      async function createDatapoints(idBase) {
         let dp,
             idKey,
             firstRun = false;
      
         if (!idBase.startsWith('0_userdata.0')) return firstRun;
         firstRun = true;
         const stateAttributes = {};
         stateAttributes[idJson] = { "name": "Skripte Info", "type": "json", "role": "", "read": true, "write": true, "desc": "enthält Skript Tabelle", "def": "" }
      
         //createScriptFolder(idBase);
         for (let key in stateAttributes) {
      
             idKey = idBase + '.' + key;
      
             if (!(await existsStateAsync(idKey))) {
                 dp = stateAttributes[key];
                 firstRun = true;
                 let e = await createStateAsync(idKey, dp);
                 if (e) console.error('[createDatapoints()] - createState: ' + e);
             }
         }
      
         return firstRun;
      
      }
      
      async function createScriptFolder(id) {
         const arr = id.split('.');
         const preId = arr[0] + '.' + arr[1];
         if (preId.length === id.length || (preId != 'script.js' /*&& preId != '0_userdata.0'*/)) return;
         const idNew = id.replace(/[\s"]/g, '_');
      
         if (!(await existsObjectAsync(idNew))) {
             const obj = new Object({
                 "type": "folder",
                 "common": {
                     name: arr[arr.length - 1]
                 },
                 "native": {},
             })
      
             await setObjectAsync(idNew, obj);
         }
         arr.pop();
         id = arr.join('.');
         await createScriptFolder(id);
      }
      
      onStop(() => {
         fse.removeSync(tmpPath);
         if (dbg) console.log('[onStop()] - Skript wurde nach Beendigung automatisch gestoppt!');
      })
      

      sigi234 S R 3 Replies Last reply Reply Quote 6
      • sigi234
        sigi234 Forum Testing Most Active @fastfoot last edited by

        @fastfoot

        Cool, auch unter Windows lauffähig?

        F 2 Replies Last reply Reply Quote 0
        • F
          fastfoot @sigi234 last edited by

          @sigi234 jein, die Archiv Entpackroutinen sind (noch!!??) auf Linux ausgelegt. Wenn Du aber die entsprechende Datei entpackst und nach inputPath kopierst sollte es problemlos funktionieren. Ich wollte vermeiden dass man noch zusätzliche Libs installieren muss, überlege aber das evtl. zu ändern

          sigi234 1 Reply Last reply Reply Quote 1
          • sigi234
            sigi234 Forum Testing Most Active @fastfoot last edited by sigi234

            @fastfoot sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

            @sigi234 jein, die Archiv Entpackroutinen sind (noch!!??) auf Linux ausgelegt. Wenn Du aber die entsprechende Datei entpackst und nach inputPath kopierst sollte es problemlos funktionieren. Ich wollte vermeiden dass man noch zusätzliche Libs installieren muss, überlege aber das evtl. zu ändern

            Hm, eventuell ist ja eine eigene Windows Version sinnvoll?

            F 1 Reply Last reply Reply Quote 0
            • liv-in-sky
              liv-in-sky last edited by

              @fastfoot sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

              Inhaltsfilter contentFilter

              ['0_userdata.myState', 'sendTo'] findet Skripte welche im Code Wetter oder sendTo enthalten

              super sache - kleiner fehler in der beschreibung ?

              F 1 Reply Last reply Reply Quote 0
              • F
                fastfoot @sigi234 last edited by

                @sigi234 sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

                Hm, eventuell ist ja eine eigene Windows Version sinnvoll?

                nee, zuviel Supportaufwand. Ich habe aber mittlerweile Libraries gefunden, welche man (hoffentlich!) nicht nachinstallieren muss. Damit sollte es auch unter Windows und Mac laufen. Ich update Post #1 wenn fertig

                1 Reply Last reply Reply Quote 1
                • F
                  fastfoot @liv-in-sky last edited by

                  @liv-in-sky sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

                  kleiner fehler in der beschreibung ?

                  Danke, hab's korrigiert. Du hast ja auch jede Menge Skripte, wie ist die Performance denn bei Dir? Hier benötigt das Skript für 500 Skripte nur wenige Sekunden (ohne Import ins System)

                  liv-in-sky 2 Replies Last reply Reply Quote 0
                  • liv-in-sky
                    liv-in-sky @fastfoot last edited by

                    @fastfoot

                    superschnell - 2-3 sekunden für über 850 scripte (muss mal wieder aufräumen 🙂 )

                    1 Reply Last reply Reply Quote 1
                    • liv-in-sky
                      liv-in-sky @fastfoot last edited by

                      @fastfoot

                      könnte sowas auch gut für die vis gebrauchen 🙂

                      H 1 Reply Last reply Reply Quote 0
                      • H
                        homecineplexx @liv-in-sky last edited by

                        sagt, muss diese Datei

                        /home/iobroker/scriptInput
                        

                        vorhanden sein?

                        liv-in-sky F 2 Replies Last reply Reply Quote 0
                        • liv-in-sky
                          liv-in-sky @homecineplexx last edited by liv-in-sky

                          @homecineplexx du musst den ordner benennen und anlegen - hier mal mein setting des testscript - vielleicht hilft das - ich nutze direkt den backup folder in meinem setting und habe den output folder angelegt

                          const dbg = false;
                          
                          // hier wird die JSON Tabelle gespeichert, der DP wird erstellt wenn generateTable true ist
                          const idBase = "0_userdata.0.scriptRecovery";
                          const idJson = "jsonTable";
                          
                          // erzeugt eine JSON Tabelle der gefundenen Skripte für eine evtl. VIS
                          const generateTable = true;
                          
                          // erzeugt ein Listing der gefundenen Skripte(__Listingxxx.json)
                          const generateListing = true;
                          
                          // Dateien ins Filesystem schreiben, false = brauchbar wenn man nur ein Listing will
                          const restoreToFilesystem = false;
                          
                          // Extension für importierte Skripte, zur Unterscheidung von existierenden Skripten.
                          const scriptSuffix = "_rcvr";
                          
                          // Skripte werden sofort ins System geladen(Endung: wie in scriptSuffix) ACHTUNG: AUF EIGENE GEFAHR!!!!
                          // existierende Skripte werden nicht überschrieben
                          const restoreToSystemDB = false;
                          
                          // Array Skriptnamen-Filter, wenn vorhanden werden nur diese  Skripte behandelt z.B. ['script 1','script 2']
                          // Nur Teil-Namens sind erlaubt und Groß- Kleinschreibung ist egal
                          // const scriptFilter = ['^[abc]', '[xyz0-9]$', 'script'];// Skripte beginnen mit a,b oder c oder enden mit x,y,z oder einer Zahl oder haben <<script>> im Namen
                          const scriptFilter = [''];
                          
                          // Array Inhaltsfilter z.B. ['0_userdata.0.example_state', 'Wetter'] zum Suchen nach bestimmten Begriffen
                          // const contentFilter = ['0_user', 'sql', 'sendto'];
                          const contentFilter = [''];
                          
                          // Array - Skripte in diesen Ordnern werden nicht berücksichtigt(für rootFolder 'root' oder '/')
                          // const excludeFolders = ['/','global', 'löschen'];
                          const excludeFolders = [''];
                          
                          // Array - Nur Skripte in diesen Ordnern und deren Unterordnern werden berücksichtigt(für NUR rootFolder 'root' oder '/')
                          // const includeFolders = ['/','tools', 'forum'];
                          const includeFolders = [''];
                          
                          // Array Typ Filter um nur bestimmte Typen zu berücksichtigen (Blockly, Javascript, Rules, Typescript)
                          // const typeFilter = ['Blockly','javas'];// findet Blockly- oder Javascript Skripte
                          const typeFilter = [''];
                          
                          // hier liegt die in inputFile definierte Datei, entweder Archiv(nur Linux) oder bereits extrahierte Datei
                          let inputPath = "/opt/iobroker/backups";
                          
                          // hier landen die extrahierten Skripte und die Listing-Datei, wird bei Skriptstart geleert und angelegt wenn nicht vorhanden
                          const outputPath = "/Daten/scriptOutput";
                          
                          // Datei mit den Skripten(autoObjects = letzte objects.json[l], autoBackup = letzte backupdatei, autoScripts = letztes Skript Backup)
                          let inputFile = "javascripts_2023_01_18-16_16_18_daily_backupiobroker.tar.gz";
                          
                          //                                                       Beispiele für mögliche Dateien
                          // letzte Dateien JS-Controller und BackitUp-Adapter
                          //inputFile = "iobroker_2023_01_18-16_15_10_daily_backupiobroker.tar.gz";
                          // inputFile = "autoBackup";
                          // inputFile = "autoScripts";
                          
                          // Backup von JS-Controller
                          // inputFile = '2023-01-17_19-16_objects.jsonl.gz';
                          // inputFile = "objects.jsonl";
                          // inputFile = "2022-12-19_12-18_objects.json.gz";
                          // inputFile = "objects.json";
                          
                          // BackitUp-Adapter
                          // inputFile = "iobroker_2023_01_17-17_38_03_backupiobroker.tar.gz";
                          // inputFile = "backup.json";
                          // inputFile = "javascripts_2023_01_17-17_38_18_backupiobroker.tar.gz";
                          // inputFile = "script.json";
                          
                          // Konsole: 'iobroker backup'
                          // inputFile = "2023_01_17-17_45_40_backupiobroker.tar.gz";
                          
                          // JS-Adapter Export
                          //inputFile = "";
                            //2023-01-17-scripts.zip 
                          // Einzelskript
                          // inputFile = 'findObject.json';
                          // inputFile = 'sqlBL.json';
                          // inputFile = 'sqlBL.js';
                          
                          

                          1 Reply Last reply Reply Quote 0
                          • F
                            fastfoot @homecineplexx last edited by

                            @homecineplexx sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

                            sagt, muss diese Datei

                            /home/iobroker/scriptInput
                            

                            vorhanden sein?

                            irgendwo muss deine zu durchsuchende Datei ja liegen 🙂 Du kannst das ja frei wählen. Wenn Du aber zB autoObjects angibst dann ist damit schon klar wo die Datei liegt. Allerdings wird dann nur die neueste Datei durchsucht. Oder du machst es wie liv-in-sky

                            1 Reply Last reply Reply Quote 0
                            • F
                              fastfoot @sigi234 last edited by

                              @sigi234 sagte in [Skript] Wiederherstellen und Auflisten von Skripten:

                              @fastfoot

                              Cool, auch unter Windows lauffähig?

                              probier mal 🙂

                              1 Reply Last reply Reply Quote 0
                              • F
                                fastfoot last edited by

                                kleines Update, die Fehlerbehandlung wurde verbessert. Da das Skript auch unter Windows und Mac lauffähig ist wäre eine Rückmeldung von Benutzern dieser Systeme hilfreich. Vor allem unter Mac ist das Skript gar nicht getestet

                                H 1 Reply Last reply Reply Quote 0
                                • H
                                  homecineplexx @fastfoot last edited by

                                  @fastfoot said in [Skript] Wiederherstellen und Auflisten von Skripten:

                                  kleines Update, die Fehlerbehandlung wurde verbessert. Da das Skript auch unter Windows und Mac lauffähig ist wäre eine Rückmeldung von Benutzern dieser Systeme hilfreich. Vor allem unter Mac ist das Skript gar nicht getestet

                                  Guten Morgen
                                  danke für dein Script, aber eine Frage, warum legst du es nicht in GIT ab, dann hätte man auch eine Versionierung bzw wäre vielleicht einfacher

                                  F 1 Reply Last reply Reply Quote 0
                                  • F
                                    fastfoot @homecineplexx last edited by

                                    @homecineplexx eine Versionierung braucht es nicht, das Skript ist 'fertig' und tut alles wozu ich es geschrieben habe. Ausser evtl. kleinerer Fehlerbehebungen wird sich da also nicht mehr viel tun

                                    1 Reply Last reply Reply Quote 1
                                    • S
                                      sruhsam @fastfoot last edited by

                                      @fastfoot
                                      super Teil, war sehr lange auf der Suche ......

                                      Hat super funktioniert, doch nun kommt aber ein Fehler, bestimmt kein großes ding .......

                                      16:19:25.797	info	javascript.0 (22538) Stop script script.js.common.Restore
                                      16:19:27.683	info	javascript.0 (22538) Start javascript script.js.common.Restore
                                      16:19:27.684	error	javascript.0 (22538) script.js.common.Restore compile failed: at script.js.common.Restore:15
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.558	error	at processImmediate (node:internal/timers:473:21)
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.558	error	at Immediate._onImmediate (/opt/iobroker/node_modules/iobroker.javascript/main.js:1628:17)
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.558	error	at /opt/iobroker/node_modules/iobroker.javascript/main.js:2153:17
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	at prepareScript (/opt/iobroker/node_modules/iobroker.javascript/main.js:2055:37)
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	at createVM (/opt/iobroker/node_modules/iobroker.javascript/main.js:1802:21)
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	at new Script (node:vm:100:7)
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	SyntaxError: Identifier 'dbg' has already been declared
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	^
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	const dbg = false;
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.557	error	script.js.common.Restore compile failed: at script.js.common.Restore:15
                                      
                                      javascript.0
                                      2023-08-25 16:27:43.556	info	Start javascript script.js.common.Restore
                                      
                                      javascript.0
                                      2023-08-25 16:27:36.426	info	Stop script script.js.common.Restore
                                      

                                      Grüße Stephan

                                      1 Reply Last reply Reply Quote 0
                                      • R
                                        Ralf 6 @fastfoot last edited by

                                        @fastfoot
                                        Ich habe es zum Laufen gebracht. Im Fall der Fälle habe ich jetzt ein prima Werkzeug.

                                        Vielen Dank für Deine Mühe. 👍

                                        1 Reply Last reply Reply Quote 0
                                        • First post
                                          Last post

                                        Support us

                                        ioBroker
                                        Community Adapters
                                        Donate

                                        785
                                        Online

                                        31.6k
                                        Users

                                        79.4k
                                        Topics

                                        1.3m
                                        Posts

                                        6
                                        18
                                        1121
                                        Loading More Posts
                                        • Oldest to Newest
                                        • Newest to Oldest
                                        • Most Votes
                                        Reply
                                        • Reply as topic
                                        Log in to reply
                                        Community
                                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                                        The ioBroker Community 2014-2023
                                        logo