Skip to content
  • Home
  • Aktuell
  • Tags
  • 0 Ungelesen 0
  • Kategorien
  • Unreplied
  • Beliebt
  • GitHub
  • Docu
  • Hilfe
Skins
  • Light
  • Brite
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Standard: (Kein Skin)
  • Kein Skin
Einklappen
ioBroker Logo

Community Forum

donate donate
  1. ioBroker Community Home
  2. Deutsch
  3. Skripten / Logik
  4. JavaScript
  5. [Skript] Wiederherstellen und Auflisten von Skripten

NEWS

  • Neuer Blogbeitrag: Monatsrückblick - Dezember 2025 🎄
    BluefoxB
    Bluefox
    10
    1
    315

  • Weihnachtsangebot 2025! 🎄
    BluefoxB
    Bluefox
    24
    1
    1.5k

  • UPDATE 31.10.: Amazon Alexa - ioBroker Skill läuft aus ?
    apollon77A
    apollon77
    48
    3
    9.4k

[Skript] Wiederherstellen und Auflisten von Skripten

Geplant Angeheftet Gesperrt Verschoben JavaScript
18 Beiträge 6 Kommentatoren 2.1k Aufrufe 10 Watching
  • Älteste zuerst
  • Neuste zuerst
  • Meiste Stimmen
Antworten
  • In einem neuen Thema antworten
Anmelden zum Antworten
Dieses Thema wurde gelöscht. Nur Nutzer mit entsprechenden Rechten können es sehen.
  • F Offline
    F Offline
    fastfoot
    schrieb am zuletzt editiert von fastfoot
    #1

    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!');
    })
    

    iobroker läuft unter Docker auf QNAP TS-451+
    SkriptRecovery: https://forum.iobroker.net/post/930558

    sigi234S S R 3 Antworten Letzte Antwort
    6
    • F 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!');
      })
      

      sigi234S Offline
      sigi234S Offline
      sigi234
      Forum Testing Most Active
      schrieb am zuletzt editiert von
      #2

      @fastfoot

      Cool, auch unter Windows lauffähig?

      Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
      Immer Daten sichern!

      F 2 Antworten Letzte Antwort
      0
      • sigi234S sigi234

        @fastfoot

        Cool, auch unter Windows lauffähig?

        F Offline
        F Offline
        fastfoot
        schrieb am zuletzt editiert von
        #3

        @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

        iobroker läuft unter Docker auf QNAP TS-451+
        SkriptRecovery: https://forum.iobroker.net/post/930558

        sigi234S 1 Antwort Letzte Antwort
        1
        • F fastfoot

          @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

          sigi234S Offline
          sigi234S Offline
          sigi234
          Forum Testing Most Active
          schrieb am zuletzt editiert von sigi234
          #4

          @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?

          Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat.
          Immer Daten sichern!

          F 1 Antwort Letzte Antwort
          0
          • liv-in-skyL Offline
            liv-in-skyL Offline
            liv-in-sky
            schrieb am zuletzt editiert von
            #5

            @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 ?

            nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

            F 1 Antwort Letzte Antwort
            0
            • sigi234S 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 Offline
              F Offline
              fastfoot
              schrieb am zuletzt editiert von
              #6

              @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

              iobroker läuft unter Docker auf QNAP TS-451+
              SkriptRecovery: https://forum.iobroker.net/post/930558

              1 Antwort Letzte Antwort
              1
              • liv-in-skyL liv-in-sky

                @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 Offline
                F Offline
                fastfoot
                schrieb am zuletzt editiert von
                #7

                @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)

                iobroker läuft unter Docker auf QNAP TS-451+
                SkriptRecovery: https://forum.iobroker.net/post/930558

                liv-in-skyL 2 Antworten Letzte Antwort
                0
                • F fastfoot

                  @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-skyL Offline
                  liv-in-skyL Offline
                  liv-in-sky
                  schrieb am zuletzt editiert von
                  #8

                  @fastfoot

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

                  nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                  1 Antwort Letzte Antwort
                  1
                  • F fastfoot

                    @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-skyL Offline
                    liv-in-skyL Offline
                    liv-in-sky
                    schrieb am zuletzt editiert von
                    #9

                    @fastfoot

                    könnte sowas auch gut für die vis gebrauchen :-)

                    nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                    H 1 Antwort Letzte Antwort
                    0
                    • liv-in-skyL liv-in-sky

                      @fastfoot

                      könnte sowas auch gut für die vis gebrauchen :-)

                      H Offline
                      H Offline
                      homecineplexx
                      schrieb am zuletzt editiert von
                      #10

                      sagt, muss diese Datei

                      /home/iobroker/scriptInput
                      

                      vorhanden sein?

                      liv-in-skyL F 2 Antworten Letzte Antwort
                      0
                      • H homecineplexx

                        sagt, muss diese Datei

                        /home/iobroker/scriptInput
                        

                        vorhanden sein?

                        liv-in-skyL Offline
                        liv-in-skyL Offline
                        liv-in-sky
                        schrieb am zuletzt editiert von liv-in-sky
                        #11

                        @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';
                        
                        

                        nach einem gelösten Thread wäre es sinnvoll dies in der Überschrift des ersten Posts einzutragen [gelöst]-... Bitte benutzt das Voting rechts unten im Beitrag wenn er euch geholfen hat. Forum-Tools: PicPick https://picpick.app/en/download/ und ScreenToGif https://www.screentogif.com/downloads.html

                        1 Antwort Letzte Antwort
                        0
                        • H homecineplexx

                          sagt, muss diese Datei

                          /home/iobroker/scriptInput
                          

                          vorhanden sein?

                          F Offline
                          F Offline
                          fastfoot
                          schrieb am zuletzt editiert von
                          #12

                          @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

                          iobroker läuft unter Docker auf QNAP TS-451+
                          SkriptRecovery: https://forum.iobroker.net/post/930558

                          1 Antwort Letzte Antwort
                          0
                          • sigi234S sigi234

                            @fastfoot

                            Cool, auch unter Windows lauffähig?

                            F Offline
                            F Offline
                            fastfoot
                            schrieb am zuletzt editiert von
                            #13

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

                            @fastfoot

                            Cool, auch unter Windows lauffähig?

                            probier mal :-)

                            iobroker läuft unter Docker auf QNAP TS-451+
                            SkriptRecovery: https://forum.iobroker.net/post/930558

                            1 Antwort Letzte Antwort
                            0
                            • F Offline
                              F Offline
                              fastfoot
                              schrieb am zuletzt editiert von
                              #14

                              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

                              iobroker läuft unter Docker auf QNAP TS-451+
                              SkriptRecovery: https://forum.iobroker.net/post/930558

                              H 1 Antwort Letzte Antwort
                              0
                              • F fastfoot

                                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 Offline
                                H Offline
                                homecineplexx
                                schrieb am zuletzt editiert von
                                #15

                                @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 Antwort Letzte Antwort
                                0
                                • H homecineplexx

                                  @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 Offline
                                  F Offline
                                  fastfoot
                                  schrieb am zuletzt editiert von
                                  #16

                                  @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

                                  iobroker läuft unter Docker auf QNAP TS-451+
                                  SkriptRecovery: https://forum.iobroker.net/post/930558

                                  1 Antwort Letzte Antwort
                                  1
                                  • F 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!');
                                    })
                                    

                                    S Offline
                                    S Offline
                                    sruhsam
                                    schrieb am zuletzt editiert von
                                    #17

                                    @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 Antwort Letzte Antwort
                                    0
                                    • F 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!');
                                      })
                                      

                                      R Offline
                                      R Offline
                                      Ralf 6
                                      schrieb am zuletzt editiert von
                                      #18

                                      @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:

                                      1 Antwort Letzte Antwort
                                      0
                                      Antworten
                                      • In einem neuen Thema antworten
                                      Anmelden zum Antworten
                                      • Älteste zuerst
                                      • Neuste zuerst
                                      • Meiste Stimmen


                                      Support us

                                      ioBroker
                                      Community Adapters
                                      Donate

                                      411

                                      Online

                                      32.5k

                                      Benutzer

                                      81.7k

                                      Themen

                                      1.3m

                                      Beiträge
                                      Community
                                      Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen | Einwilligungseinstellungen
                                      ioBroker Community 2014-2025
                                      logo
                                      • Anmelden

                                      • Du hast noch kein Konto? Registrieren

                                      • Anmelden oder registrieren, um zu suchen
                                      • Erster Beitrag
                                        Letzter Beitrag
                                      0
                                      • Home
                                      • Aktuell
                                      • Tags
                                      • Ungelesen 0
                                      • Kategorien
                                      • Unreplied
                                      • Beliebt
                                      • GitHub
                                      • Docu
                                      • Hilfe