commit f088c17a8b2df4ed1c5d51492e37cba88e77ca21 Author: Jake Date: Sat Oct 18 13:57:06 2014 -0500 init commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ec70f8d --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.png +*.log +node_modules/ diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e7be37c --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Jake0oo0 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/app.js b/app.js new file mode 100644 index 0000000..79ece11 --- /dev/null +++ b/app.js @@ -0,0 +1,61 @@ +var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); + +var routes = require('./routes/index'); +var users = require('./routes/users'); +var avatars = require('./routes/avatars') + +var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'jade'); + +// uncomment after placing your favicon in /public +//app.use(favicon(__dirname + '/public/favicon.ico')); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +app.use(express.static(path.join(__dirname, 'public'))); + +app.use('/', routes); +app.use('/users', users); +app.use('/avatars', avatars) + +// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handlers + +// development error handler +// will print stacktrace +if (app.get('env') === 'development') { + app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: err + }); + }); +} + +// production error handler +// no stacktraces leaked to user +app.use(function(err, req, res, next) { + res.status(err.status || 500); + res.render('error', { + message: err.message, + error: {} + }); +}); + +module.exports = app; diff --git a/bin/www b/bin/www new file mode 100644 index 0000000..89a732e --- /dev/null +++ b/bin/www @@ -0,0 +1,9 @@ +#!/usr/bin/env node +var debug = require('debug')('crafatar'); +var app = require('../app'); + +app.set('port', process.env.PORT || 3000); + +var server = app.listen(app.get('port'), function() { + debug('Express server listening on port ' + server.address().port); +}); diff --git a/package.json b/package.json new file mode 100644 index 0000000..e2e432a --- /dev/null +++ b/package.json @@ -0,0 +1,18 @@ +{ + "name": "crafatar", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "express": "~4.9.0", + "body-parser": "~1.8.1", + "cookie-parser": "~1.3.3", + "morgan": "~1.3.0", + "serve-favicon": "~2.1.3", + "debug": "~2.0.0", + "jade": "~1.6.0", + "node-imagemagick": "0.1.3" + } +} \ No newline at end of file diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css new file mode 100644 index 0000000..30e047d --- /dev/null +++ b/public/stylesheets/style.css @@ -0,0 +1,8 @@ +body { + padding: 50px; + font: 14px "Lucida Grande", Helvetica, Arial, sans-serif; +} + +a { + color: #00B7FF; +} \ No newline at end of file diff --git a/routes/avatars.js b/routes/avatars.js new file mode 100644 index 0000000..7ed80ba --- /dev/null +++ b/routes/avatars.js @@ -0,0 +1,36 @@ +var express = require('express'); +var router = express.Router(); +var skins = require('../skins'); +var fs = require('fs') + +/* GET home page. */ +router.get('/:uuid', function(req, res) { + //res.render('index', { title: 'Express' }); + //res.send("uuid is set to " + req.param("uuid")); + uuid = req.param('uuid') + var filename = 'skins/' + uuid + ".png"; + if (fs.existsSync(filename)) { + fs.readFile(filename, function(err, data) { + res.writeHead(200, {'Content-Type': 'image/jpeg'}); + res.end(data); + }); + } else { + skins.get_profile(uuid, function(profile) { + var skinurl = skins.skin_url(profile); + if (skinurl) { + skins.skin_file(skinurl, filename, function() { + skins.extract_face(filename, filename, function() { + fs.readFile(filename, function(err, data) { + res.writeHead(200, {'Content-Type': 'image/jpeg'}); + res.end(data); + }); + }); + }); + } else { + res.send("No skin found."); + } + }); + } +}); + +module.exports = router; diff --git a/routes/index.js b/routes/index.js new file mode 100644 index 0000000..ed4a9f8 --- /dev/null +++ b/routes/index.js @@ -0,0 +1,10 @@ +var express = require('express'); +var router = express.Router(); + +/* GET home page. */ +router.get('/', function(req, res) { + res.render('index', { title: 'Crafatar' }); +}); + + +module.exports = router; diff --git a/routes/users.js b/routes/users.js new file mode 100644 index 0000000..c00d7de --- /dev/null +++ b/routes/users.js @@ -0,0 +1,9 @@ +var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +router.get('/', function(req, res) { + res.send('respond with a resource'); +}); + +module.exports = router; diff --git a/skins.js b/skins.js new file mode 100644 index 0000000..589de9b --- /dev/null +++ b/skins.js @@ -0,0 +1,48 @@ +var http = require('http'); +var https = require('https'); +var fs = require('fs'); +var imagemagick = require('imagemagick'); + +module.exports = { + get_profile: function(uuid, callback) { + https.get("https://sessionserver.mojang.com/session/minecraft/profile/" + uuid, function(res) { + res.on('data', function(d) { + var profile = JSON.parse(d); + if (profile.error) throw profile.error; + callback(profile); + }); + }); + }, + + skin_url: function(profile) { + var url = null; + if (profile && profile.properties) { + profile.properties.forEach(function(prop) { + if (prop.name == 'textures') { + var json = Buffer(prop.value, 'base64').toString(); + var props = JSON.parse(json); + url = props.textures.SKIN.url; + } + }); + } + return url; + }, + + skin_file: function(url, filename, callback) { + var file = fs.createWriteStream(filename); + http.get(url, function(res) { + res.on('data', function(data) { + file.write(data); + }).on('end', function() { + file.end(); + callback(); + }); + }); + }, + extract_face: function(infile, outfile, callback) { + imagemagick.convert([infile, '-crop', '8x8+8+8', outfile], function(err, stdout) { + if (err) throw err; + callback(); + }); + } +}; \ No newline at end of file diff --git a/skins/.gitkeep b/skins/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/views/error.jade b/views/error.jade new file mode 100644 index 0000000..51ec12c --- /dev/null +++ b/views/error.jade @@ -0,0 +1,6 @@ +extends layout + +block content + h1= message + h2= error.status + pre #{error.stack} diff --git a/views/index.jade b/views/index.jade new file mode 100644 index 0000000..3d63b9a --- /dev/null +++ b/views/index.jade @@ -0,0 +1,5 @@ +extends layout + +block content + h1= title + p Welcome to #{title} diff --git a/views/layout.jade b/views/layout.jade new file mode 100644 index 0000000..b945f57 --- /dev/null +++ b/views/layout.jade @@ -0,0 +1,7 @@ +doctype html +html + head + title= title + link(rel='stylesheet', href='/stylesheets/style.css') + body + block content \ No newline at end of file