UNPKG

stardew-git

Version:

A tool that versions changes in Stardew Valley savegames with git.

160 lines (137 loc) 3.78 kB
const chalk = require('chalk') , chokidar = require('chokidar') , fs = require('fs-extra') , Git = require('simple-git') , inquirer = require('inquirer') , path = require('path') , prettifyXml = require('prettify-xml') , xml2js = require('xml2js') require('manakin').global const fileNames = { savegameInfo: 'SaveGameInfo' } module.exports = class StardewWatcher { constructor(directory) { this.directory = path.normalize(directory) this._files = { savegame: path.basename(this.directory), additional: [ fileNames.savegameInfo ] } this.wait = false if(!fs.existsSync(path.normalize(this.directory))) { throw new Error(`Path "${directory}" not found!`) } if(!this.isSdvSaveDirectory()) { throw new Error(`Path "${directory} is not a Stardew Valley savegame directory!`) } } get files() { return [ this._files.savegame, ...this._files.additional ] } get filesAbsolute() { return this.files .map(x => { return path.join(this.directory, x) }) } async init() { return new Promise((resolve, reject) => { this.git = Git(this.directory) this.git.checkIsRepo((err, isRepo) => { if(isRepo) return resolve(this) this.git.init(err => { if(err) return reject() }) inquirer.prompt([{ type: 'input', name: 'url', message: 'Enter the URL for a remote git repository:' }]).then(answers => { this.git.addRemote('origin', answers.url, err => { if(err) return reject() resolve(this) }) }) }) }) } isSdvSaveDirectory() { return fs.existsSync(path.join(this.directory, path.basename(this.directory))) && fs.existsSync(path.join(this.directory, fileNames.savegameInfo)) } run(options) { console.info('Watching!') chokidar.watch(path.join(this.directory, this._files.savegame), { awaitWriteFinish: true }) .on('change', () => { if(this.wait) return this.wait = true process.stdout.write(`Savegame "${chalk.green(this._files.savegame)}" changed!`) const promises = [] try { for(let file of this.filesAbsolute) { promises.push(new Promise((resolve, reject) => { return fs.readFile(file) .then(data => { data = data.toString() if(file.endsWith(fileNames.savegameInfo)) { new xml2js.Parser().parseString(data, (err, xml) => { if(err) return reject(err) this.day = parseInt(xml.Farmer.stats[0].daysPlayed[0]) process.stdout.write(`\u0008: ${chalk.yellow(`day #${this.day}!`)}`) }) } return fs.writeFile(file, prettifyXml(data.toString())) }) .then(resolve) .catch(err => { console.log(' ') reject(err) }) })) } Promise.all(promises) .then(() => { return new Promise((resolve, reject) => { this.git.silent(true) .add(this.files, err => { if(err) return reject(err) process.stdout.write(`\u0008, ${chalk.cyan(`added`)}!`) }) .commit(`Day #${this.day}.`, err => { if(err) return reject(err) process.stdout.write(`\u0008, ${chalk.cyan(`committed`)}!`) if(!options.push) resolve() }) if(options.push) { this.git .push('origin', err => { if(err) return reject(err) process.stdout.write(`\u0008, ${chalk.cyan(`pushed`)}!`) resolve() }) } }) }) .then(() => { console.log() }) .catch(err => { console.log() console.error(err) }) .then(() => { setTimeout(() => { this.wait = false }, 3000) }) } catch(e) { console.error(e) } }) } }