Skip to content
This repository has been archived by the owner on Jul 16, 2019. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
jbdemonte committed Dec 31, 2016
0 parents commit f66a9dd
Show file tree
Hide file tree
Showing 34 changed files with 942 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .bowerrc
@@ -0,0 +1,3 @@
{
"directory": "public/vendors/"
}
3 changes: 3 additions & 0 deletions .jshintrc
@@ -0,0 +1,3 @@
{
"node" : true
}
36 changes: 36 additions & 0 deletions api/:systemId/delete.js
@@ -0,0 +1,36 @@
var fs = require('fs');
var path = require('path');
var tools = require('../../server/tools');

module.exports = function (req, res) {
var system = tools.system.get(req.params.systemId);
if (!system) {
return res.json({error: 'Unknown system'});
}

var promises = (Array.isArray(req.body.games) ? req.body.games : []).map(function (file) {
// check requested file is in the target system path
var filePath = path.resolve(system.path + '/' + file);
if (filePath.indexOf(system.path) === 0) {
return new Promise(function (resolve, reject) {
fs.unlink(filePath, function (err) {
if (err) {
return reject(err);
}
resolve();
});
});
} else {
return Promise.reject(new Error('Unknown file ' + file));
}
});

Promise
.all(promises)
.then(function () {
res.send({});
})
.catch(function (err) {
res.status(400).send({error: err ? err.message : 'Unknown error'});
});
};
13 changes: 13 additions & 0 deletions api/:systemId/get.js
@@ -0,0 +1,13 @@
var fs = require('fs');
var tools = require('../../server/tools');

module.exports = function (req, res) {
var system = tools.system.get(req.params.systemId);
if (!system) {
return res.json({error: 'Unknown system'});
}
fs.readdir(system.path, function (err, files) {
res.json({games: files || []});
});

};
123 changes: 123 additions & 0 deletions api/:systemId/post.js
@@ -0,0 +1,123 @@
var fs = require('fs');
var mkdirp = require('mkdirp');
var AdmZip = require('adm-zip');
var p7zip = require('p7zip');
var tools = require('../../server/tools');
var multipart = require('connect-multiparty');

module.exports = [multipart(), function (req, res) {

var system = tools.system.get(req.params.systemId);
if (!system) {
return res.json({error: 'Unknown system'});
}

if (!req.files ||!req.files.file || !req.files.file.name || !req.files.file.path) {
return res.json({error: 'Upload error'});
}

var file = req.files.file;
var extension = tools.file.extension(file.name);
var moved;

Promise
.resolve()
.then(function () {
return mkdir(system.path);
})
.then(function () {
if (system.extensions.indexOf(extension) < 0) {
if (extension === 'zip') {
return unzip(file.path, system.path, system.extensions);
}
if (extension === '7z') {
return un7zip(file.path, system.path, system.extensions);
}
} else {
return rename(file.path, system.path + '/' + file.name).then(function () {
moved = true;
return [file.name];
});
}
return Promise.reject({message: 'Unknown file type'});
})
.then(function (files) {
res.send({files: files});
})
.catch(function (err) {
res.send({error: err ? err.message : 'Unknown error'});
})
.then(function () { // finally
if (!moved) {
fs.unlink(file.path);
}
});

}];

function rename(source, target) {
return new Promise(function (resolve, reject) {
fs.rename(source, target, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}

function unzip(source, destination, extensions) {
return new Promise(function (resolve, reject) {
try {
var zip = new AdmZip(source);

var files = zip
.getEntries()
.filter(function (entry) {
return ~extensions.indexOf(tools.file.extension(entry.entryName));
})
.map(function (entry) {
zip.extractEntryTo(entry.entryName, destination, false, true);
return entry.entryName;
});
resolve(files);
} catch (err) {
reject(err);
}
});
}

function un7zip(source, destination, extensions) {
return p7zip
.list(source)
.then(function (info) {
var files = info.files
.filter(function (entry) {
return ~extensions.indexOf(tools.file.extension(entry.name));
})
.map(function (entry) {
return entry.name;
});
if (files) {
return p7zip
.extract(source, destination, files, false)
.then(function () {
return files;
});
}
return files;
});
}

function mkdir(target) {
return new Promise(function (resolve, reject) {
mkdirp(target, function (err) {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
22 changes: 22 additions & 0 deletions bower.json
@@ -0,0 +1,22 @@
{
"name": "retropie-manager",
"description": "A ROMs manager for Retropie",
"main": "index.js",
"author": {
"name": "Jean-Baptiste DEMONTE",
"email": "jbdemonte@gmail.com",
"url": "http://jb.demonte.fr"
},
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"public/vendors/"
],
"dependencies": {
"angular": "~1.6.1",
"angular-ui-router": "~0.3.2",
"ng-file-upload": "~12.2.13",
"font-awesome": "^4.7.0"
}
}
4 changes: 4 additions & 0 deletions config.json
@@ -0,0 +1,4 @@
{
"BIOS_PATH": "/home/pi/RetroPie/BIOS",
"ROMS_PATH": "/home/pi/RetroPie/roms"
}
43 changes: 43 additions & 0 deletions index.js
@@ -0,0 +1,43 @@
var glob = require('glob');
var express = require('express');
var stylus = require('stylus');
var nib = require('nib');
var bodyParser = require('body-parser');

var app = express();

function compile(str, path) {
return stylus(str)
.set('filename', path)
.use(nib());
}
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');

app.use(stylus.middleware({ src: __dirname + '/public', compile: compile}));
app.use(express.static(__dirname + '/public'));

app.get('/partials/*.html', function (req, res) {
return res.render(__dirname + '/partials/' + req.params[0]);
});

app.use(bodyParser.json({limit: '10mb'}));
app.use(bodyParser.urlencoded({ extended: true }));

// Load API and create route automatically
glob.sync('api/**/*.js').forEach(function (api) {
var path = api.split('/');
var method = path.pop().replace('.js', '');
var args = require('./' + api);
if (!Array.isArray(args)) {
args = [args];
}
args.unshift('/' + path.join('/'));
app[method].apply(app, args);
});

app.get('*', function (req, res) {
res.render('index', {systems: JSON.stringify(require('./systems.json'))});
});

app.listen(3000);
30 changes: 30 additions & 0 deletions package.json
@@ -0,0 +1,30 @@
{
"name": "retropie-manager",
"version": "0.0.0",
"description": "A ROMs manager for Retropie",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": {
"name": "Jean-Baptiste DEMONTE",
"email": "jbdemonte@gmail.com",
"url": "http://jb.demonte.fr"
},
"license": "MIT",
"keywords": [
"raspberry", "raspbian", "retropie", "rom", "retrogaming"
],
"dependencies": {
"adm-zip": "^0.4.7",
"body-parser": "^1.15.2",
"connect-multiparty": "^2.0.0",
"express": "^4.14.0",
"glob": "^7.1.1",
"jade": "^1.11.0",
"mkdirp": "^0.5.1",
"nib": "^1.1.2",
"p7zip": "^2.0.0",
"stylus": "^0.54.5"
}
}
7 changes: 7 additions & 0 deletions partials/list.jade
@@ -0,0 +1,7 @@
#systems
.channel(ng-repeat="system in systems", ui-sref="system({systemId: system.id})")
.box
span.helper
img(ng-if="system.picture", ng-src="{{'images/systems/' + system.picture}}")
.title
span {{system.name}}
31 changes: 31 additions & 0 deletions partials/system.jade
@@ -0,0 +1,31 @@
#system(ng-class="{uploading: uploading.length}", ngf-drop, ngf-select, ng-model='files', ngf-drag-over-class="'dragover'", ngf-multiple='true', ngf-select-disabled='true', ngf-allow-dir='true')
img(ng-if="system.logo", ng-src="{{'images/systems/' + system.logo}}")
img(ng-if="system.picture && !system.logo", ng-src="{{'images/systems/' + system.picture}}")

h1 {{system.name}}

#uploading-list(ng-if="uploading.length")
.upload(ng-repeat='file in uploading')
span {{file.name}}
.progress
span(style="width:{{file.progress}}%")


.no-entry(ng-if="!games.length")
span No game found

ul#games(ng-if="games.length")
li(ng-repeat='game in games')
label
input(type='checkbox', ng-model="selected[game]")
span(ng-if="!unknown[game]") {{game | noExtension}}
span.unknown(ng-if="unknown[game]") {{game}}

#games-tools(ng-if="games.length")
button(ng-disabled="!hasSelected()", ng-click="remove()")
i.fa.fa-trash-o
span Remove

.drop-label
i.fa.fa-download
span Drop your ROMs for the {{system.name}} here

0 comments on commit f66a9dd

Please sign in to comment.