Skip to content

Commit

Permalink
Automatic backups
Browse files Browse the repository at this point in the history
  • Loading branch information
NoudH committed Dec 29, 2021
1 parent ef9a485 commit 2abed96
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 46 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "timewinder",
"version": "1.0.0",
"version": "1.1.0",
"private": true,
"description": "A backup tool for the League of Legends client settings",
"author": "Noud-H",
Expand Down
47 changes: 43 additions & 4 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import * as path from "path";
import yaml from "js-yaml";
import axios from "axios";
import {ipcRenderer} from "electron";
import {execSync} from "child_process";
export default {
name: 'App',
Expand All @@ -46,9 +47,15 @@ export default {
return {
showProgress: false,
backups: [],
//Default settings
settings: {
leagueLocation: 'C:\\Riot Games\\League of Legends',
maxBackups: 5,
automaticBackups: {
enabled: false,
time: "18:00",
frequency: null
}
}
}
},
Expand All @@ -61,7 +68,7 @@ export default {
createBackup: function () {
ipcRenderer.invoke("create-backup")
.then(backup => {
if(backup) {
if (backup) {
this.backups.unshift(backup)
if (this.settings.maxBackups > 0 && this.backups.length > this.settings.maxBackups)
this.backups.pop();
Expand Down Expand Up @@ -145,9 +152,41 @@ export default {
}
},
saveSettings: function (newSettings) {
fs.writeFileSync("settings.json", JSON.stringify(newSettings), () => {
});
this.settings = newSettings;
if (JSON.stringify(newSettings.automaticBackups) !== JSON.stringify(this.settings.automaticBackups)){
try {
if (newSettings.automaticBackups?.enabled) {
execSync(`schtasks /Create /RU SYSTEM /TN timewinder /TR "'${path.resolve('.', 'timewinder.exe')}' --headless --create-backup"`
+ ` /SC ${newSettings.automaticBackups.frequency.frequency} /ST ${newSettings.automaticBackups.time} /F`)
this.$toast.add({
severity: 'success',
summary: 'Automatic backups setup',
detail: 'Automatic backups have been setup successfully.',
life: 5000
});
} else {
execSync(`schtasks /Delete /TN timewinder /F`);
this.$toast.add({
severity: 'success',
summary: 'Automatic backups disabled',
detail: 'Automatic backups have been disabled successfully.',
life: 5000
});
}
} catch (e) {
this.$toast.add({
severity: 'error',
summary: 'An error has occurred with Automatic backups!',
detail: e.message,
life: 5000
});
throw e;
}
}
fs.writeFileSync("settings.json", JSON.stringify(newSettings), () => {});
this.settings = JSON.parse(JSON.stringify(newSettings));
ipcRenderer.send("save-settings");
},
},
created() {
Expand Down
93 changes: 58 additions & 35 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import path from "path";
import {format} from "date-fns";

const isDevelopment = process.env.NODE_ENV !== 'production'
const cmdArgs = process.argv.slice(2);
const rootPath = isDevelopment ? '' : path.dirname(process.execPath);

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
Expand All @@ -19,6 +21,10 @@ app.commandLine.appendSwitch('ignore-certificate-errors', 'true');

async function createWindow() {

if(cmdArgs.includes('--headless')) {
return;
}

// Create the browser window.
const win = new BrowserWindow({
width: 1200,
Expand Down Expand Up @@ -52,15 +58,19 @@ let settings = {
maxBackups: 5,
}

if (fs.existsSync("settings.json")) {
Object.assign(
settings,
JSON.parse(
fs.readFileSync("settings.json", {encoding: "utf-8", flag: "r"})
) || {}
)
function readSettings() {
if (fs.existsSync(path.join(rootPath, "settings.json"))) {
Object.assign(
settings,
JSON.parse(
fs.readFileSync(path.join(rootPath, "settings.json"), {encoding: "utf-8", flag: "r"})
) || {}
)
}
}

readSettings();

ipcMain.on('close', () => {
BrowserWindow.getFocusedWindow().close();
})
Expand All @@ -79,41 +89,18 @@ ipcMain.on('minimize', () => {
})

ipcMain.handle('create-backup', () => {
let date = format(new Date(), "yyyy-MM-dd HH-mm-ss")

if(fs.existsSync(path.join("backups", date))) {
return;
}

try {
fs.mkdirSync(path.join("backups", date), {recursive: true});

fs.copyFileSync(
path.join(settings.leagueLocation, "Config", "LCUAccountPreferences.yaml"),
path.join("backups", date, "LCUAccountPreferences.yaml")
)
fs.copyFileSync(
path.join(settings.leagueLocation, "Config", "LCULocalPreferences.yaml"),
path.join("backups", date, "LCULocalPreferences.yaml")
)

let backups = fs.readdirSync("backups").sort().reverse();
if(settings.maxBackups > 0 && backups.length > settings.maxBackups) {
fs.rmdirSync(path.join("backups", backups[settings.maxBackups]), {recursive: true})
}
return createBackup();
})

return date
} catch (e) {
fs.rmdirSync(path.join("backups", date), {recursive: true})
throw e;
}
ipcMain.on('save-settings', () => {
readSettings();
})

// Quit when all windows are closed.
app.on('window-all-closed', () => {
// On macOS it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
if (process.platform !== 'darwin' && !cmdArgs.includes("--headless")) {
app.quit()
}
})
Expand Down Expand Up @@ -157,3 +144,39 @@ if (isDevelopment) {
if (!fs.existsSync( "backups")){
fs.mkdirSync("backups");
}

if(cmdArgs.includes("--create-backup")) {
createBackup();
app.quit();
}

function createBackup() {
let date = format(new Date(), "yyyy-MM-dd HH-mm-ss")

if(fs.existsSync(path.join(rootPath, "backups", date))) {
return;
}

try {
fs.mkdirSync(path.join(rootPath, "backups", date), {recursive: true});

fs.copyFileSync(
path.join(settings.leagueLocation, "Config", "LCUAccountPreferences.yaml"),
path.join(rootPath, "backups", date, "LCUAccountPreferences.yaml")
)
fs.copyFileSync(
path.join(settings.leagueLocation, "Config", "LCULocalPreferences.yaml"),
path.join(rootPath, "backups", date, "LCULocalPreferences.yaml")
)

let backups = fs.readdirSync(path.join(rootPath, "backups")).sort().reverse();
if(settings.maxBackups > 0 && backups.length > settings.maxBackups) {
fs.rmdirSync(path.join(rootPath, "backups", backups[settings.maxBackups]), {recursive: true})
}

return date
} catch (e) {
fs.rmdirSync(path.join(rootPath, "backups", date), {recursive: true})
throw e;
}
}
48 changes: 46 additions & 2 deletions src/components/Settings.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,38 @@
<br>
<label for="MaxBackups">Max backups</label>
<InputNumber id="MaxBackups" placeholder="0" :min="0" v-model="pr_settings.maxBackups" showButtons/>
<br>
<br>
<label for="AutomaticBackups">Automatic Backups</label>
<br>
<InputSwitch
id="AutomaticBackups"
v-model="pr_settings.automaticBackups.enabled"
:disabled="!pr_isAdmin"
/>
<div v-if="pr_settings.automaticBackups.enabled">
<br>
<label for="AutomaticBackups_Frequency">Frequency</label>
<Dropdown
id="AutomaticBackups_Frequency"
v-model="pr_settings.automaticBackups.frequency"
:options="automaticOptions"
optionLabel="name"
placeholder="Automatic backups"
:disabled="!pr_isAdmin"
/>
<br>
<label for="AutomaticBackups_Time">Time</label>
<InputMask
id="AutomaticBackups_Time"
v-model="pr_settings.automaticBackups.time"
mask="99:99"
placeholder="18:00"
:disabled="!pr_isAdmin"
/>
</div>
<br>
<span v-if="!pr_isAdmin" style="font-size: small; color: var(--text-color-secondary)"><i>(Requires Admin privileges)</i></span>
</div>
</div>
<template #footer>
Expand All @@ -29,6 +61,7 @@

<script>
import {remote, shell} from "electron";
import {exec} from "child_process";
export default {
name: "Settings",
Expand All @@ -38,8 +71,14 @@ export default {
emits: ["save-settings"],
data() {
return {
pr_settings: this.settings,
pr_settings: JSON.parse(JSON.stringify(this.settings)),
pr_isAdmin: false,
showSettings: false,
automaticOptions: [
{name: "Daily", frequency: "DAILY"},
{name: "Weekly", frequency: "WEEKLY"},
{name: "Monthly", frequency: "MONTHLY"},
]
}
},
methods: {
Expand All @@ -53,8 +92,13 @@ export default {
},
openWebPage: function (page) {
shell.openExternal(page);
}
},
},
created() {
exec('NET SESSION', null, (error, stdout, stderr) => {
this.pr_isAdmin = (stderr.length === 0);
})
}
}
</script>

Expand Down
8 changes: 6 additions & 2 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import InputNumber from "primevue/inputnumber";
import FileUpload from 'primevue/fileupload';
import ConfirmDialog from 'primevue/confirmdialog';
import Toast from 'primevue/toast';
import ProgressBar from "primevue/progressbar";
import Dropdown from 'primevue/dropdown';
import InputSwitch from 'primevue/inputswitch';
import InputMask from "primevue/inputmask";

const app = createApp(App);

Expand All @@ -41,9 +43,11 @@ app.component("AccordionTab", AccordionTab);
app.component("Dialog", Dialog);
app.component("InputText", InputText);
app.component("InputNumber", InputNumber);
app.component("InputSwitch", InputSwitch);
app.component("InputMask", InputMask);
app.component("FileUpload", FileUpload);
app.component("ConfirmDialog", ConfirmDialog);
app.component("Toast", Toast);
app.component("ProgressBar", ProgressBar);
app.component("Dropdown", Dropdown);

app.mount('#app');

0 comments on commit 2abed96

Please sign in to comment.