How to use adb.rimraf method in Appium Android Driver

Best JavaScript code snippet using appium-android-driver

build-tweaks.js

Source:build-tweaks.js Github

copy

Full Screen

1/* ************************************************************************** *\2|** ************************************************************************ **|3|** MZD-AIO-TI                                                               **|4|** By: Trezdog44 - Trevor Martin                                            **|5|** http://mazdatweaks.com                                                   **|6|** ©2020 Trevelopment                                                       **|7|**                                                                          **|8|** build-tweaks.js - The main 'builder' component copys neccesary files to  **|9|** a temporary folder for copying to a usb additionaly                      **|10|** gives the option to copy files directly to an available usb drive.       **|11|**                                                                          **|12|** ************************************************************************ **|13\* ************************************************************************** */14/* jshint esversion:8, -W033, -W117, -W097 */15// First line of AIO log16var AIO_LOG = `# __MZD-AIO-TI__ ${app.getVersion()}| MZD All In One Tweaks Installer\n#### AIO COMPILATION LOG - ${Date()}\r\n___\n- *START!*\n`17var AIO_LOG_HTML = `<button class="w3-btn w3-hover-teal w3-display-bottomright w3-margin" onclick="saveAIOLogHTML()">Save Log (HTML)</button><div id="aio-comp-log" class="aio-comp-log"><h1><b>MZD-AIO-TI ${app.getVersion()}</b> | MZD All In One Tweaks Installer</h1><br><h4> AIO COMPILATION LOG - ${Date()}</h4><hr><div><ul><li><b><i>START!</i></b></li>`18var userView = document.getElementById(`userLogView`)19var fileCount = 0 // Number of files in the Queue20var opsComplete = false // Flag to signal writing of tweaks.sh file is completed21var filesComplete = true // Flag to signal the files have all been copied22var errFlag = false // Error flag23var copySwapfile = false // Swapfile flag24var tweaks2write = [] // Queue for order consistantcy writing tweaks.sh (Always starts with 00_intro.txt)25var tmpdir = path.normalize(path.join(persistantData.get('copyFolderLocation', app.getPath('desktop')), '_copy_to_usb')) // Place to hold USB drive files before copying26var themeColor = 'Red' // Default color27var tweaksFileName = 'tweaks' // Filename for tweaks.sh28var userOps = null29var swapdest = ''30var keeplog = true31/*                                      *********\32|*  START BUILD OF TWEAKS.SH & ASSOCIATED FILES *|33\**********                                     */34function buildTweakFile (user, apps) {35  userOps = user36  keeplog = !user.autorun.serial37  /* Set _copy_to_usb folder location */38  tmpdir = path.normalize(path.join(persistantData.get('copyFolderLocation', app.getPath('desktop')), '_copy_to_usb'))39  /* Start building tweaks.sh */40  tweaks2write = [`${builddir}00_intro.txt`]41  /* * Add Variables * */42  tweakVariables(user)43  tweaks2write.push(`${builddir}00_start.txt`)44  /* Start Writing Log Files */45  AIO_LOG += `- Tweak Files Location: ${tmpdir}\r\n`46  AIO_LOG_HTML += `<li><b>Tweak Files Location: ${tmpdir}</b></li>`47  /* Building Dialog */48  bootbox.dialog({49    message: `<div style='text-align:center;'>${langObj.popupMsgs[0].msg}<br><div id='userLogView' style='text-align:center;' ></div><br><img class='loader' src='./files/img/load-1.gif' alt='...' /></div><div id='copy-loc'>${langObj.popupMsgs[1].msg}: ${tmpdir.replace(/\\/g, '/')}<span class="w3-close icon-x w3-right" onclick="$(this).parent().hide()"></span></div>`,50    closeButton: false51  })52  saveInstallerOps(user)53  if (fs.existsSync(`${tmpdir}`)) {54    aioLog('Delete old _copy_to_usb folder...')55  }56  // delete tmp folder if it exists and make new tmpdir57  rimraf(`${tmpdir}`, (err) => {58    if (err) {59      let m = `Error occured while deleting old '_copy_to_usb' folder: ${err}\n Try closing all other running programs and folders before compiling.`60      aioLog(m, m)61      return62    }63    mkdirp(`${tmpdir}`, (err) => {64      if (err) {65        aioLog(err, err)66        return67      }68      buildTweaksConfig(user, apps)69    })70  })71}72function buildTweaksConfig (user, apps) {73  setTimeout(() => {74    /* Autorun Script Installer */75    if (user.autorun.installer && !user.restore.full) {76      buildAutorunInstaller(user)77      return78    }79    try {80      mkdirp.sync(`${tmpdir}/config/`)81    } catch (e) {82      var m = `${e} - Error occured while creating '_copy_to_usb' folder. Try closing all other running programs and folders before compiling.`83      aioLog(e.message, m)84      return85    }86    if (user.runsh) {87      tweaksFileName = 'run'88    }89    /* Full System Restore Script */90    if (user.restore.full) {91      fullSystemRestore(user)92      return93    }94    /* CASDK Installer */95    if (user.casdk.inst || user.casdk.uninst) {96      if (apps) {97        buildCASDK(user, apps)98        rimraf.sync(`${tmpdir}/config/`)99        rimraf.sync(`${tmpdir}/config_org/`)100        return101      }102    }103    // first back up JCI folder if chosen104    if (user.mainOps.includes(1)) {105      addTweak('00_backup.txt')106    }107    if (user.mainOps.includes(0) || user.options.includes(21)) {108      addTweak('00_wifi.txt')109    }110    if (user.mainOps.includes(4) || user.options.includes(21)) {111      addTweak('00_sshbringback.txt')112    }113    if (user.options.includes(16)) {114      mkdirp.sync(`${tmpdir}/config/blank-album-art-frame/jci/gui/common/images/`)115      var inStr = fs.createReadStream(`${varDir}/no_artwork_icon.png`)116      inStr.on('error', function (err) {117        aioLog('ERROR: NO BLANK ALBUM ART CHOSEN')118        ipc.send('default-blnk-art')119        setTimeout(() => {120          var inStr2 = fs.createReadStream(`${varDir}/no_artwork_icon.png`)121          inStr2.on('error', function (err) {122            console.error(err.toString())123            aioLog(err, 'Error: Missing Blank Album Art')124          })125          inStr2.on('open', function () {126            addBlankAlbumArt(user, this)127          })128          inStr2.on('close', function () {129            aioLog('Missing Blank Album Art... Using Default')130            checkForColorScheme(user)131          })132        }, 3000)133      })134      inStr.on('open', function () {135        addBlankAlbumArt(user, this)136      })137      inStr.on('close', function () {138        aioLog('Blank Album Art Copy Successful!')139        checkForColorScheme(user)140      })141    } else {142      checkForColorScheme(user)143    }144  }, 1000)145}146function addBlankAlbumArt (user, inStr) {147  var outStr = fs.createWriteStream(`${tmpdir}/config/blank-album-art-frame/jci/gui/common/images/no_artwork_icon.png`)148  outStr.on('open', () => {149    // addTweakDir('blank-album-art-frame', true)150  })151  outStr.on('close', () => {152    // aioLog('Blank Album Art Copy Successful!')153  })154  outStr.on('error', (err) => {155    aioLog(err, 'Blank Album Art Copy FAILED!')156  })157  inStr.pipe(outStr)158}159/* Check For Color Scheme Tweak */160function checkForColorScheme (user) {161  if (user.mainOps.includes(3)) {162    if (user.colors > 16) {163      customTheme(themeColor, user)164    } else if (user.colors < 8 || user.colors === 11) { // 11 for CarOS theme165      setColor(themeColor, user)166    } else {167      setTheme(themeColor, user)168    }169  } else {170    buildTweak(user)171  }172}173function customTheme (color, user) {174  if (user.customTheme) {175    if (user.customTheme[0].substr(user.customTheme.length - 4) === 'jci') {176      aioLog(`Copying ${user.customTheme} Theme Folder`)177      copydir(`${user.customTheme}`, `${tmpdir}/config/color-schemes/theme/jci/`, function (stat, filepath, filename) {178        if (stat === 'file' && path.extname(filepath) !== '.png') {179          return false180        }181        return true182      }, (err) => {183        if (err) { aioLog(err, err) } else { aioLog(`Custom Theme Copied Successfully.`) }184        buildTweak(user)185      })186    } else {187      aioLog(`ERROR: INVALID THEME FOLDER`, `ERROR: INVALID THEME FOLDER: ${user.customTheme[0].substr(user.customTheme.length - 4)}   Please Select a 'jci' Folder To Use Custom Theme`)188    }189  } else {190    aioLog(`Custom theme not found, Copy the jci folder from a MZD Theme Package to '/config/color-schemes/theme/' To Use Your Theme`)191    mkdirp.sync(`${tmpdir}/config/color-schemes/theme/jci/`)192    buildTweak(user)193  }194}195function setTheme (color, user) {196  aioLog(`Unzipping ${color} Theme Folder`)197  extract(`${builddir}/config/themes/${color}.zip`, { dir: `${tmpdir}/config/color-schemes/theme/` }, (err) => {198    if (err) { aioLog(err, err) }199    aioLog(`${color} Theme Folder Unzipped & Added.`)200    if (!user.useColorBG) {201      if (fs.existsSync(`${tmpdir}/config/color-schemes/theme/jci/gui/common/images/background.png`)) {202        fs.unlinkSync(`${tmpdir}/config/color-schemes/theme/jci/gui/common/images/background.png`)203      }204      aioLog('Removed Theme Background')205    }206    if (fs.existsSync(`${tmpdir}/config/color-schemes/theme/jci/gui/common/images/no_artwork_icon.png`)) {207      fs.unlinkSync(`${tmpdir}/config/color-schemes/theme/jci/gui/common/images/no_artwork_icon.png`)208    }209    if (fs.existsSync(`${tmpdir}/config/color-schemes/theme/jci/gui/apps/system/controls/OffScreen/images/OffScreenBackground.png`)) {210      fs.unlinkSync(`${tmpdir}/config/color-schemes/theme/jci/gui/apps/system/controls/OffScreen/images/OffScreenBackground.png`)211    }212    buildTweak(user)213  })214}215function setColor (color, user) {216  if (!fs.existsSync(`${tmpdir}/config/color-schemes`)) {217    mkdirp.sync(`${tmpdir}/config/color-schemes`)218  }219  aioLog(`Unzipping ${color} color theme folder`)220  extract(`${colordir}/${color}/jci.zip`, { dir: `${tmpdir}/config/color-schemes/${color}` }, (err) => {221    if (err) { aioLog(err, err) }222    aioLog(`${color} Color Scheme Folder Unzipped... Continue Build.`)223    buildTweak(user)224    if (user.colors === 1) {225      fs.createReadStream(`${colordir}/Blue/_skin_jci_bluedemo.zip`).pipe(fs.createWriteStream(`${tmpdir}/config/color-schemes/Blue/_skin_jci_bluedemo.zip`))226      aioLog(`Copying Blue Color Scheme For Navigation`)227    }228    if (!user.useColorBG) {229      if (fs.existsSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/common/images/background.png`)) {230        fs.unlinkSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/common/images/background.png`)231      }232      aioLog('Removed Color Scheme Background')233    }234    if (fs.existsSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/apps/system/controls/OffScreen/images/OffScreenBackground.png`)) {235      fs.unlinkSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/apps/system/controls/OffScreen/images/OffScreenBackground.png`)236    }237    if (fs.existsSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/common/images/no_artwork_icon.png`)) {238      fs.unlinkSync(`${tmpdir}/config/color-schemes/${color}/jci/gui/common/images/no_artwork_icon.png`)239    }240  })241}242function buildTweak (user) {243  // ****************************************************/244  // **********Write uninstalls first********************/245  // ****************************************************/246  if (user.options.includes(101)) {247    addTweak('01_touchscreen-u.txt')248  }249  if (user.options.includes(102)) {250    addTweak('02_disclaimer-u.txt')251  }252  if (user.options.includes(103)) {253    addTweak('03_warning-u.txt')254    addTweakDir('safety-warning-reverse-camera', false)255  }256  if (user.options.includes(104)) {257    addTweak('04_sensor-u.txt')258    addTweakDir('transparent-parking-sensor', false)259  }260  if (user.options.includes(105)) {261    addTweak('05_mainloop-u.txt')262  }263  if (user.options.includes(106)) {264    addTweak('06_listloop-u.txt')265  }266  if (user.options.includes(107)) {267    addTweak('07_shorterdelay-u.txt')268  }269  if (user.options.includes(108)) {270    addTweak('08_sysbeep-u.txt')271  }272  if (user.options.includes(109)) {273    addTweak('09_audioorder-u.txt')274  }275  if (user.options.includes(110)) {276    addTweak('10_pausemute-u.txt')277  }278  if (user.options.includes(111)) {279    addTweak('11_msgreplies-u.txt')280  }281  if (user.options.includes(112)) {282    addTweak('12_diag-u.txt')283  }284  if (user.options.includes(113)) {285    addTweak('13_boot-u.txt')286    addTweakDir('bootanimation', false)287  }288  if (user.options.includes(114)) {289    addTweak('14_bgart-u.txt')290    addTweakDir('bigger-album-art', false)291  }292  if (user.options.includes(115)) {293    addTweak('15_btnbackground-u.txt')294    addTweakDir('NoButtons', false)295  }296  if (user.options.includes(116)) {297    addTweak('16_blnkframe-u.txt')298    addTweakDir('blank-album-art-frame', false)299  }300  if (user.options.includes(118)) {301    addTweak('18_swapfile-u.txt')302  }303  if (user.options.includes(122)) {304    addTweak('22_fuel-u.txt')305    addTweakDir('FuelConsumptionTweak', false)306  }307  if (user.options.includes(121)) {308    addTweak('08_orderflac-u.txt')309    addTweakDir('media-order-patching', false)310  }311  if (user.options.includes(126)) {312    addTweak('26_usbaudiomod-u.txt')313    addTweakDir('USBAudioMod', false)314  }315  if (user.mainOps.includes(106)) {316    addTweak('00_bgrotator-u.txt')317    addTweakDir('BackgroundRotator', false)318  }319  if (user.options.includes(124)) {320    addTweak('24_castscreen-u.txt')321  }322  if (user.options.includes(117)) {323    addTweak('17_videoplayer-u.txt')324  }325  if (user.options.includes(119)) {326    addTweak('19_speedo-u.txt')327  }328  if (user.options.includes(125)) {329    addTweak('25_androidauto-u.txt')330  }331  if (user.options.includes(127)) {332    addTweak('27_aioapp-u.txt')333  }334  if (user.mzdmeter.uninst) {335    addTweak('28_mzdmeter-u.txt')336  }337  // ****************************************************/338  // ******************Write Installs********************/339  // ****************************************************/340  if (user.mainOps.includes(3)) {341    if (user.colors === 0) {342      addTweak('21_colors-u.txt')343    } else if (user.colors < 8 || user.colors === 11) {344      addTweak('21_colors-i.txt')345    } else {346      addTweak('21_theme-i.txt')347    }348  }349  if (user.options.includes(1)) {350    addTweak('01_touchscreen-i.txt')351  }352  if (user.options.includes(2)) {353    addTweak('02_disclaimer-i.txt')354  }355  if (user.options.includes(3)) {356    addTweak('03_warning-i.txt')357    addTweakDir('safety-warning-reverse-camera', true)358  }359  if (user.options.includes(4)) {360    addTweak('04_sensor-i.txt')361    addTweakDir('transparent-parking-sensor', true)362  }363  if (user.options.includes(5)) {364    addTweak('05_mainloop-i.txt')365    addTweakDir('main-menu-loop', true)366  }367  if (user.options.includes(6)) {368    addTweak('06_listloop-i.txt')369    addTweakDir('list-loop', true)370  }371  if (user.options.includes(7)) {372    addTweak('07_shorterdelay-i.txt')373  }374  if (user.listbeep) {375    addTweak('07_listbeep-i.txt')376  }377  if (user.options.includes(8)) {378    addTweak('08_sysbeep-i.txt')379  }380  if (user.options.includes(9)) {381    addTweak('09_audioorder-i.txt')382  }383  if (user.options.includes(10)) {384    addTweak('10_pausemute-i.txt')385  }386  if (user.options.includes(19)) {387    addTweak('19_speedo-i1.txt', true)388    switch (user.speedoOps.lang.id) {389      case 1:390        break391      case 2:392        addTweak('19_speedo-spanish.txt', true)393        break394      case 3:395        addTweak('19_speedo-polish.txt', true)396        break397      case 4:398        addTweak('19_speedo-slovic.txt', true)399        break400      case 5:401        addTweak('19_speedo-turkish.txt', true)402        break403      case 6:404        addTweak('19_speedo-french.txt', true)405        break406      case 7:407        addTweak('19_speedo-italian.txt', true)408        break409      case 8:410        addTweak('19_speedo-dutch.txt', true)411        break412      default:413        addTweak('19_speedo-english.txt', true)414    }415    if (user.speedoOps.xph.id === 10) {416      addTweak('19_speedo-mph.txt', true)417    }418    if (user.speedoOps.effic.id === 40) {419      addTweak('19_speedo-kml.txt', true)420    }421    if (user.speedoOps.classicLargeText) {422      addTweak('19_speedo-lrgtxt.txt', true)423    }424    if (user.speedoOps.temperature.id === 43) {425      addTweak('19_speedo-temp.txt', true)426    }427    if (user.speedoOps.modAlt) {428      addTweak('19_speedo-analog.txt', true)429    }430    if (user.speedoOps.simpmod) {431      addTweak('19_speedo_bar.txt', true)432    }433    if (user.speedoOps.bg.id === 30) {434      addTweak('19_speedo-own_background.txt', true)435    } else if (user.speedoOps.bg.id === 31) {436      addTweak('19_speedo-old_background.txt', true)437    }438    if (user.speedoOps.sml.id === 22) {439      addTweak('19_speedo-small_speedo_off.txt', true)440    } else {441      if (user.speedoOps.sbmain !== undefined) {442        addTweak('19_set_sb_values.txt', true)443      }444      if (user.speedoOps.sbfuel !== 'disable') {445        addTweak('19_sbfuelbar.txt', true)446      }447      if (user.speedoOps.digiclock) {448        addTweak('19_speedo-digiclock.txt', true)449      }450      if (user.speedoOps.sbreverse) {451        addTweak('19_speedo-sbhiderev.txt', true)452      }453      if (!user.speedoOps.sbhideinapp) {454        addTweak('19_speedo-sbdonthide.txt', true)455      }456    }457    addTweak('19_speedo-i2.txt', true)458    addTweakDir('speedometer', true)459    writeSpeedoConfigFile(user)460  }461  if (user.options.includes(21)) {462    addTweak('08_orderflac-i.txt')463    addTweakDir('media-order-patching', true)464  }465  if (user.options.includes(24)) {466    addTweak('24_castscreen-i.txt')467    addTweakDir('castscreen-receiver', true)468  }469  if (user.options.includes(11)) {470    addTweak('11_msgreplies-i.txt')471    copyPresetMessageFile()472  }473  if (user.options.includes(13)) {474    addTweak('13_boot-i.txt')475    addTweakDir('bootanimation', true)476  }477  if (user.options.includes(26)) {478    addTweak('26_usbaudiomod-i.txt') // USB Audio Mod Install comes before Bigger Album Art479    addTweakDir('USBAudioMod', true)480  }481  if (user.options.includes(14)) {482    addTweak('14_bgart-i.txt')483    addTweakDir('bigger-album-art', true)484  }485  if (user.options.includes(15)) {486    addTweak('15_btnbackground-i.txt')487    addTweakDir('NoButtons', true)488  }489  if (user.options.includes(16)) {490    addTweakDir('blank-album-art-frame', true)491  }492  if (user.options.includes(17)) {493    addTweak('17_videoplayer-i.txt')494    addTweakDir('videoplayer', true)495  }496  if (user.options.includes(27)) {497    addTweak('27_aioapp-i.txt')498    if (user.screenOffBoot) {499      addTweak('27_aioapp-screenoff.txt')500    }501    addTweakDir('aio-app', true)502  }503  if (user.options.includes(27) || user.options.includes(17)) {504    addTweak('00_storage-i.txt', true)505  }506  if (user.mzdmeter.inst) {507    addTweak('28_mzdmeter-i.txt')508    addTweakDir('mzdmeter', true)509  }510  if (user.options.includes(22)) {511    addTweak('22_fuel-i.txt')512    addTweakDir('FuelConsumptionTweak', true)513  }514  if (user.options.includes(25)) {515    if (user.aaHUD) {516      addTweakDir('androidauto', true, replaceInFile, `${tmpdir}/config/androidauto/data_persist/dev/bin/headunit-wrapper`, `DEBUG=0`, `DEBUG=1`)517    } else {518      addTweakDir('androidauto', true)519    }520    addTweak('25_androidauto-i.txt')521    if (user.aaCarGPS) {522      addTweak('25_androidautocargps.txt')523    } else if (user.aaBetaVer) {524      addTweak('25_androidautorevgps.txt')525    }526    if (user.aaWifi) {527      if (user.aaHUD) {528        addTweakDir('androidautowifi', true, replaceInFile, `${tmpdir}/config/androidautowifi/headunit-wrapper`, `DEBUG=0`, `DEBUG=1`)529      } else {530        addTweakDir('androidautowifi', true)531      }532      addTweak('25_androidautowifi-i.txt')533    }534  }535  if (user.mainOps.includes(4) || user.options.includes(21)) {536    addTweakDir('ssh_bringback', true)537  }538  // disclaimer & order of audio source list539  if (user.options.includes(2) || user.options.includes(9) || user.options.includes(102) || user.options.includes(109)) {540    addTweakDir('audio_order_AND_no_More_Disclaimer', true)541    buildEntList(user)542  }543  // Statusbar Tweaks544  if (user.options.includes(120)) {545    addTweak('20_date-u.txt')546    addTweakDir('date-to-statusbar_mod', false)547  } else if (user.options.includes(20)) {548    if (user.statusbar.d2sbuninst) {549      addTweak('20_date2status-u.txt')550      addTweakDir('date-to-statusbar_mod', false)551    } else if (user.statusbar.d2sbinst) {552      if (user.d2sbOps === 0) {553        addTweak('20_date-iv1.txt')554      } else {555        addTweak('20_date-iv3.3.txt')556      }557      addTweakDir('date-to-statusbar_mod', true)558    }559    if (user.statusbar.uninst) {560      addTweak('20_statusbar_tweaks-u.txt')561    } else {562      addTweak('20_statusbar_tweaks-i.txt')563    }564  }565  if (user.uistyle.uninst) {566    addTweak('20_uistyle-u.txt')567  } else if (user.mainOps.includes(9)) {568    addTweak('20_uistyle-i.txt')569  }570  if (user.uistyle.uninstmain) {571    addTweak('20_mainmenu-u.txt')572  } else if (user.mainOps.includes(8)) {573    addTweak('20_mainmenu-i.txt')574    addTweakDir('MainMenuTweaks', true)575  }576  if (user.options.includes(16)) {577    addTweak('16_blnkframe-i.txt')578  }579  if (user.options.includes(12)) {580    addTweak('12_diag-i.txt')581    addTweakDir('test_mode', true)582  }583  // Off Screen Background584  if (user.mainOps.includes(10) || user.mainOps.includes(110)) {585    var offBG = user.mainOps.includes(10) ? `${varDir}/OffScreenBackground.png` : path.resolve(approot, '../background-images/default/OffScreenBackground.png')586    var inStrOff = fs.createReadStream(offBG)587    inStrOff.on('error', (err) => {588      aioLog('ERROR: No Off-Screen Background Chosen... ', err)589    })590    inStrOff.on('open', () => {591      addTweak(`00_offbackground-${user.mainOps.includes(10) ? 'i' : 'u'}.txt`)592      var outOff = fs.createWriteStream(`${tmpdir}/config/OffScreenBackground.png`, { flags: 'w' })593      outOff.on('close', () => {594        aioLog('Off Screen Background Copy Successful!')595      })596      outOff.on('error', (err) => {597        aioLog('ERROR: Copy Off Screen Background Failed!', err)598      })599      inStrOff.pipe(outOff)600    })601  }602  // Add chosen background603  if (user.mainOps.includes(2)) {604    var inStrbg = fs.createReadStream(`${getBackground}`)605    inStrbg.on('error', (err) => {606      aioLog('ERROR: No Background Chosen...', err)607    })608    inStrbg.on('open', () => {609      var out = fs.createWriteStream(`${tmpdir}/config/background.png`, { flags: 'w' })610      out.on('close', () => {611        aioLog('Background Copy Successful!')612      })613      out.on('error', (err) => {614        aioLog('Background Copy Failed!', err)615      })616      inStrbg.pipe(out)617    })618    if (user.mainOps.includes(6)) {619      addTweak('00_bgrotator-i.txt')620    }621    addTweak('00_background.txt')622  }623  if (user.mainOps.includes(5)) {624    addTweak('00_sd-cid.txt')625    addTweakDir('get_sd_cid', true)626  }627  /* if (user.multictrlbtns) {628    addTweak('00_multicontroller-i.txt')629    addTweakDir('multicontroller', true)630  } */631  if (user.options.includes(19) || user.options.includes(17) || user.options.includes(25) || user.options.includes(27) || user.options.includes(28) || user.options.includes(119) || user.options.includes(117) || user.options.includes(125) || user.options.includes(127) || user.options.includes(128)) {632    addTweakDir('bin', true)633    if (user.options.includes(19) || user.options.includes(17) || user.options.includes(25) || user.options.includes(27) || user.options.includes(28)) {634      addTweakDir('jci', true)635      if (!user.options.includes(2) && !user.options.includes(9)) {636        addTweak('00_59patch.txt')637      }638    }639  }640  if (user.options.some((x) => { return x > 100 })) {641    twkdir = '/config_org/'642    mkdirp.sync(`${tmpdir}${twkdir}`)643    if (!fs.existsSync(`${tmpdir}${twkdir}/v70`)) {644      mkdirp.sync(`${tmpdir}${twkdir}/v70`)645      copydir(`${builddir}${twkdir}/v70`, `${tmpdir}${twkdir}/v70`, (err) => {646        (err) ? aioLog(`File Copy Error:`, `${err}`) : aioLog(`Copied v70 Fallback Files`)647      })648    }649  }650  // Swapfile tweak has to be last651  if (user.options.includes(18)) {652    copySwapfile = true653    if (user.swapOps.mount) {654      swapdest = '/config/swapfile/'655      addTweak('18_swapfile-i.txt')656    }657  }658  // Self Destruct mode so you dont need to remove the USB drive659  if (user.destruct || copySwapfile) {660    addTweak('99_self-destruct.txt')661  }662  // Add root files to tmp and write tweaks.sh663  addRootFiles(user.dataDump)664  setTimeout(() => {665    // Finish with the end script666    addTweak(user.options.includes(11) ? '00_factory-reset-end.txt' : '00_end.txt')667    writeTweaksFile()668  }, 2000)669}670// function to add each tweak to the array671function addTweak (twk) {672  tweaks2write.push(`${builddir}${twk}`)673  twk = twk.substr(3)674  twk = twk.replace('.txt', '')675  twk = twk.replace('-i', ' Install ')676  twk = twk.replace('-u', ' Uninstall ')677  twk = twk.charAt(0).toUpperCase() + twk.slice(1)678  aioLog(`${twk} added successfully.`)679}680function writeTweaksFile () {681  // write stream writes tweaks.txt682  var tweaks = fs.createWriteStream(`${tmpdir}/tweaks.txt`)683  // file appender function is given the array and piped to the write stream684  new appender(tweaks2write).pipe(tweaks)685  tweaks.on('close', convert2LF)686}687function langVar (id) {688  switch (id) {689    case 0: return 'EN'690    case 1: return 'DE'691    case 2: return 'PL'692    case 3: return 'SL'693    case 4: return 'EN'694    case 5: return 'TK'695    case 6: return 'FR'696    case 7: return 'IT'697    case 8: return 'NL'698    default: return 'EN'699  }700}701function writeSpeedoConfigFile (user) {702  mkdirp.sync(`${tmpdir}/config/speedometer/jci/gui/apps/_speedometer/js/`)703  /* TODO: GENERATE SPEEDOMETER STARTUP VARIABLES RATHER THAN CHANGING AT INSTALL TIME704  var spdStartup = `// speedometer-startup.js\n// Generated By AIO v${app.getVersion()}\n`705  spdStartup += `var enableSmallSbSpeedo = ${user.speedoOps.sml !== 22};\n`706  spdStartup += `var isMPH = ${user.speedoOps.xph == 11};\n`707  spdStartup += `var language = ''${langvar(user.speedoOps.language)}';\n`708  spdStartup += `var fuelEffunit_kml = ${user.speedoOps.fuelEffunit_kml};\n`709  spdStartup += `var black_background_opacity = ${user.speedoOps.black_background_opacity};\n`710  spdStartup += `var original_background_image = ${user.speedoOps.original_background_image};\n`711  spdStartup += `var startAnalog = ${user.speedoOps.startAnalog};\n`712  spdStartup += `var barSpeedometerMod = ${user.speedoOps.barSpeedometerMod};\n`713  spdStartup += `var speedMod = ${user.speedoOps.speedMod};\n`714  spdStartup += `var engineSpeedBar = ${user.speedoOps.engineSpeedBar};\n`715  spdStartup += `var hideSpeedBar = ${user.speedoOps.hideSpeedBar};\n`716  spdStartup += `var tempIsF = ${user.speedoOps.tempIsF};\n`717  spdStartup += `var speedAnimation = ${user.speedoOps.speedAnimation};\n`718  spdStartup += `var analogColor = ${user.speedoOps.analogColor};\n`719  spdStartup += `var speedometerTheme = ${user.speedoOps.speedometerTheme};\n`720  spdStartup += `var sbFuelBar = ${user.speedoOps.sbFuelBar};\n`721  spdStartup += `var sbfbPos = '${user.speedoOps.sbfbPos}';\n`722  spdStartup += `var SbMain = '${user.speedoOps.SbMain}';\n`723  spdStartup += `var SbVal1 = '${user.speedoOps.SbVal1}';\n`724  spdStartup += `var SbVal2 = '${user.speedoOps.SbVal2}';\n`725  fs.writeFileSync(`${varDir}/startupvars.js`, spdStartup)726  var config = fs.createWriteStream(`${tmpdir}/config/speedometer/jci/gui/apps/_speedometer/js/speedometer-startup.js`)727  new appender(speedoConfig).pipe(config)728  config.on('close', () => { console.log("speedometer-startup.js written successfully!") })729*/730  var JSobj = `var spdBottomRows = ${user.spdExtra.barSpeedoRows}; //Number of Bottom Rows\n`731  JSobj += 'var spdTbl = {\n'732  for (var val in user.spdValues) {733    if (`${user.spdValues[val].pos}` !== null) {734      JSobj += `\t${user.spdValues[val].elmnt}: [${user.spdValues[val].pos}], //${user.spdValues[val].label}\n`735    }736  }737  JSobj += '}\n'738  JSobj += 'var classicSpeedoTmplt = '739  JSobj += JSON.stringify(user.classicSpeed, null, '\t') + '\n'740  fs.writeFileSync(`${varDir}/spdConf.txt`, JSobj)741  var speedoConfig = []742  speedoConfig.push(`${builddir}/config/speedometer_config/config-start.js`)743  speedoConfig.push(`${varDir}/spdConf.txt`)744  speedoConfig.push(`${builddir}/config/speedometer_config/config-end.js`)745  var config = fs.createWriteStream(`${tmpdir}/config/speedometer/speedometer-config.js`)746  new appender(speedoConfig).pipe(config)747  config.on('close', () => {748    // console.log("speedometer-config.js written successfully!")749  })750  fs.writeFileSync(`${tmpdir}/config/speedometer/speedometer-controls.js`, `var spdBtn = ${JSON.stringify(user.multictrl, null, '\t')}`)751  for (var bt in user.barThemeColors) {752    var num = user.barThemeColors[bt].num753    barColorFile += `/* Theme #${num} */\n`754    barColorFile += `#speedBarContainer.theme${num} #vehdataMainDiv fieldset div, #speedBarContainer.theme${num} #vehdataMainDiv [class*="vehDataMain"].pos0 div {\n`755    barColorFile += `\tcolor: ${user.barThemeColors[bt].main};\n}\n`756    barColorFile += `#speedBarContainer.theme${num} #vehdataMainDiv [class*="vehDataMain"].pos0 legend .spunit span, #speedBarContainer.theme${num} #vehdataMainDiv fieldset {\n`757    barColorFile += `\tcolor: ${user.barThemeColors[bt].secondary};\n`758    barColorFile += `\tborder-color: ${user.barThemeColors[bt].border};\n}\n`759  }760  fs.writeFileSync(`${tmpdir}/config/speedometer/barThemes.css`, barColorFile)761}762function tweakVariables (user) {763  mkdirp.sync(`${varDir}`)764  var bak = `KEEPBKUPS=` + (user.backups.org ? `1\n` : `0\n`)765  bak += `TESTBKUPS=` + (user.backups.test ? `1\n` : `0\n`)766  bak += `SKIPCONFIRM=` + (user.backups.skipconfirm ? `1\n` : `0\n`)767  bak += `APPS2RESOURCES=` + (user.backups.apps2resources ? `1\n` : `0\n`)768  bak += (user.mainOps.includes(1) ? `ZIPBACKUP=` + (user.zipbackup ? `1\n` : `0\n`) : '')769  bak += (user.mainOps.includes(4) || user.options.includes(21) ? `FORCESSH=` + (user.forcessh ? `1\n` : `0\n`) : '')770  fs.writeFileSync(`${varDir}/backups.txt`, bak)771  tweaks2write.push(`${varDir}/backups.txt`)772  if (user.restore.full) {773    bak = `DEL_BAKUPS=`774    bak += (user.restore.delBackups) ? `1\n` : `0\n`775    fs.writeFileSync(`${varDir}/restore.txt`, bak)776    tweaks2write.push(`${varDir}/restore.txt`)777  }778  if (user.mainOps.includes(6)) {779    tweaks2write.push(`${varDir}/bg-rotator.txt`)780  }781  if (user.mainOps.includes(3)) {782    switch (user.colors) {783      case 0: themeColor = 'Red'; break784      case 1: themeColor = 'Blue'; break785      case 2: themeColor = 'Green'; break786      case 3: themeColor = 'Silver'; break787      case 4: themeColor = 'Pink'; break788      case 5: themeColor = 'Purple'; break789      case 6: themeColor = 'Orange'; break790      case 7: themeColor = 'Yellow'; break791      case 8: themeColor = 'SmoothRed'; break792      case 9: themeColor = 'SmoothAzure'; break793      case 10: themeColor = 'SmoothViolet'; break794      case 11: themeColor = 'carOS'; break795      case 12: themeColor = 'StormTroopers'; break796      case 13: themeColor = 'Poker'; break797      case 14: themeColor = 'Mazda'; break798      case 15: themeColor = 'Floating'; break799      case 16: themeColor = 'X-Men'; break800      case 17: themeColor = 'Custom'; break801      default: themeColor = 'Red'802    }803  }804  if (user.options.includes(13)) {805    var bootAnimations = `BOOTLOGO1=${user.boot.logo1}\n`806    bootAnimations += `BOOTLOGO2=${user.boot.logo2}\n`807    bootAnimations += `BOOTLOGO3=${user.boot.logo3}\n`808    fs.writeFileSync(`${varDir}/bootlogo.txt`, bootAnimations)809    tweaks2write.push(`${varDir}/bootlogo.txt`)810  }811  if (user.mainOps.includes(3)) {812    fs.writeFileSync(`${varDir}/color.txt`, `COLORTHEME=${themeColor}\n`)813    tweaks2write.push(`${varDir}/color.txt`)814  }815  if (user.options.includes(1)) {816    var tchscrn = `KEEP_SPEED_RESTRICT=`817    tchscrn += (user.keepSpeedRestrict) ? `1\n` : `0\n`818    tchscrn += `ENABLE_DVD=`819    tchscrn += (user.enableDVD) ? `1\n` : `0\n`820    fs.writeFileSync(`${varDir}/touchscreen.txt`, tchscrn)821    tweaks2write.push(`${varDir}/touchscreen.txt`)822  }823  if (user.mainOps.includes(8)) {824    var mmenu = `UI_STYLE_ELLIPSE=`825    mmenu += (user.uistyle.ellipse) ? `1\n` : `0\n`826    mmenu += `UI_STYLE_MINICOINS=`827    mmenu += (user.uistyle.minicoins) ? `1\n` : `0\n`828    mmenu += `UI_STYLE_MINIFOCUS=`829    mmenu += (user.uistyle.minifocus) ? `1\n` : `0\n`830    mmenu += `UI_STYLE_NOGLOW=`831    mmenu += (user.uistyle.hideglow) ? `1\n` : `0\n`832    mmenu += `UI_STYLE_ALTLAYOUT=${user.uistyle.layout}\n`833    mmenu += `UI_STYLE_MAIN3D=${user.uistyle.mainlabel}\n`834    mmenu += `UI_STYLE_LABELCOLOR=${user.uistyle.labelcolor}\n`835    fs.writeFileSync(`${varDir}/mainmenu.txt`, mmenu)836    tweaks2write.push(`${varDir}/mainmenu.txt`)837  }838  if (user.mainOps.includes(9)) {839    var ui = `UI_STYLE_BODY=${user.uistyle.body}\n`840    ui += `UI_STYLE_LIST=${user.uistyle.listitem}\n`841    ui += `UI_STYLE_DISABLED=${user.uistyle.listitemdisabled}\n`842    ui += `UI_STYLE_TITLE=${user.uistyle.title}\n`843    ui += `UI_STYLE_RADIO=${user.uistyle.radio}\n`844    ui += `UI_STYLE_SHADOW=`845    ui += (user.uistyle.shadow) ? `"text-shadow: 2px 2px .5px #000;"\n` : `\n`846    fs.writeFileSync(`${varDir}/uistyle.txt`, ui)847    tweaks2write.push(`${varDir}/uistyle.txt`)848  }849  if (user.options.includes(14)) {850    var noalbmart = `NOALBM=`851    noalbmart += (user.uistyle.noalbm) ? `1\n` : `0\n`852    noalbmart += `FULLTITLES=`853    noalbmart += (user.uistyle.fulltitles) ? `1\n` : `0\n`854    fs.writeFileSync(`${varDir}/bgralbmart.txt`, noalbmart)855    tweaks2write.push(`${varDir}/bgralbmart.txt`)856  }857  if (user.options.includes(15)) {858    var transbg = `NO_BTN_BG=`859    transbg += (user.uistyle.nobtnbg) ? `1\n` : `0\n`860    transbg += `NO_NP_BG=`861    transbg += (user.uistyle.nonpbg) ? `1\n` : `0\n`862    transbg += `NO_LIST_BG=`863    transbg += (user.uistyle.nolistbg) ? `1\n` : `0\n`864    transbg += `NO_CALL_BG=`865    transbg += (user.uistyle.nocallbg) ? `1\n` : `0\n`866    transbg += `NO_TEXT_BG=`867    transbg += (user.uistyle.notextbg) ? `1\n` : `0\n`868    fs.writeFileSync(`${varDir}/removebgs.txt`, transbg)869    tweaks2write.push(`${varDir}/removebgs.txt`)870  }871  if (user.options.includes(20)) {872    var dateFormat = user.d2sbOps - 1873    var sc = `DATE_FORMAT=${dateFormat}\n`874    sc += `STATUS_BAR_APP=${user.statusbar.app}\n`875    sc += `STATUS_BAR_CLOCK=${user.statusbar.clock}\n`876    sc += `STATUS_BAR_NOTIF=${user.statusbar.notif}\n`877    sc += `STATUS_BAR_OPACITY=${user.statusbar.opacity}\n`878    sc += (user.statusbar.main) ? `STATUS_BAR_CTRL="background-image: none;"\nSBN_CTRL="background-image: none;"\n` : `STATUS_BAR_CTRL="background-image: url('../images/StatusBarBg.png');"\nSBN_CTRL=\n`879    fs.writeFileSync(`${varDir}/statusbar-color.txt`, sc)880    tweaks2write.push(`${varDir}/statusbar-color.txt`)881  }882  if (user.options.includes(22)) {883    fs.writeFileSync(`${varDir}/fuel-consumption.txt`, `FUEL_CONS_UNIT=${user.fuelOps}\n`)884    tweaks2write.push(`${varDir}/fuel-consumption.txt`)885  }886  if (user.options.includes(17)) {887    var vpops = `VP_SHUFFLE=${user.vpOps.shuffle}\n`888    vpops += `VP_REPEAT=${user.vpOps.repeat}\n`889    vpops += `VP_FULLSCRN=${user.vpOps.fullscreen}\n`890    vpops += `VP_V4LSINK=${user.vpOps.v4lsink}\n`891    fs.writeFileSync(`${varDir}/vpops.txt`, vpops)892    tweaks2write.push(`${varDir}/vpops.txt`)893  }894  if (user.options.includes(19)) {895    var sops = `OPACITY=`896    sops += (user.speedoOps.bg.id === 30) ? `${user.speedoOps.opac}\n` : `0\n`897    sops += `SPEEDCOLOR=`898    sops += (user.speedoOps.color !== null) ? `${user.speedoOps.color}\n` : `0\n`899    sops += `SPD_BAR_RPM=`900    sops += (user.spdExtra.engineSpeedBar) ? `1\n` : `0\n`901    sops += `SPD_BAR_HIDE=`902    sops += (user.spdExtra.hideSpeedBar) ? `1\n` : `0\n`903    sops += `SPD_COUNTER=`904    sops += (user.spdExtra.speedAnimation) ? `1\n` : `0\n`905    sops += `HIDE_SPEEDO_SBN=`906    sops += (user.spdExtra.hidespeedosbn) ? `1\n` : `0\n`907    sops += `SPD_XTRA_FUEL_SUFF=${user.spdExtra.fuelGaugeValueSuffix}\n`908    sops += `SPD_XTRA_FUEL_FACT=${user.spdExtra.fuelGaugeFactor}\n`909    sops += (user.speedoOps.sbmain !== undefined) ? `SBMAIN=${user.speedoOps.sbmain}\n` : `\n`910    sops += (user.speedoOps.sbval1 !== undefined) ? `SBVAL1=${user.speedoOps.sbval1}\n` : `\n`911    sops += (user.speedoOps.sbval2 !== undefined) ? `SBVAL2=${user.speedoOps.sbval2}\n` : `\n`912    sops += (user.speedoOps.sbfuel !== undefined) ? `SBFBPOS=${user.speedoOps.sbfuel}\n` : `\n`913    sops += `SBUNIT=speedUnit\n`914    sops += `BTSTART=${user.spdExtra.barThemeStart}\n`915    sops += `SBINT=${user.speedoOps.sbint * 1000}\n`916    for (var fb in user.fuelBarColors) {917      sops += `${user.fuelBarColors[fb].bashVar}="${user.fuelBarColors[fb].colorVal}"\n`918      // console.log(`${user.fuelBarColors[fb].bashVar}="${user.fuelBarColors[fb].colorVal}"`);919    }920    fs.writeFileSync(`${varDir}/bgopacity.txt`, sops)921    tweaks2write.push(`${varDir}/bgopacity.txt`)922  }923  if (user.options.includes(26)) {924    fs.writeFileSync(`${varDir}/gracenote.txt`, `GRACENOTE="${user.gracenoteText}"`)925    tweaks2write.push(`${varDir}/gracenote.txt`)926  }927}928function convert2LF () {929  /* For now the files are pre converted, but this needs to stay in just in case EOL format changes.*********** */930  crlf.set(`${tmpdir}/tweaks.txt`, 'LF', function (err, endingType) {931    if (err) {932      aioLog(err, 'LF Convert Error')933    } else if (endingType === 'NA') {934      aioLog(`LF Convert Error`, `EOL => ${endingType} (Format should be: LF)`)935    } else if (endingType === 'LF') {936      aioLog(`EOL => ${endingType}`)937    } else {938      aioLog(`LF Convert Error`, `EOL => ${endingType} (Format should be: LF)`)939    }940    // Rename tweaks.txt to tweaks.sh941    fs.renameSync(`${tmpdir}/tweaks.txt`, `${tmpdir}/${tweaksFileName}.sh`)942    aioLog(`Writing ${tweaksFileName}.sh`)943    if (`${tweaksFileName}` === 'run') {944      try {945        fs.unlinkSync(`${tmpdir}/jci-autoupdate`)946        fs.unlinkSync(`${tmpdir}/cmu_dataretrieval.up`)947        fs.unlinkSync(`${tmpdir}/dataRetrieval_config.txt`)948      } catch (e) {949        aioLog(`${e}`)950      }951    }952    opsComplete = true953    setTimeout(() => {954      if (filesComplete) {955        printAIOlog()956      }957    }, 5000)958  })959}960// Function for copying tweak folders961function addTweakDir (twk, inst, cback) {962  var cbackArgs = []963  for (var i = 0; i < arguments.length; i++) {964    if (i > 2) {965      cbackArgs.push(arguments[i])966    }967  }968  filesComplete = false969  aioLog(`Copying ${twk} files...`)970  fileCount++971  var twkdir = '/config/'972  if (!inst) {973    twkdir = '/config_org/'974    mkdirp.sync(`${tmpdir}${twkdir}`)975  }976  try {977    if (!fs.existsSync(`${tmpdir}${twkdir}${twk}`)) {978      mkdirp.sync(`${tmpdir}${twkdir}${twk}`)979    }980    // Above creates, below copies to tmp981    copydir(`${builddir}${twkdir}${twk}`, `${tmpdir}${twkdir}${twk}`, (err) => {982      if (err) {983        return aioLog(`File Copy Error: ${twk}-${err}`, `${err}-${twk}`)984      }985      aioLog(`Files for ${twk} copied successfully!`)986      if (typeof cback === 'function') {987        cback(cbackArgs[0] || null, cbackArgs[1] || null, cbackArgs[2] || null)988      }989      fileCount--990      if (fileCount === 0) {991        setTimeout(() => {992          if (fileCount === 0) {993            filesComplete = true994          }995          if (opsComplete) {996            printAIOlog()997          }998        }, 5000)999      }1000    })1001  } catch (e) {1002    aioLog(e, e)1003  }1004}1005// Function copys root files1006function addRootFiles (dataDump) {1007  try {1008    copydir(`${approot}/files/tweaks/root`, `${tmpdir}`, (err) => {1009      if (err) {1010        errFlag = true1011        aioLog('ERROR COPYING ROOT FILES', err)1012      } else {1013        if (dataDump) {1014          copydir(`${tmpdir}/data`, `${tmpdir}`, (err) => {1015            if (err) { errFlag = true } else {1016              rimraf.sync(`${tmpdir}/data`)1017              aioLog('Root files copied successfully!')1018            }1019          })1020        } else {1021          rimraf.sync(`${tmpdir}/data`)1022          aioLog('Root files copied successfully!')1023        }1024      }1025    })1026  } catch (e) {1027    aioLog(e, e)1028  }1029}1030function aioLog (logMsg, err) {1031  if (keeplog) {1032    AIO_LOG += `- ${logMsg}\n`1033  }1034  if (userView = document.getElementById(`userLogView`)) {1035    userView.innerHTML = logMsg1036  }1037  if (err) {1038    AIO_LOG_HTML += `<li style='font-weight:600;color:red'>${err}</li><li style='font-weight:600;color:red'>${logMsg}</li>\n`1039    $('#sidePanel').append(`<div id="AIO-ERR"><h4>${logMsg}</h4><small><strong>${err}</strong></small></div>`)1040    errFlag = true1041    printAIOlog()1042    // dialog.showErrorBox(err)1043  } else if (keeplog) {1044    AIO_LOG_HTML += `<li style='color:#004c00'> ${logMsg}</li>\n`1045  }1046}1047// Prints out the log1048function printAIOlog () {1049  if (filesComplete && opsComplete || errFlag) {1050    filesComplete = false1051    opsComplete = false1052    if (keeplog) {1053      fs.writeFile(`${tmpdir}/${logFileName}.md`, AIO_LOG, { flag: 'w' }, (err) => {1054        if (err) { console.log('AIO Could Not Be Saved') } else { console.log('AIO log saved!') }1055        fs.writeFile(path.resolve(path.join(`${approot}`, `../../${logFileName}.htm`)), AIO_LOG_HTML, { flag: 'w' }, (err) => {1056          if (err) { console.log('HTML Log Cannot Be Saved') } else { console.log('AIO log saved! (HTML version)') }1057          bootbox.hideAll()1058          if (!errFlag) {1059            usbDrives()1060          } else {1061            finishedMessage()1062          }1063        })1064      })1065    } else {1066      usbDrives()1067    }1068  }1069}1070function appendAIOlog (logMsg) {1071  if (keeplog) {1072    fs.writeFile(path.resolve(path.join(`${approot}`, `../../${logFileName}.htm`)), logMsg, { flag: 'a' }, (err) => {1073      if (err) {1074        console.warn(err)1075      }1076      fs.writeFile(path.resolve(path.join(`${tmpdir}`, `${logFileName}.md`)), `- ${String(logMsg).replace(/<[^>]+>/gm, '')}`, { flag: 'a' }, (err) => {1077        if (err) {1078          // do nothing1079          // console.warn(`Log File has been moved: ${err}`)1080        }1081      })1082    })1083  }1084}1085// Returns the available usb drives1086async function usbDrives () {1087  var dsklst = await drivelist.list()1088  var disks = []1089  var usbDriveLst = []1090  try {1091    dsklst.forEach((drive) => {1092      if (!drive.isSystem && drive.mountpoints && drive.mountpoints[0] && drive.mountpoints[0].path) {1093        disks.push({ 'desc': drive.description.replace(' USB Device', ''), 'mp': `${drive.mountpoints[0].path}` })1094        usbDriveLst.push({ 'text': `<span class='icon-usb'></span> ${drive.mountpoints[0].path.replace(/\\/g, '/')} ${drive.description.replace(' USB Device', '')}`, 'value': drive.mountpoints[0].path })1095      }1096    })1097    introJs().hideHints()1098    var usb = disks1099    var lst = ''1100    if (usb.length < 1) {1101      appendAIOlog(`<li style='color:#520086'>No USB Drives Found</li>`)1102      unzipSwapfile(null)1103    } else if (usb.length > 1) {1104      lst += `<h2><b>${usb.length} ${langObj.popupMsgs[6].msg}:</b></h2>`1105      var usbuttons = ''1106      for (var j = 0; j < usb.length; j++) {1107        var mpLoc = (process.platform === 'win32') ? `${usb[j].mp.replace(/\\/g, '')}` : `${usb[j].mp}`1108        lst += `<h4><strong>${mpLoc}</strong> ${usb[j].desc} `1109        lst += `<button class="w3-round w3-btn w3-ripple w3-hover-indigo w3-border w3-hover-border-pink w3-large" title='${langObj.popupMsgs[5].msg} ${mpLoc.replace(':', '')}' onclick="shell.openItem('${mpLoc}')"></span><span class="icon-usb2"></span> ${langObj.popupMsgs[5].msg} ${mpLoc.replace(':', '')}</button></h4>`1110        appendAIOlog(`<li style='color:#005182'>Found USB Drive #${j + 1} - ${mpLoc} ${usb[j].desc}</li>`)1111      }1112      lst += `<h5><b>${langObj.popupMsgs[8].msg}:</b></h5>${langObj.popupMsgs[2].msg}`1113      lst += usbuttons1114      lst += `<label class="delCopyMultiLabel w3-display-bottomleft"><input type="checkbox" class="w3-check" id="rmCpDirCheck">${langObj.popupMsgs[21].msg}</label>`1115      bootbox.prompt({1116        title: lst,1117        inputType: 'select',1118        inputOptions: usbDriveLst,1119        className: 'copytoUSBMulti',1120        buttons: {1121          confirm: {1122            label: `<span class='icon-usb'></span> ${langObj.popupMsgs[3].msg}`1123          },1124          cancel: {1125            label: `<span class='icon-x'></span> ${langObj.popupMsgs[4].msg}`1126          }1127        },1128        callback: function (result) {1129          if (!result) {1130            unzipSwapfile(null)1131          } else {1132            settings.set('delCopyFolder', $('#rmCpDirCheck').prop('checked'))1133            copyToUSB(result)1134          }1135        }1136      })1137      $('#rmCpDirCheck').prop('checked', settings.get('delCopyFolder', false))1138    } else if (usb.length === 1) {1139      lst = `<h2><b>${langObj.popupMsgs[6].msg}: </b></h2>`1140      for (var k = 0; k < usb.length; k++) {1141        lst += `<h4><b>${usb[k].mp.replace(/\\/g, '/')} ${usb[k].desc}</b></h4>`1142        appendAIOlog(`<li style='color:#005182'>USB Drive - ${usb[k].mp.replace(/\\/g, '/')} ${usb[k].desc}</li>`)1143      }1144      var mpLocation = (process.platform === 'win32') ? `${usb[0].mp.replace(/\\/g, '/')}` : `${usb[0].mp}`1145      lst += `<b>${langObj.popupMsgs[7].msg} ${mpLocation.replace(/[\/:]/g, '')}?</b><br>${langObj.popupMsgs[2].msg}`1146      lst += `<button class="w3-large w3-blue-grey w3-btn w3-ripple w3-hover-teal w3-border w3-border-orange w3-large w3-display-bottomleft" style="margin-bottom: -55px;margin-left: 10px;" title='${langObj.popupMsgs[5].msg}' onclick="shell.openItem('${mpLocation}')"></span><span class="icon-usb3"></span> ${langObj.popupMsgs[5].msg}</button>`1147      lst += `<label class="delCopyLabel w3-display-bottomright"><input type="checkbox" id="rmCpDirCheck" class="w3-check">${langObj.popupMsgs[21].msg}</label>`1148      bootbox.confirm({1149        title: `Copy files to USB drive?`,1150        message: lst,1151        className: 'copytoUSB1',1152        buttons: {1153          confirm: {1154            label: `<span class='icon-usb'></span> ${langObj.popupMsgs[3].msg}`1155          },1156          cancel: {1157            label: `<span class='icon-x'></span> ${langObj.popupMsgs[4].msg}`1158          }1159        },1160        callback: function (result) {1161          if (!result) {1162            unzipSwapfile(null)1163          } else {1164            settings.set('delCopyFolder', $('#rmCpDirCheck').prop('checked'))1165            copyToUSB(mpLocation)1166          }1167        }1168      })1169      $('#rmCpDirCheck').prop('checked', settings.get('delCopyFolder', false))1170      return usb1171    }1172  } catch (e) {1173    bootbox.alert({1174      title: '<center>Error Locating Available USB Drives</center>',1175      message: `<div>${e.toString()}</div><div class="w3-center w3-large"><h2>Build has completed successfully</h2>Although USB drives cannot be found because of an error.<br>${langObj.popupMsgs[9].msg} <pre>${tmpdir.replace(/\\/g, '/')}</pre> ${langObj.popupMsgs[10].msg}. <br><button href='' class='w3-large w3-center w3-black w3-btn w3-ripple nousbbutton' title='Copy These Files To A Blank USB Drive' onclick='openCopyFolder()'>${langObj.menu.copytousb.toolTip}</button></div> `,1176      callback: () => {1177        bootbox.hideAll()1178        unzipSwapfile(null)1179      }1180    })1181    appendAIOlog(e)1182  }1183}1184function noUsbDrive () {1185  bootbox.hideAll()1186  bootbox.alert({1187    title: `<h2>Compilation Finished!</h2>`,1188    className: `compFinishBox`,1189    message: `${langObj.popupMsgs[9].msg} <pre>${tmpdir.replace(/\\/g, '/')}</pre> ${langObj.popupMsgs[10].msg}. <br><button href='' class='w3-large w3-center w3-black w3-btn w3-ripple nousbbutton' title='Copy These Files To A Blank USB Drive' onclick='openCopyFolder()'>${langObj.menu.copytousb.toolTip}</button>`,1190    callback: () => { finishedMessage() }1191  })1192  appendAIOlog(`<li style='color:#4a0dab'>To Install Tweak Files: Copy Entire Contents of "_copy_to_usb" Onto USB Drive.</li><li style='color:#1a0dab'>Location:<a href='' onclick='openCopyFolder()'><u> ${tmpdir.replace(/\\/g, '/')}</u></a></li>`)1193}1194function copyToUSB (mp) {1195  var copyingUSB = bootbox.dialog({1196    message: `<div class='w3-center'><h3>${langObj.popupMsgs[11].msg} ${mp.replace(/\\/g, '/')}...  ${langObj.popupMsgs[12].msg}...</h3><br><div id='userLogView' style='text-align:center;' ></div><br><img class='loader' src='./files/img/load-0.gif' alt='...' /></div>`,1197    className: 'copyingtoUSB',1198    closeButton: false1199  })1200  if (userOps.autorun.installer && userOps.autorun.serial) {1201    mp = `${mp}/XX`1202    mkdirp.sync(mp)1203  }1204  try {1205    copydir(tmpdir, mp, (err) => {1206      if (err) {1207        dialog.showErrorBox('Error: Unable to copy files to USB drive', `${err.toString()}`)1208        appendAIOlog(`<li style='color:#ff0000'>${err} Unable To Copy Files To USB Drive ${mp.replace(/\\/g, '/')}</li>`)1209        errFlag = true1210        finishedMessage()1211      } else {1212        appendAIOlog(`<li style='color:#002200;font-weight:800;'>Files Copied to USB Drive ${mp.replace(/\\/g, '/')}.</li>`)1213      }1214      copyingUSB.hide()1215      unzipSwapfile(mp)1216    })1217  } catch (err) {1218    bootbox.hideAll()1219    dialog.showErrorBox(`Error Copying to USB`, `${err.toString()}`)1220    appendAIOlog(`<li style='color:#ff0000'>${err} Unable To Copy Files To USB Drive ${mp.replace(/\\/g, '/')}</li>`)1221  }1222}1223function unzipSwapfile (dest) {1224  var nocopy = false1225  if (!dest) {1226    nocopy = true1227    dest = `${tmpdir}`1228  }1229  swapdest = `${dest}${swapdest}`.replace(/(\\|\/\/)/g, '/')1230  if (copySwapfile) {1231    copySwapfile = false1232    appendAIOlog(`<li style='color:#005182'>${langObj.popupMsgs[13].msg}: ${swapdest}</li>`)1233    var swapMsg = bootbox.dialog({1234      message: `<div class='w3-center'><h3>${langObj.popupMsgs[13].msg}: ${swapdest}...  ${langObj.popupMsgs[12].msg}... </h3><br><div id='swapLogView' style='text-align:center;' ></div><br><img class='loader' src='./files/img/load-0.gif' alt='...' /></div>`,1235      closeButton: false1236    })1237    setTimeout(() => {1238      if (document.getElementById('swapLogView')) {1239        document.getElementById('swapLogView').innerHTML += `\n\n${langObj.popupMsgs[14].msg}`1240      }1241      setTimeout(() => {1242        if (document.getElementById('swapLogView')) {1243          document.getElementById('swapLogView').innerHTML += `\n\n${langObj.popupMsgs[15].msg}`1244        }1245        setTimeout(() => {1246          if (document.getElementById('swapLogView')) {1247            document.getElementById('swapLogView').innerHTML = `${langObj.popupMsgs[16].msg}:<br>${langObj.tweakOps[19].toolTip}`1248          }1249        }, 10000)1250      }, 10000)1251    }, 10000)1252    try {1253      mkdirp.sync(`${swapdest}`)1254    } catch (e) {1255      appendAIOlog(`<li style='color:#ff0000'>${e} Swapfile Already Exists, Overwriting...</li>`)1256    }1257    extract(`${approot}/files/tweaks/config/swapfile/swapfile.zip`, { dir: `${swapdest}` }, (err) => {1258      if (err) {1259        fs.unlinkSync(`${swapdest}/swapfile`)1260        appendAIOlog(`<li style='color:#ff0000'>Swapfile Error: ${err}</li>`)1261        console.error(err.toString(), err)1262        dialog.showErrorBox('Swapfile Error', `CANNOT UNZIP SWAPFILE - ${err.toString()}`)1263      } else {1264        appendAIOlog(`<li style='color:#005182'>Swapfile Unzipped.</li>`)1265      }1266      swapMsg.modal('hide')1267      if (nocopy) {1268        noUsbDrive()1269      } else {1270        finishedMessage(dest)1271      }1272    })1273  } else {1274    if (nocopy) {1275      noUsbDrive()1276    } else {1277      finishedMessage(dest)1278    }1279  }1280}1281var strtOver = `<button id="startOver" class="w3-round-large w3-btn w3-ripple w3-large w3-hover-white w3-border w3-border-white w3-hover-border-black" onclick="location.reload()" autofocus><span class="icon-space-shuttle"></span>     ${langObj.popupMsgs[17].msg}</button>`1282var viewLog = `<button class="w3-round-large w3-indigo w3-btn w3-ripple w3-hover-cyan w3-large w3-border w3-border-black view-log" title='Compile Log' onclick="$('#opn-mzd-log').click()"><span class='icon-star-full'></span>   ${langObj.popupMsgs[18].msg}</button>`1283var closeApp = `<button class="w3-round-large w3-red w3-btn w3-ripple w3-hover-lime w3-large w3-border w3-border-purple" title="Close The App" onclick="window.close()"><span class="icon-exit"></span>    ${langObj.popupMsgs[19].msg}</button>`1284var cp2usb = `<button class="w3-round-large w3-teal w3-btn w3-ripple w3-hover-pink w3-large w3-border w3-border-indigo" style="letter-spacing:1px" title="Copy These Files To A Blank USB Drive" onclick="openCopyFolder()"><span class="icon-copy2"></span> ${langObj.menu.copytousb.toolTip}</button>`1285var saveBtn = `<button class="w3-round-large w3-purple w3-btn w3-ripple w3-hover-deep-orange w3-large w3-border w3-border-green" style="letter-spacing:.81px" title="Save Options" onclick="$('#save-btn').click()"><span class="icon-floppy-disk"></span> ${langObj.menu.save.toolTip}</button>`1286var openUSB = ''1287function finishedMessage (mp) {1288  // Finished message1289  if (mp) {1290    if (settings.get('delCopyFolder', false)) {1291      cleanCopyDir()1292      cp2usb = ''1293    }1294    openUSB = `<h3><button class="w3-round-large w3-amber w3-btn w3-ripple w3-hover-blue w3-large w3-border w3-border-pink" title='${langObj.popupMsgs[5].msg}' onclick="shell.openItem('${process.platform === 'win32' ? mp.replace(/\\/g, '/') : mp}')"></span><span class="icon-usb3"></span>${langObj.popupMsgs[5].msg} ${mp.replace(/\\/g, '/')}</button></h3>`1295  }1296  bootbox.hideAll()1297  if (errFlag) {1298    bootbox.dialog({1299      message: `<div class="errMessage w3-center"><span class="w3-closebtn" onclick="location.reload()">&times;</span><h2>An Error Has Occured.</h2>${$('#AIO-ERR').html()}<h3>${strtOver}</h3><h3>${saveBtn}</h3><h3>${viewLog}</h4><h2>Please Try Again.</h4></div>`,1300      className: 'finishedMessage',1301      closeButton: false1302    })1303  } else {1304    setTimeout(() => {1305      var finalbox = bootbox.dialog({1306        message: `<span class="w3-closebtn" onclick="postInstallTitle()">&times;</span><div class="w3-center w3-container w3-blue-grey" style="line-height:1.5;"><h1><small class="icon-bolt3"></small> ${langObj.popupMsgs[20].msg} <small class="icon-magic-wand"></small></h1><h3>${strtOver}</h3><h3>${viewLog}</h3><h3>${openUSB}</h3><h3>${cp2usb}</h3><h3>${saveBtn}</h3><h3>${closeApp}</h3></div>`,1307        className: 'finishedMessage',1308        closeButton: false1309      })1310      finalbox.on('shown.bs.modal', () => {1311        $('#startOver').focus()1312      })1313    }, 100)1314  }1315  setTimeout(() => {1316    appendAIOlog(`<li style='color:#000000;font-weight:800;'><em>Finished!</em></li></ul></div>`)1317  }, 1000)1318}1319function postInstallTitle () {1320  bootbox.hideAll()1321  $('.twkfltr').hide()1322  document.getElementById(`mzd-title`).innerHTML = `${viewLog}${document.getElementById('mzd-title').innerHTML}${strtOver}`1323}1324function saveInstallerOps (user) {1325  settings.set('keepBackups', user.backups.org)1326  settings.set('testBackups', user.backups.test)1327  settings.set('skipConfirm', user.backups.skipconfirm)1328  settings.set('apps2resources', user.backups.apps2resources)1329}1330function cleanCopyDir () {1331  rimraf(`${tmpdir}`, () => { appendAIOlog(`<li style='color:#ff3366'>Deleted '_copy_to_usb' Folder</li>`) })1332}1333function casdkAppOptions (apps, inst) {1334  var casdkapps = `APPSIMPLEDASHBOARD=`1335  casdkapps += (apps.simpledashboard) ? `1\n` : `0\n`1336  casdkapps += `APPGPSSPEED=`1337  casdkapps += (apps.gpsspeed) ? `1\n` : `0\n`1338  casdkapps += `APPMULTIDASH=`1339  casdkapps += (apps.multidash) ? `1\n` : `0\n`1340  casdkapps += `APPVDD=`1341  casdkapps += (apps.vdd) ? `1\n` : `0\n`1342  casdkapps += `APPDEVTOOLS=`1343  casdkapps += (apps.devtools) ? `1\n` : `0\n`1344  casdkapps += `APPTERMINAL=`1345  casdkapps += (apps.terminal) ? `1\n` : `0\n`1346  casdkapps += `APPBG=`1347  casdkapps += (apps.background) ? `1\n` : `0\n`1348  casdkapps += `APPTETRIS=`1349  casdkapps += (apps.tetris) ? `1\n` : `0\n`1350  casdkapps += `APPBREAKOUT=`1351  casdkapps += (apps.breakout) ? `1\n` : `0\n`1352  casdkapps += `APPSNAKE=`1353  casdkapps += (apps.snake) ? `1\n` : `0\n`1354  casdkapps += `APPCLOCK=`1355  casdkapps += (apps.clock) ? `1\n` : `0\n`1356  casdkapps += `APPSIMPLESPEEDO=`1357  casdkapps += (apps.simplespeedo) ? `1\n` : `0\n`1358  casdkapps += `CASDK_SD=`1359  casdkapps += (apps.sdcard) ? `1\n` : `0\n`1360  if (inst) {1361    mkdirp.sync(`${tmpdir}/casdk/apps`)1362    addCASDKapp(apps.simpledashboard, 'simpledashboard')1363    addCASDKapp(apps.gpsspeed, 'gpsspeed')1364    addCASDKapp(apps.multidash, 'multidash')1365    addCASDKapp(apps.vdd, 'vdd')1366    addCASDKapp(apps.devtools, 'devtools')1367    addCASDKapp(apps.terminal, 'terminal')1368    addCASDKapp(apps.background, 'background')1369    addCASDKapp(apps.tetris, 'tetris')1370    addCASDKapp(apps.breakout, 'breakout')1371    addCASDKapp(apps.snake, 'snake')1372    addCASDKapp(apps.clock, 'clock')1373    addCASDKapp(apps.simplespeedo, 'simplespeedo')1374  }1375  fs.writeFileSync(`${varDir}/casdkapps.txt`, casdkapps)1376  tweaks2write.push(`${varDir}/casdkapps.txt`)1377}1378function addCASDKapp (add, app) {1379  if (add) {1380    copydir(`${builddir}casdk/apps/app.${app}`, `${tmpdir}/casdk/apps/app.${app}`, (err) => {1381      if (err) {1382        aioLog(`File Copy Error: ${app}: ${err}`, err.message)1383        return1384      }1385      aioLog(`Files for ${app} copied successfully!`)1386    })1387  }1388}1389function buildCASDK (user, apps) {1390  addRootFiles()1391  casdkAppOptions(apps, user.casdk.inst)1392  if (user.casdk.inst) {1393    mkdirp.sync(`${tmpdir}/casdk/`)1394    if (!user.casdkAppsOnly) {1395      tweaks2write.push(`${builddir}00__casdk-i.txt`)1396      tweaks2write.push(`${builddir}00_storage-i.txt`)1397      if (user.casdk.region === 'eu') {1398        fs.writeFileSync(`${varDir}/casdkreg.txt`, `sed -i "s/'na'/'eu'/g" /jci/gui/apps/custom/runtime/runtime.js && log_message "===                      Region Changed to EU                         ==="`)1399      } else {1400        fs.writeFileSync(`${varDir}/casdkreg.txt`, `sed -i "s/'eu'/'na'/g" /jci/gui/apps/custom/runtime/runtime.js && log_message "===                      Region Changed to NA                         ==="`)1401      }1402      tweaks2write.push(`${varDir}/casdkreg.txt`)1403    }1404    tweaks2write.push(`${builddir}00__casdkapps-i.txt`)1405    copydir(`${builddir}casdk`, `${tmpdir}/casdk`, function (stat, filepath, filename) {1406      if (filepath.includes(`apps`)) {1407        return false1408      }1409      return true1410    }, (err) => {1411      if (err) {1412        aioLog(`File Copy Error: ${err}`, err.message)1413        return1414      }1415      aioLog(`Files for CASDK copied successfully!`)1416    })1417  } else if (user.casdk.uninst) {1418    tweaks2write.push(user.casdkAppsOnly ? `${builddir}00__casdkapps-u.txt` : `${builddir}00__casdk-u.txt`)1419  } else {1420    errFlag = true1421    finishedMessage()1422    return1423  }1424  writeTweaksFile()1425}1426function fullSystemRestore (user) {1427  addRootFiles()1428  tweaks2write.push(`${builddir}00___fullRestore.sh`)1429  if (fs.existsSync(`${colordir}/Red/jci.zip`)) {1430    mkdirp.sync(`${tmpdir}/config/color-schemes/Red`)1431    aioLog(`Unzipping Red color theme folder`)1432    extract(`${colordir}/Red/jci.zip`, { dir: `${tmpdir}/config/color-schemes/Red` }, (err) => {1433      if (err) {1434        aioLog(err, err)1435      } else {1436        aioLog(`Red Color Scheme Added Successfully`)1437      }1438    })1439  }1440  copydir(`${builddir}config_org`, `${tmpdir}/config_org`, (err) => {1441    if (err) {1442      aioLog(`File Copy Error: ${err}`, err.message)1443      return1444    }1445    aioLog(`Uninstall files copied successfully!`)1446  })1447  writeTweaksFile()1448}1449function buildAutorunInstaller (user) {1450  if (user.autorun.serial) {1451    tmpdir = `${tmpdir}/XX`1452    try {1453      mkdirp.sync(`${tmpdir}`)1454    } catch (e) {1455      errFlag = true1456      aioLog(`ERROR CREATING ${tmpdir}`, e)1457    }1458  }1459  copydir(`${approot}/files/tweaks/cmu-autorun/installer`, `${tmpdir}`, (err) => {1460    if (err) {1461      errFlag = true1462      aioLog('ERROR COPYING AUTORUN FILES', err)1463    } else {1464      if (user.autorun.id7recovery || user.autorun.serial) {1465        copydir(`${approot}/files/tweaks/cmu-autorun/sdcard/recovery`, `${tmpdir}`, (err) => {1466          if (err) {1467            errFlag = true1468            aioLog('ERROR COPYING ID7RECOVERY FILES', err)1469          } else {1470            rimraf.sync(`${tmpdir}/**/*.md`)1471            rimraf.sync(`${tmpdir}/02-*/*.txt`)1472            if (user.autorun.serial) {1473              fs.unlinkSync(`${tmpdir}/tweaks.sh`)1474            } else {1475              fs.unlinkSync(`${tmpdir}/run.sh`)1476              if (!user.backups.skipconfirm) {1477                replaceInFile(`${tmpdir}/tweaks.sh`, '# confirmation ', '')1478              }1479            }1480            aioLog('ID7_recovery Pack Copied Successfully!')1481            addWifiAP(user)1482          }1483        })1484      } else {1485        aioLog('Autorun Installer/Uninstaller Copied Successfully!')1486        addWifiAP(user)1487      }1488    }1489  })1490}1491function addWifiAP (user) {1492  filesComplete = true1493  opsComplete = true1494  if (user.autorun.autoADB || user.autorun.autoWIFI) {1495    copydir(`${approot}/files/tweaks/cmu-autorun/sdcard/recovery-extra`, `${tmpdir}`, (err) => {1496      if (err) {1497        errFlag = true1498        aioLog('ERROR COPYING AUTORUN FILES', err)1499      }1500      if (!user.autorun.autoADB) {1501        rimraf.sync(`${tmpdir}/*-start-adb/`)1502        rimraf.sync(`${tmpdir}/adb`)1503      }1504      if (!user.autorun.autoWIFI) {1505        rimraf.sync(`${tmpdir}/*-start-wifiAP/`)1506      }1507    })1508  }1509  if (user.autorun.dryrun && !user.autorun.serial) {1510    copydir(`${approot}/files/tweaks/cmu-autorun/sdcard/dryrun`, `${tmpdir}`, (err) => {1511      if (err) { errFlag = true }1512    })1513  }1514  if (user.autorun.autoWIFI) {1515    bootbox.hideAll()1516    var wificonfig = '# This is your wifiAP.config file\nexport NETWORK_WIFI_SSID=YourSSID\nexport NETWORK_WIFI_PASSWORD=YourSSIDpassword\n'1517    bootbox.prompt({1518      title: "You <b>MUST REPLACE THE VALUES</b> <em>'YourSSID'</em> and <em>'YourSSIDPassword'</em> with <b>your own values</b> to run the WiFi AP!",1519      inputType: 'textarea',1520      className: 'wifiSSIDprompt',1521      value: wificonfig,1522      callback: function (result) {1523        if (result === null || result === wificonfig) {1524          bootbox.alert({1525            size: 'small',1526            title: 'Values Were Not Changed',1527            message: 'WiFi AP Will not be installed',1528            callback: () => {1529              rimraf.sync(`${tmpdir}/*-start-wifiAP/`)1530              serialCheck(user)1531            }1532          })1533        } else {1534          fs.writeFileSync(`${tmpdir}/*-start-wifiAP/wifiAP.config`, result + '\n')1535          serialCheck(user)1536        }1537      }1538    })1539  } else {1540    serialCheck(user)1541  }1542}1543function serialCheck (user) {1544  if (user.autorun.serial) {1545    try {1546      fs.unlinkSync(`${tmpdir}/jci-autoupdate`)1547      rimraf.sync(`${tmpdir}/*.temp`)1548      rimraf.sync(`${tmpdir}/*.txt`)1549      rimraf.sync(`${tmpdir}/*.md`)1550      rimraf.sync(`${tmpdir}/*.up`)1551      rimraf.sync(`${tmpdir}/*.sh`)1552    } catch (e) {1553      let m = `${e} - An Error Occured.`1554      aioLog(m, m)1555      finishedMessage()1556      return1557    }1558  }1559  printAIOlog()1560}1561function writePresetMessageFile (result) {1562  try {1563    mkdirp.sync(`${varDir}/message_replies/jci/settings/configurations`)1564    fs.writeFileSync(`${varDir}/message_replies/jci/settings/configurations/blm_msg-system.xml`, result)1565    snackbar('Preset Messages Saved!')1566  } catch (e) {1567    snackbar(`ERROR CREATING PRESET MESSAGES FILE 'blm_msg-system.xml': ${e}`)1568  }1569}1570function copyPresetMessageFile () {1571  if (fs.existsSync(`${varDir}/message_replies`)) {1572    copydir(`${varDir}/message_replies`, `${tmpdir}/config/message_replies`, (err) => {1573      if (err) {1574        aioLog(err + ' copy default preset text messages')1575        addTweakDir('message_replies', true)1576      } else {1577        aioLog('Copied Preset Messages!')1578      }1579    })1580  } else {1581    aioLog('Copy default preset text messages')1582    addTweakDir('message_replies', true)1583  }...

Full Screen

Full Screen

android-controller.js

Source:android-controller.js Github

copy

Full Screen

...379  var b64data = "";380  async.series([381    function (cb) {382      // ensure the ec we're pulling is newly created as a result of the intent.383      this.adb.rimraf(ecOnDevicePath, function () { cb(); });384    }.bind(this),385    function (cb) {386      this.adb.broadcastProcessEnd(intentToBroadcast, this.appProcess, cb);387    }.bind(this),388    function (cb) {389      this.adb.pull(ecOnDevicePath, localfile, cb);390    }.bind(this),391    function (cb) {392      fs.readFile(localfile, function (err, data) {393        if (err) return cb(err);394        b64data = new Buffer(data).toString('base64');395        cb();396      });397    }.bind(this),...

Full Screen

Full Screen

ah1.js

Source:ah1.js Github

copy

Full Screen

...443  const remoteDir = '/data/local/tmp';444  const stringsJson = 'strings.json';445  const remoteFile = `${remoteDir}/${stringsJson}`;446  // clean up remote string.json if present447  await adb.rimraf(remoteFile);448  if (_.isEmpty(opts.appPackage) || !(await fs.exists(opts.app))) {449    return {};450  }451  const stringsTmpDir = path.resolve(opts.tmpDir, opts.appPackage);452  try {453    logger.debug('Extracting strings from apk', opts.app, language, stringsTmpDir);454    const {apkStrings, localPath} = await adb.extractStringsFromApk(opts.app, language, stringsTmpDir);455    await adb.push(localPath, remoteDir);456    return apkStrings;457  } catch (err) {458    logger.warn(`Could not get strings, continuing anyway. Original error: ${err.message}`);459    await adb.shell('echo', [`'{}' > ${remoteFile}`]);460  } finally {461    await fs.rimraf(stringsTmpDir);...

Full Screen

Full Screen

android-helpers.js

Source:android-helpers.js Github

copy

Full Screen

...386    return apkStrings;387  } catch (err) {388    if (!(await fs.exists(opts.app))) {389      // delete remote string.json if present390      await adb.rimraf(`${remotePath}/${stringsJson}`);391    } else {392      logger.warn("Could not get strings, continuing anyway");393      let remoteFile = `${remotePath}/${stringsJson}`;394      await adb.shell('echo', [`'{}' > ${remoteFile}`]);395    }396  }397  return {};398};399helpers.unlockWithUIAutomation = async function (driver, adb, unlockCapabilities) {400  let unlockType = unlockCapabilities.unlockType;401  if (!unlocker.isValidUnlockType(unlockType)) {402    throw new Error(`Invalid unlock type ${unlockType}`);403  }404  let unlockKey = unlockCapabilities.unlockKey;...

Full Screen

Full Screen

android.js

Source:android.js Github

copy

Full Screen

...303      if (!fs.existsSync(this.args.app)) {304        // apk doesn't exist locally so remove old strings.json305        logger.debug("Could not get strings, but it looks like we had an " +306                     "old strings file anyway, so ignoring");307        return this.adb.rimraf(remotePath + '/' + stringsJson, function (err) {308          if (err) return cb(new Error("Could not remove old strings"));309          cb();310        });311      } else {312        // if we can't get strings, just dump an empty json and continue313        logger.warn("Could not get strings, continuing anyway");314        var remoteFile = remotePath + '/' + stringsJson;315        return this.adb.shell("echo '{}' > " + remoteFile, cb);316      }317    }318    var jsonFile = path.resolve(outputPath, stringsJson);319    this.adb.push(jsonFile, remotePath, function (err) {320      if (err) return cb(new Error("Could not push strings.json"));321      cb();...

Full Screen

Full Screen

recordscreen.js

Source:recordscreen.js Github

copy

Full Screen

...201      `otherwise the recorded media might quickly exceed all the free space on the device under test.`);202  }203  if (!_.isEmpty(this._screenRecordingProperties)) {204    for (const record of (this._screenRecordingProperties.records || [])) {205      await this.adb.rimraf(record);206    }207    this._screenRecordingProperties = null;208  }209  const timeout = parseFloat(timeLimit);210  if (isNaN(timeout) || timeout > MAX_TIME_SEC || timeout <= 0) {211    throw new Error(`The timeLimit value must be in range [1, ${MAX_TIME_SEC}] seconds. ` +212      `The value of '${timeLimit}' has been passed instead.`);213  }214  this._screenRecordingProperties = {215    timer: new timing.Timer().start(),216    videoSize,217    timeLimit,218    currentTimeLimit: timeLimit,219    bitRate,220    bugReport,221    records: [],222    recordingProcess: null,223    stopped: false,224  };225  await scheduleScreenRecord(this.adb, this._screenRecordingProperties);226  return result;227};228/**229 * @typedef {Object} StopRecordingOptions230 *231 * @property {?string} remotePath - The path to the remote location, where the resulting video should be uploaded.232 *                                  The following protocols are supported: http/https, ftp.233 *                                  Null or empty string value (the default setting) means the content of resulting234 *                                  file should be encoded as Base64 and passed as the endpount response value.235 *                                  An exception will be thrown if the generated media file is too big to236 *                                  fit into the available process memory.237 * @property {?string} user - The name of the user for the remote authentication.238 * @property {?string} pass - The password for the remote authentication.239 * @property {?string} method - The http multipart upload method name. The 'PUT' one is used by default.240 * @property {?Object} headers - Additional headers mapping for multipart http(s) uploads241 * @property {?string} fileFieldName [file] - The name of the form field, where the file content BLOB should be stored for242 *                                            http(s) uploads243 * @property {?Object|Array<Pair>} formFields - Additional form fields for multipart http(s) uploads244 */245/**246 * Stop recording the screen.247 * If no screen recording has been started before then the method returns an empty string.248 *249 * @param {?StopRecordingOptions} options - The available options.250 * @returns {string} Base64-encoded content of the recorded media file if 'remotePath'251 *                   parameter is falsy or an empty string.252 * @throws {Error} If there was an error while getting the name of a media file253 *                 or the file content cannot be uploaded to the remote location254 *                 or screen recording is not supported on the device under test.255 */256commands.stopRecordingScreen = async function stopRecordingScreen (options = {}) {257  await verifyScreenRecordIsSupported(this.adb, this.isEmulator());258  if (!_.isEmpty(this._screenRecordingProperties)) {259    this._screenRecordingProperties.stopped = true;260  }261  try {262    await terminateBackgroundScreenRecording(this.adb, false);263  } catch (err) {264    log.warn(err.message);265    if (!_.isEmpty(this._screenRecordingProperties)) {266      log.warn('The resulting video might be corrupted');267    }268  }269  if (_.isEmpty(this._screenRecordingProperties)) {270    log.info(`Screen recording has not been previously started by Appium. There is nothing to stop`);271    return '';272  }273  if (this._screenRecordingProperties.recordingProcess && this._screenRecordingProperties.recordingProcess.isRunning) {274    try {275      await this._screenRecordingProperties.recordingProcess.stop('SIGINT', PROCESS_SHUTDOWN_TIMEOUT);276    } catch (e) {277      log.errorAndThrow(`Unable to stop screen recording within ${PROCESS_SHUTDOWN_TIMEOUT}ms`);278    }279    this._screenRecordingProperties.recordingProcess = null;280  }281  if (_.isEmpty(this._screenRecordingProperties.records)) {282    log.errorAndThrow(`No screen recordings have been stored on the device so far. ` +283      `Are you sure the ${SCREENRECORD_BINARY} utility works as expected?`);284  }285  const tmpRoot = await tempDir.openDir();286  try {287    const localRecords = [];288    for (const pathOnDevice of this._screenRecordingProperties.records) {289      localRecords.push(path.resolve(tmpRoot, path.posix.basename(pathOnDevice)));290      await this.adb.pull(pathOnDevice, _.last(localRecords));291      await this.adb.rimraf(pathOnDevice);292    }293    let resultFilePath = _.last(localRecords);294    if (localRecords.length > 1) {295      log.info(`Got ${localRecords.length} screen recordings. Trying to merge them`);296      try {297        resultFilePath = await mergeScreenRecords(localRecords);298      } catch (e) {299        log.warn(`Cannot merge the recorded files. The most recent screen recording is going to be returned as the result. ` +300          `Original error: ${e.message}`);301      }302    }303    return await uploadRecordedMedia(resultFilePath, options.remotePath, options);304  } finally {305    await fs.rimraf(tmpRoot);...

Full Screen

Full Screen

apk-utils-e2e-specs.js

Source:apk-utils-e2e-specs.js Github

copy

Full Screen

...30    (await adb.isAppInstalled('com.example.android.contactmanager')).should.be.true;31    (await adb.uninstallApk('com.example.android.contactmanager')).should.be.true;32    (await adb.isAppInstalled('com.example.android.contactmanager')).should.be.false;33    (await adb.uninstallApk('com.example.android.contactmanager')).should.be.false;34    await adb.rimraf(deviceTempPath + 'ContactManager.apk');35    await adb.push(contactManagerPath, deviceTempPath);36    await adb.installFromDevicePath(deviceTempPath + 'ContactManager.apk');37  });38  describe('startUri', async () => {39    it('should be able to start a uri', async () => {40      await adb.goToHome();41      let res = await adb.getFocusedPackageAndActivity();42      res.appPackage.should.not.equal('com.android.contacts');43      await adb.install(contactManagerPath);44      await adb.startUri('content://contacts/people', 'com.android.contacts');45      await retryInterval(10, 500, async () => {46        res = await adb.shell(['dumpsys', 'window', 'windows']);47        // depending on apilevel, app might show up as active in one of these48        // two dumpsys output formats...

Full Screen

Full Screen

coverage.js

Source:coverage.js Github

copy

Full Screen

2const commands = {};3commands.endCoverage = async function endCoverage (intentToBroadcast, ecOnDevicePath) {4  try {5    // ensure the ec we're pulling is newly created as a result of the intent.6    await this.adb.rimraf(ecOnDevicePath);7    await this.adb.broadcastProcessEnd(intentToBroadcast, this.appProcess);8    return await this.pullFile(ecOnDevicePath);9  } catch (err) {10    log.warn(`Error ending test coverage: ${err.message}`);11  }12  return '';13};14export { commands };...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1var wd = require('wd');2var path = require('path');3var assert = require('assert');4var _ = require('underscore');5var rimraf = require('rimraf');6var desired = {7};8var driver = wd.remote("localhost", 4723);9driver.init(desired, function(err, session) {10  if (err) {11    console.log(err);12    return;13  }14    if (err) {15      console.log(err);16      return;17    }18    driver.elementByCss('#lst-ib', function(err, element) {19      if (err) {20        console.log(err);21        return;22      }23      element.type("Hello World!", function(err) {24        if (err) {25          console.log(err);26          return;27        }28        driver.elementByCss('#lst-ib', function(err, element) {29          if (err) {30            console.log(err);31            return;32          }33          element.text(function(err, text) {34            if (err) {35              console.log(err);36              return;37            }38            assert.equal(text, "Hello World!");39            driver.quit();40          });41        });42      });43    });44  });45});46driver.rimraf('/data/local/tmp/abcd', function(err) {47  if (err) {48    console.log(err);49    return;50  }51  console.log("Folder deleted");52});53var wd = require('wd');54var path = require('path');55var assert = require('assert');56var _ = require('underscore');57var rimraf = require('rimraf');58var desired = {59};60var driver = wd.remote("localhost", 4723);61driver.init(desired, function(err, session) {62  if (err) {63    console.log(err);64    return;65  }66    if (err) {67      console.log(err);68      return;69    }70    driver.elementByCss('#lst-ib', function(err, element) {71      if (err) {72        console.log(err);73        return;74      }75      element.type("Hello World!", function(err) {76        if (err) {77          console.log(err);78          return;79        }

Full Screen

Automation Testing Tutorials

Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.

LambdaTest Learning Hubs:

YouTube

You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.

Run Appium Android Driver automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful