From 1dcf384c0dacef6ee3596b1e22f84c7bb6252c1b Mon Sep 17 00:00:00 2001 From: Jake Date: Sun, 2 Nov 2014 10:36:12 -0600 Subject: [PATCH 01/21] Fix Travis --- .travis.yml | 3 ++- test/test.js | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index f5f5596..8866134 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,4 +4,5 @@ node_js: notifications: irc: "irc.esper.net#spongy" services: - - redis-server \ No newline at end of file + - redis-server +script: "mocha" \ No newline at end of file diff --git a/test/test.js b/test/test.js index 960fdc1..dc121b9 100644 --- a/test/test.js +++ b/test/test.js @@ -5,7 +5,7 @@ var networking = require('../modules/networking'); var helpers = require('../modules/helpers'); var config = require('../modules/config'); var skins = require('../modules/skins'); -var redis = require("redis").createClient(); +var redis = require("../modules/cache"); var uuids = fs.readFileSync('test/uuids.txt').toString().split("\r\n"); // Get a random UUID in order to prevent rate limiting From afc7b0fac740877154de2898b1de48ee647fe9d0 Mon Sep 17 00:00:00 2001 From: Jake Date: Sun, 2 Nov 2014 10:37:50 -0600 Subject: [PATCH 02/21] Make Travis less spammy --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 8866134..0695e16 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,4 +5,5 @@ notifications: irc: "irc.esper.net#spongy" services: - redis-server -script: "mocha" \ No newline at end of file +script: "mocha" +skip_join: true \ No newline at end of file From 3eb8d7278d8efa94bc40b49be39bf14d3645a45e Mon Sep 17 00:00:00 2001 From: Jake Date: Sun, 2 Nov 2014 10:42:24 -0600 Subject: [PATCH 03/21] Don't watch --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index c0bfb12..f041426 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ ], "scripts": { "start": "node server.js", - "test": "node_modules/.bin/mocha -w" + "test": "node_modules/.bin/mocha" }, "dependencies": { "express": "~4.9.0", @@ -32,7 +32,7 @@ "jade": "~1.6.0", "lwip": "0.0.5", "request": "2.45.0", - "redis": " 0.12.1", + "redis": "0.12.1", "mocha": "2.0.1" } } \ No newline at end of file From 326e733d436888c2c939a26d078a3ec943d6ee45 Mon Sep 17 00:00:00 2001 From: Jake Date: Sun, 2 Nov 2014 10:43:17 -0600 Subject: [PATCH 04/21] No --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0695e16..86bbafe 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,5 +5,4 @@ notifications: irc: "irc.esper.net#spongy" services: - redis-server -script: "mocha" skip_join: true \ No newline at end of file From 5a4643f334743f8ab6865d4dd88b54771bf7b0ad Mon Sep 17 00:00:00 2001 From: Jake Date: Sun, 2 Nov 2014 10:47:40 -0600 Subject: [PATCH 05/21] Add Redis getter --- modules/cache.js | 4 ++++ test/test.js | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/modules/cache.js b/modules/cache.js index fd0f4fe..b350b8f 100644 --- a/modules/cache.js +++ b/modules/cache.js @@ -25,6 +25,10 @@ function connect_redis() { var exp = {}; +exp.get_redis = function() { + return redis; +}; + // sets the timestamp for +uuid+ to now exp.update_timestamp = function(uuid) { console.log(uuid + " cache: updating timestamp"); diff --git a/test/test.js b/test/test.js index dc121b9..b684115 100644 --- a/test/test.js +++ b/test/test.js @@ -5,7 +5,7 @@ var networking = require('../modules/networking'); var helpers = require('../modules/helpers'); var config = require('../modules/config'); var skins = require('../modules/skins'); -var redis = require("../modules/cache"); +var cache = require("../modules/cache"); var uuids = fs.readFileSync('test/uuids.txt').toString().split("\r\n"); // Get a random UUID in order to prevent rate limiting @@ -13,7 +13,7 @@ var uuid = uuids[Math.floor(Math.random() * uuids.length)]; describe('Avatar Serving', function(){ before(function() { - redis.flushall(); + cache.get_redis().flushall(); }); describe('UUID', function(){ it("should be an invalid uuid", function(done){ From f71f11aa87afc52653aa0d9c45419f21d8a3528b Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 01:11:19 +0100 Subject: [PATCH 06/21] flush redis after connection established, improve bulk.sh --- modules/cache.js | 2 +- test/bulk.sh | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/modules/cache.js b/modules/cache.js index b350b8f..9e850cf 100644 --- a/modules/cache.js +++ b/modules/cache.js @@ -8,12 +8,12 @@ function connect_redis() { var redisURL = require("url").parse(process.env.REDISCLOUD_URL); redis = require("redis").createClient(redisURL.port, redisURL.hostname); redis.auth(redisURL.auth.split(":")[1]); - redis.flushall(); } else { redis = require("redis").createClient(); } redis.on("ready", function() { console.log("Redis connection established."); + redis.flushall(); }); redis.on("error", function (err) { console.error(err); diff --git a/test/bulk.sh b/test/bulk.sh index 6b7feed..5267027 100755 --- a/test/bulk.sh +++ b/test/bulk.sh @@ -1,4 +1,9 @@ #!/bin/bash +host="$1" +if [ -z "$host" ]; then + echo "Usage: $0 " + exit 1 +fi dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" rm -f "$dir/../skins/"*.png || exit 1 for uuid in `cat "$dir/uuids.txt"`; do @@ -8,5 +13,5 @@ for uuid in `cat "$dir/uuids.txt"`; do if [ "$(( ((RANDOM<<15)|RANDOM) % 2 ))" -eq "1" ]; then helm="&helm" fi - curl -sS -o /dev/null -w "%{url_effective} %{http_code} %{time_total}s\\n" "http://crafatar.com/avatars/$uuid?size=$size$helm" || exit 1 + curl -sSL -o /dev/null -w "%{url_effective} %{http_code} %{time_total}s\\n" "http://$host/avatars/$uuid?size=$size$helm" || exit 1 done From ce8e194b45790930e7204d59607bd23eb68c673d Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 01:18:16 +0100 Subject: [PATCH 07/21] mobile friendly website --- public/stylesheets/style.css | 1 + views/layout.jade | 1 + 2 files changed, 2 insertions(+) diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 973c56b..601e61c 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -27,6 +27,7 @@ mark.green { .code { font-family: monospace; + word-wrap: break-word; } .sideface { width: 180px; diff --git a/views/layout.jade b/views/layout.jade index 240b8dd..155d99c 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -5,6 +5,7 @@ html link(rel='stylesheet', href='/stylesheets/style.css') link(rel="icon", type="image/x-icon", href="/favicon.ico") link(href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css", rel="stylesheet") + meta(name="viewport" content="initial-scale=1,maximum-scale=1") script(src="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js") body a.forkme(href="https://github.com/Jake0oo0/crafatar", target="_blank") From 69be1145b29fb6354e03bab7ea36ae6a9df6ec50 Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 01:21:56 +0100 Subject: [PATCH 08/21] add travis status + link to readme --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 128a443..a071a35 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,6 @@ -# Crafatar +# Crafatar [![travis](https://api.travis-ci.org/Jake0oo0/Spongy.svg)](https://travis-ci.org/Jake0oo0/Spongy/) + +https://crafatar.com Crafatar serves Minecraft skins and heads for use in external applications. Inspired by [Gravatar](https://gravatar.com) (hence the name) and [Minotar](https://minotar.net). From 1ab0ca99136731bc1695f01dd6effddbb7bb1907 Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 01:29:01 +0100 Subject: [PATCH 09/21] compress default images --- public/images/alex.png | Bin 396 -> 162 bytes public/images/steve.png | Bin 484 -> 271 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/public/images/alex.png b/public/images/alex.png index b1222ed7f23c305778f5775034588f03e2ae14d3..8048d1c911d8166b4e8fd3b96a4b4aa6e969dbfd 100644 GIT binary patch delta 22 dcmeBSUc@*-WnzNm#HTi#44$rjF6*2UngCdY2fhFR delta 252 zcmZ3)*uy+Q#gZl6(btiIVPik{pF~y$1_p&>k04(LhAK4%hK3dfhF?ITh8GMBr3MTP zuM!v-tY$DUh!@P+6=*Y2(Z-W8$=lt9FMqFrKTsKGzMESykmdm6e+%}l1_>5;L;?l5 zg+Z8+Vb&Z8kYHJXV>*y_0OMDmem6ag8WRNi0dVN-jzTQVd20h9k04(LhAK4%hK3dfhF?ITh8GMBr3MTP zuM!v-tY$DUh!@P+6=*Y2ae@hBlDE5y#O%ygIiNDmd^fjZAk6{B{}$|94H7IXa7+i% z4q*K1^N)my>mssMOI#yLQW8s2t&)pUffR$0fuV`6p@FWUWr&fHm65TPk-4^kk(Ge~ zTf+tqpjL#2-29Zxv`UBu14~^)vk(JID Date: Mon, 3 Nov 2014 01:52:12 +0100 Subject: [PATCH 10/21] link lwip in readme --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index a071a35..fd9f545 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,8 @@ https://crafatar.com Crafatar serves Minecraft skins and heads for use in external applications. Inspired by [Gravatar](https://gravatar.com) (hence the name) and [Minotar](https://minotar.net). +Image manipulation is done by [lwip](https://github.com/EyalAr/lwip) + ## Usage See the [API Usage](https://crafatar.com) From a6c74c9831ff7a380963115874420e0fc934090e Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 02:12:58 +0100 Subject: [PATCH 11/21] use 160px as default - 180 results in irregular resized pixels (22,5px) --- modules/config.js | 2 +- public/stylesheets/style.css | 24 ++++++++++++------------ test/test.js | 6 +++--- views/index.jade | 4 ++-- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/modules/config.js b/modules/config.js index c9b6725..eb03af3 100644 --- a/modules/config.js +++ b/modules/config.js @@ -1,7 +1,7 @@ var config = { min_size: 0, // < 0 will (obviously) cause crash max_size: 512, // too big values might lead to slow response time or DoS - default_size: 180, // size to be used when no size given + default_size: 160, // size to be used when no size given local_cache_time: 3600, // seconds until we will check if the image changed browser_cache_time: 3600, // seconds until browser will request image again http_timeout: 1000, // ms until connection to mojang is dropped diff --git a/public/stylesheets/style.css b/public/stylesheets/style.css index 601e61c..29d0447 100644 --- a/public/stylesheets/style.css +++ b/public/stylesheets/style.css @@ -30,36 +30,36 @@ mark.green { word-wrap: break-word; } .sideface { - width: 180px; - height: 180px; + width: 160px; + height: 160px; } .sideface.Jake0oo0 { - background:url("/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=180&default=alex"); + background:url("/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=160&default=alex"); } .sideface.Jake0oo0:hover { - background:url("/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=180&default=alex&helm=true"); + background:url("/avatars/2d5aa9cdaeb049189930461fc9b91cc5?size=160&default=alex&helm=true"); } .sideface.redstone_sheep { - background:url("/avatars/ae795aa86327408e92ab25c8a59f3ba1?size=180&default=alex"); + background:url("/avatars/ae795aa86327408e92ab25c8a59f3ba1?size=160&default=alex"); } .sideface.redstone_sheep:hover { - background:url("/avatars/ae795aa86327408e92ab25c8a59f3ba1?size=180&default=alex&helm=true"); + background:url("/avatars/ae795aa86327408e92ab25c8a59f3ba1?size=160&default=alex&helm=true"); } .sideface.Notch { - background:url("/avatars/069a79f444e94726a5befca90e38aaf5?size=180&default=alex"); + background:url("/avatars/069a79f444e94726a5befca90e38aaf5?size=160&default=alex"); } .sideface.Notch:hover { - background:url("/avatars/069a79f444e94726a5befca90e38aaf5?size=180&default=alex&helm=true"); + background:url("/avatars/069a79f444e94726a5befca90e38aaf5?size=160&default=alex&helm=true"); } .sideface.sk89q { - background:url("/avatars/0ea8eca3dbf647cc9d1ac64551ca975c?size=180&default=alex"); + background:url("/avatars/0ea8eca3dbf647cc9d1ac64551ca975c?size=160&default=alex"); } .sideface.sk89q:hover { - background:url("/avatars/0ea8eca3dbf647cc9d1ac64551ca975c?size=180&default=alex&helm=true"); + background:url("/avatars/0ea8eca3dbf647cc9d1ac64551ca975c?size=160&default=alex&helm=true"); } .sideface.md_5 { - background:url("/avatars/af74a02d19cb445bb07f6866a861f783?size=180&default=alex"); + background:url("/avatars/af74a02d19cb445bb07f6866a861f783?size=160&default=alex"); } .sideface.md_5:hover { - background:url("/avatars/af74a02d19cb445bb07f6866a861f783?size=180&default=alex&helm=true"); + background:url("/avatars/af74a02d19cb445bb07f6866a861f783?size=160&default=alex&helm=true"); } \ No newline at end of file diff --git a/test/test.js b/test/test.js index 7c226f1..712196f 100644 --- a/test/test.js +++ b/test/test.js @@ -27,13 +27,13 @@ describe('Avatar Serving', function(){ }); describe('Avatar', function(){ it("should be downloaded", function(done) { - helpers.get_avatar(uuid, false, 180, function(err, status, image) { + helpers.get_avatar(uuid, false, 160, function(err, status, image) { assert.equal(status, 2); done(); }); }); it("should be local", function(done) { - helpers.get_avatar(uuid, false, 180, function(err, status, image) { + helpers.get_avatar(uuid, false, 160, function(err, status, image) { assert.equal(status, 1); done(); }); @@ -44,7 +44,7 @@ describe('Avatar Serving', function(){ cache.get_redis().flushall(); }); it("should be rate limited", function(done) { - helpers.get_avatar(uuid, false, 180, function(err, status, image) { + helpers.get_avatar(uuid, false, 160, function(err, status, image) { assert.equal(err, null); done(); }); diff --git a/views/index.jade b/views/index.jade index 0febd7f..b066ab9 100644 --- a/views/index.jade +++ b/views/index.jade @@ -23,7 +23,7 @@ block content h3 Parameters h4 size - p The size of the image in pixels, 1 - 512.
Default is 180. + p The size of the image in pixels, 1 - 512.
Default is 160. h4 default p The image to be returned when the uuid has no skin.
Valid options are a(href="/avatars/00000000000000000000000000000000?default=steve") steve @@ -41,7 +41,7 @@ block content p Either 'local' or 'downloaded'. Local means that Crafatar already had the image on disk, while downloaded means that it was retrieved from Mojang's skin servers. h3 Examples - p Get jeb_'s avatar, 180 × 180 pixels + p Get jeb_'s avatar, 160 × 160 pixels img(src="/avatars/853c80ef3c3749fdaa49938b674adae6") .well.code <img src="#{domain}/avatars/853c80ef3c3749fdaa49938b674adae6"> p Get jeb_'s avatar, 64 × 64 pixels From b7b07ffc04f07c6f83a858fad53eb9fffe023503 Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 02:16:23 +0100 Subject: [PATCH 12/21] useless menu is useless --- views/layout.jade | 4 ---- 1 file changed, 4 deletions(-) diff --git a/views/layout.jade b/views/layout.jade index 155d99c..de5fcf7 100644 --- a/views/layout.jade +++ b/views/layout.jade @@ -18,8 +18,4 @@ html span.icon-bar span.icon-bar a.navbar-brand(href='/') Crafatar - .navbar-collapse.collapse - ul.nav.navbar-nav - li.active - a(href='/') Home block content \ No newline at end of file From 94911167e6f5ad11cc90fc4f9d2aa83cecaf3ee2 Mon Sep 17 00:00:00 2001 From: jomo Date: Mon, 3 Nov 2014 17:08:19 +0100 Subject: [PATCH 13/21] correct readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index fd9f545..61ca922 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ https://crafatar.com -Crafatar serves Minecraft skins and heads for use in external applications. +Crafatar serves Minecraft avatars based on the skin for use in external applications. Inspired by [Gravatar](https://gravatar.com) (hence the name) and [Minotar](https://minotar.net). Image manipulation is done by [lwip](https://github.com/EyalAr/lwip) From 939d8f10a4863ddceb3781742bdb5844ec8c6e36 Mon Sep 17 00:00:00 2001 From: jomo Date: Tue, 4 Nov 2014 23:43:39 +0100 Subject: [PATCH 14/21] update file date on hash update (face only) --- modules/cache.js | 29 +++++++++++++++++++++++++---- modules/helpers.js | 2 +- 2 files changed, 26 insertions(+), 5 deletions(-) diff --git a/modules/cache.js b/modules/cache.js index 9e850cf..a5b9cc9 100644 --- a/modules/cache.js +++ b/modules/cache.js @@ -1,9 +1,10 @@ var config = require("./config"); var redis = null; +var fs = require("fs"); function connect_redis() { - console.log("connecting to redis"); + console.log("connecting to redis..."); if (process.env.REDISCLOUD_URL) { var redisURL = require("url").parse(process.env.REDISCLOUD_URL); redis = require("redis").createClient(redisURL.port, redisURL.hostname); @@ -12,7 +13,7 @@ function connect_redis() { redis = require("redis").createClient(); } redis.on("ready", function() { - console.log("Redis connection established."); + console.log("Redis connection established. Flushing all data."); redis.flushall(); }); redis.on("error", function (err) { @@ -23,17 +24,37 @@ function connect_redis() { }); } +// sets the date of the face file belonging to +hash+ to now +function update_file_date(hash) { + if (hash) { + var path = config.faces_dir + hash + ".png"; + fs.exists(path, function(exists) { + if (exists) { + var date = new Date(); + fs.utimes("path", date, date, function(err){ + if (err) { + console.error(err); + } + }); + } else { + console.error("Tried to update " + path + " date, but it doesn't exist"); + } + }); + } +} + var exp = {}; exp.get_redis = function() { return redis; }; -// sets the timestamp for +uuid+ to now -exp.update_timestamp = function(uuid) { +// sets the timestamp for +uuid+ and its face file's date to now +exp.update_timestamp = function(uuid, hash) { console.log(uuid + " cache: updating timestamp"); var time = new Date().getTime(); redis.hmset(uuid, "t", time); + update_file_date(hash); }; // create the key +uuid+, store +hash+ and time diff --git a/modules/helpers.js b/modules/helpers.js index 815c152..e1f1b26 100644 --- a/modules/helpers.js +++ b/modules/helpers.js @@ -30,7 +30,7 @@ function store_images(uuid, details, callback) { if (details && details.hash == hash) { // hash hasn't changed console.log(uuid + " hash has not changed"); - cache.update_timestamp(uuid); + cache.update_timestamp(uuid, hash); callback(null, hash); } else { // hash has changed From 5f63cfac78e1a5ff2ccaea305082645563d886cd Mon Sep 17 00:00:00 2001 From: jomo Date: Wed, 5 Nov 2014 00:04:50 +0100 Subject: [PATCH 15/21] fix stupid bug that would result in never updating images redis gives us a string. Thus,