<commit_before>module.exports = function (app, config, optimus) {


    var SKIN_COUNTER = 1000000;

    var remoteFileSize = require("remote-file-size");
    var Util = require("../util");
    var http = require('http');
    var https = require('https');
    var fs = require('fs');
    var fileType = require("file-type");
    var imageSize = require("image-size");
    var tmp = require("tmp");
    tmp.setGracefulCleanup();
    var md5 = require("md5");
    var uuid = require("uuid/v4");
    var mongoose = require("mongoose");
    var request = require("request");

    var hasha = require("hasha");

    var imageHash = function (path, callback) {
        hasha.fromFile(path, {
            algorithm: "sha1"
        }).then(function (value) {
            callback(null, value);
        }).catch(function (reason) {
            callback(reason, null);
        })
    };


    var authentication = require("../generator/authentication");
    var dataFetcher = require("../generator/dataFetcher");
    var skinChanger = require("../generator/skinChanger");

    // Schemas
    var Account = require("../db/schemas/account").Account;
    var Skin = require("../db/schemas/skin").Skin;
    var Traffic = require("../db/schemas/traffic").Traffic;
    var Stat = require("../db/schemas/stat").Stat;


    app.post("/generate/url", function (req, res) {
        var url = req.body.url || req.query.url;
        var model = req.body.model || req.query.model || "steve";
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";

        console.log(req.body)
        console.log(req.query)

        console.log(("URL:        " + url).debug);
        console.log(("Model:      " + model).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        if (!url) {
            res.status(400).json({error: "URL is required"});
            return;
        }
        if (!url.startsWith("http")) {
            res.status(400).json({error: "Invalid URL"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;

            remoteFileSize(url, function (err, remoteSize) {
                if (err) /*return*/ console.log(err);
                if (remoteSize <= 0 || remoteSize > 102400) {
                    res.status(400).json({error: "Invalid file size"});
                    return;
                }

                tmp.file(function (err, path, fd, fileCleanup) {
                    if (err) throw err;

                    // var file = fs.createWriteStream(path);
                    request(url, {"encoding": "binary"}, function (err, response, body) {
                        if (err) {
                            fileCleanup();
                            fs.close(fd);
                            return console.log(err);
                        }
                        if (response.statusCode < 200 || response.statusCode > 230) {
                            res.status(500).json({"error": "Failed to download image", code: response.statusCode});
                            fileCleanup();
                            fs.close(fd);
                            return;
                        }
                        fs.writeFile(fd, response.body, "binary", function (err) {
                            if (err) {
                                fileCleanup();
                                fs.close(fd);
                                return console.log(err);
                            }

                            imageHash(path, function (err, fileHash) {
                                if (err) {
                                    fileCleanup();
                                    fs.close(fd);
                                    return console.log(err);
                                }
                                console.log("Hash: " + fileHash);

                                skinChanger.findExistingSkin(fileHash, name, model, visibility, function (existingSkin) {
                                    if (existingSkin) {
                                        res.json(Util.skinToJson(existingSkin, generatorDelay));
                                        fs.close(fd);
                                        fileCleanup();
                                    } else {
                                        var validImage = Util.validateImage(req, res, path);
                                        // cleanup();
                                        if (validImage) {
                                            skinChanger.getAvailableAccount(req, res, function (account) {
                                                Traffic.update({ip: req.realAddress}, {lastRequest: new Date()}, {upsert: true}, function (err, traffic) {
                                                    if (err) {
                                                        fileCleanup();
                                                        fs.close(fd);
                                                        return console.log(err);
                                                    }
                                                    skinChanger.generateUrl(account, url, model, function (result, errorCause) {
                                                        fs.close(fd);
                                                        fileCleanup();
                                                        if (result === true) {
                                                            account.errorCounter = 0;
                                                            if (!account.successCounter) account.successCounter = 0;
                                                            account.successCounter++;
                                                            account.save(function (err, account) {
                                                                if (err) return console.log(err);
                                                                getAndSaveSkinData(account, {
                                                                    type: "url",
                                                                    model: model,
                                                                    visibility: visibility,
                                                                    name: name,
                                                                    via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                                                                    ua: req.headers["user-agent"]
                                                                }, fileHash, uuid(), genStart, function (err, skin) {
                                                                    if (err) {
                                                                        res.status(500).json({error: "Failed to get skin data", err: err, accountId: account.id});
                                                                        console.log(("Failed to download skin data").warn)

                                                                        console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                                        logFail(account, "url", "skin_data_fetch_failed");
                                                                    } else {
                                                                        res.json(Util.skinToJson(skin, generatorDelay));

                                                                        console.log("=> SUCCESS\n".green);
                                                                        logSuccess(account, "url");
                                                                    }
                                                                })
                                                            })
                                                        } else {
                                                            res.status(500).json({error: "Failed to generate skin data", err: result, accountId: account.id});
                                                            console.log(("Failed to generate skin data").warn)

                                                            console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                            logFail(account, "url", errorCause || "skin_data_generation_failed");
                                                        }
                                                    })
                                                })
                                            })
                                        }
                                    }
                                })
                            })
                        })
                    });
                })
            });
        })
    })

    app.post("/generate/upload", function (req, res) {
        if (!req.files) {
            res.status(400).json({error: "Missing files"});
            return;
        }
        var model = req.body.model || req.query.model || "steve";
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";

        console.log(req.body)
        console.log(req.query)

        console.log(("FILE:       " + req.files.file).debug);
        console.log(("Model:      " + model).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        var fileUpload = req.files.file;
        if (!fileUpload) {
            res.status(400).json({error: "Missing file"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;

            tmp.file(function (err, path, fd, fileCleanup) {
                if (err) throw err;

                fileUpload.mv(path, function (err) {
                    if (err) {
                        fileCleanup();
                        fs.close(fd);
                        return console.log(err);
                    }
                    imageHash(path, function (err, fileHash) {
                        if (err) {
                            fileCleanup();
                            fs.close(fd);
                            return console.log(err);
                        }
                        console.log("Hash: " + fileHash);

                        skinChanger.findExistingSkin(fileHash, name, model, visibility, function (existingSkin) {
                            if (existingSkin) {
                                res.json(Util.skinToJson(existingSkin, generatorDelay));
                                fs.close(fd);
                                fileCleanup();
                            } else {
                                fs.readFile(path, function (err, buf) {
                                    if (err) {
                                        fileCleanup();
                                        fs.close(fd);
                                        return console.log(err);
                                    }


                                    var validImage = Util.validateImage(req, res, path);
                                    // cleanup();
                                    if (validImage) {
                                        skinChanger.getAvailableAccount(req, res, function (account) {
                                            Traffic.update({ip: req.realAddress}, {lastRequest: new Date()}, {upsert: true}, function (err, traffic) {
                                                if (err) {
                                                    fileCleanup();
                                                    fs.close(fd);
                                                    return console.log(err);
                                                }
                                                skinChanger.generateUpload(account, buf, model, function (result, errorCause) {
                                                    fs.close(fd);
                                                    fileCleanup();
                                                    if (result === true) {
                                                        account.errorCounter = 0;
                                                        if (!account.successCounter) account.successCounter = 0;
                                                        account.successCounter++;
                                                        account.save(function (err, account) {
                                                            if (err) return console.log(err);
                                                            getAndSaveSkinData(account, {
                                                                type: "upload",
                                                                model: model,
                                                                visibility: visibility,
                                                                name: name,
                                                                via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                                                                ua: req.headers["user-agent"]
                                                            }, fileHash, uuid(), genStart, function (err, skin) {
                                                                if (err) {
                                                                    res.status(500).json({error: "Failed to get skin data", err: err, accountId: account.id});
                                                                    console.log(("Failed to download skin data").warn)

                                                                    console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                                    logFail(account, "upload", "skin_data_fetch_failed");
                                                                } else {
                                                                    res.json(Util.skinToJson(skin, generatorDelay));

                                                                    console.log("=> SUCCESS\n".green);
                                                                    logSuccess(account, "upload");
                                                                }
                                                            });
                                                        })
                                                    } else {
                                                        res.status(500).json({error: "Failed to upload skin data (" + result + ")", err: result, accountId: account.id});
                                                        console.log(("Failed to upload skin data").warn)

                                                        console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                        logFail(account, "upload", errorCause || "skin_data_generation_failed");
                                                    }
                                                })
                                            })
                                        })
                                    }
                                });
                            }
                        })
                    });
                })
            })
        })
    });

    app.get("/generate/user/:uuid", function (req, res) {
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";
        var uuid = req.params.uuid;

        console.log(("USER:       " + uuid).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        var shortUuid = uuid;
        var longUuid = uuid;
        if (shortUuid.indexOf("-") > -1) {
            shortUuid = shortUuid.replace(/-/g, "");
        }
        if (longUuid.indexOf("-") < 0) {
            longUuid = longUuid.substring(0, 8) + "-" + longUuid.substring(8, 8 + 4) + "-" + longUuid.substring(12, 12 + 4) + "-" + longUuid.substring(16, 16 + 4) + "-" + longUuid.substring(20, 20 + 12);
        }

        if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(longUuid)) {
            res.status(400).json({error: "Invalid UUID"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;
            Skin.findOne({uuid: longUuid, name: name, visibility: visibility}, function (err, skin) {
                if (err) return console.log(err);
                if (skin) {// Skin already generated
                    var time = Date.now() / 1000;
                    if (skin.time > time - 1800) {// Wait 30 minutes before generating again
                        skin.duplicate += 1;
                        skin.save(function (err, skin) {
                            if (err) return console.log(err);

                            res.json(Util.skinToJson(skin, generatorDelay));
                        })
                        return;
                    }
                }

                // Don't generate anything, just need to get the user's live skin data

                getAndSaveSkinData({uuid: shortUuid}, {
                    type: "user",
                    model: "unknown",
                    visibility: visibility,
                    name: name,
                    via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                    ua: req.headers["user-agent"]
                }, function (skinTexture, cb) {// Generate the file hash from the skin's texture url
                    if (!skinTexture) return;
                    tmp.file(function (err, path, fd, fileCleanup) {
                        if (err) throw err;

                        var file = fs.createWriteStream(path);
                        console.log("Downloading user texture from " + skinTexture.url + " to " + path);
                        request(skinTexture.url).pipe(file)
                            .on("error", function (err) {
                                if (err) {
                                    fileCleanup();
                                    fs.close(fd);
                                    return console.log(err);
                                }
                            })
                            .on("close", function () {
                                imageHash(path, function (err, fileHash) {
                                    if (err) {
                                        fileCleanup();
                                        fs.close(fd);
                                        return console.log(err);
                                    }
                                    console.log("Hash: " + fileHash);


                                    cb(fileHash);
                                    fs.close(fd);
                                    fileCleanup();
                                });
                            });
                    })
                }, longUuid, genStart, function (err, skin) {
                    if (err) {
                        res.status(500).json({error: "Failed to get skin data", err: err});
                        console.log(("Failed to download skin data").warn)

                        console.log(("=> FAIL\n").red);
                        logFail(null, "user", "skin_data_fetch_failed");
                    } else {
                        res.json(Util.skinToJson(skin, generatorDelay));

                        console.log("=> SUCCESS\n".green);
                        logSuccess(null, "user");
                    }
                })
            })<commit_msg>return reason<commit_after>module.exports = function (app, config, optimus) {


    var SKIN_COUNTER = 1000000;

    var remoteFileSize = require("remote-file-size");
    var Util = require("../util");
    var http = require('http');
    var https = require('https');
    var fs = require('fs');
    var fileType = require("file-type");
    var imageSize = require("image-size");
    var tmp = require("tmp");
    tmp.setGracefulCleanup();
    var md5 = require("md5");
    var uuid = require("uuid/v4");
    var mongoose = require("mongoose");
    var request = require("request");

    var hasha = require("hasha");

    var imageHash = function (path, callback) {
        hasha.fromFile(path, {
            algorithm: "sha1"
        }).then(function (value) {
            callback(null, value);
        }).catch(function (reason) {
            callback(reason, null);
        })
    };


    var authentication = require("../generator/authentication");
    var dataFetcher = require("../generator/dataFetcher");
    var skinChanger = require("../generator/skinChanger");

    // Schemas
    var Account = require("../db/schemas/account").Account;
    var Skin = require("../db/schemas/skin").Skin;
    var Traffic = require("../db/schemas/traffic").Traffic;
    var Stat = require("../db/schemas/stat").Stat;


    app.post("/generate/url", function (req, res) {
        var url = req.body.url || req.query.url;
        var model = req.body.model || req.query.model || "steve";
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";

        console.log(req.body)
        console.log(req.query)

        console.log(("URL:        " + url).debug);
        console.log(("Model:      " + model).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        if (!url) {
            res.status(400).json({error: "URL is required"});
            return;
        }
        if (!url.startsWith("http")) {
            res.status(400).json({error: "Invalid URL"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;

            remoteFileSize(url, function (err, remoteSize) {
                if (err) /*return*/ console.log(err);
                if (remoteSize <= 0 || remoteSize > 102400) {
                    res.status(400).json({error: "Invalid file size"});
                    return;
                }

                tmp.file(function (err, path, fd, fileCleanup) {
                    if (err) throw err;

                    // var file = fs.createWriteStream(path);
                    request(url, {"encoding": "binary"}, function (err, response, body) {
                        if (err) {
                            fileCleanup();
                            fs.close(fd);
                            return console.log(err);
                        }
                        if (response.statusCode < 200 || response.statusCode > 230) {
                            res.status(500).json({"error": "Failed to download image", code: response.statusCode});
                            fileCleanup();
                            fs.close(fd);
                            return;
                        }
                        fs.writeFile(fd, response.body, "binary", function (err) {
                            if (err) {
                                fileCleanup();
                                fs.close(fd);
                                return console.log(err);
                            }

                            imageHash(path, function (err, fileHash) {
                                if (err) {
                                    fileCleanup();
                                    fs.close(fd);
                                    return console.log(err);
                                }
                                console.log("Hash: " + fileHash);

                                skinChanger.findExistingSkin(fileHash, name, model, visibility, function (existingSkin) {
                                    if (existingSkin) {
                                        res.json(Util.skinToJson(existingSkin, generatorDelay));
                                        fs.close(fd);
                                        fileCleanup();
                                    } else {
                                        var validImage = Util.validateImage(req, res, path);
                                        // cleanup();
                                        if (validImage) {
                                            skinChanger.getAvailableAccount(req, res, function (account) {
                                                Traffic.update({ip: req.realAddress}, {lastRequest: new Date()}, {upsert: true}, function (err, traffic) {
                                                    if (err) {
                                                        fileCleanup();
                                                        fs.close(fd);
                                                        return console.log(err);
                                                    }
                                                    skinChanger.generateUrl(account, url, model, function (result, errorCause) {
                                                        fs.close(fd);
                                                        fileCleanup();
                                                        if (result === true) {
                                                            account.errorCounter = 0;
                                                            if (!account.successCounter) account.successCounter = 0;
                                                            account.successCounter++;
                                                            account.save(function (err, account) {
                                                                if (err) return console.log(err);
                                                                getAndSaveSkinData(account, {
                                                                    type: "url",
                                                                    model: model,
                                                                    visibility: visibility,
                                                                    name: name,
                                                                    via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                                                                    ua: req.headers["user-agent"]
                                                                }, fileHash, uuid(), genStart, function (err, skin) {
                                                                    if (err) {
                                                                        var reason = "skin_data_fetch_failed";
                                                                        res.status(500).json({error: "Failed to get skin data", err: err, accountId: account.id, reason: reason});
                                                                        console.log(("Failed to download skin data").warn)

                                                                        console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                                        logFail(account, "url", reason);
                                                                    } else {
                                                                        res.json(Util.skinToJson(skin, generatorDelay));

                                                                        console.log("=> SUCCESS\n".green);
                                                                        logSuccess(account, "url");
                                                                    }
                                                                })
                                                            })
                                                        } else {
                                                            var reason = errorCause || "skin_data_generation_failed";
                                                            res.status(500).json({error: "Failed to generate skin data", err: result, accountId: account.id, reason:reason});
                                                            console.log(("Failed to generate skin data").warn)

                                                            console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                            logFail(account, "url", reason);
                                                        }
                                                    })
                                                })
                                            })
                                        }
                                    }
                                })
                            })
                        })
                    });
                })
            });
        })
    })

    app.post("/generate/upload", function (req, res) {
        if (!req.files) {
            res.status(400).json({error: "Missing files"});
            return;
        }
        var model = req.body.model || req.query.model || "steve";
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";

        console.log(req.body)
        console.log(req.query)

        console.log(("FILE:       " + req.files.file).debug);
        console.log(("Model:      " + model).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        var fileUpload = req.files.file;
        if (!fileUpload) {
            res.status(400).json({error: "Missing file"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;

            tmp.file(function (err, path, fd, fileCleanup) {
                if (err) throw err;

                fileUpload.mv(path, function (err) {
                    if (err) {
                        fileCleanup();
                        fs.close(fd);
                        return console.log(err);
                    }
                    imageHash(path, function (err, fileHash) {
                        if (err) {
                            fileCleanup();
                            fs.close(fd);
                            return console.log(err);
                        }
                        console.log("Hash: " + fileHash);

                        skinChanger.findExistingSkin(fileHash, name, model, visibility, function (existingSkin) {
                            if (existingSkin) {
                                res.json(Util.skinToJson(existingSkin, generatorDelay));
                                fs.close(fd);
                                fileCleanup();
                            } else {
                                fs.readFile(path, function (err, buf) {
                                    if (err) {
                                        fileCleanup();
                                        fs.close(fd);
                                        return console.log(err);
                                    }


                                    var validImage = Util.validateImage(req, res, path);
                                    // cleanup();
                                    if (validImage) {
                                        skinChanger.getAvailableAccount(req, res, function (account) {
                                            Traffic.update({ip: req.realAddress}, {lastRequest: new Date()}, {upsert: true}, function (err, traffic) {
                                                if (err) {
                                                    fileCleanup();
                                                    fs.close(fd);
                                                    return console.log(err);
                                                }
                                                skinChanger.generateUpload(account, buf, model, function (result, errorCause) {
                                                    fs.close(fd);
                                                    fileCleanup();
                                                    if (result === true) {
                                                        account.errorCounter = 0;
                                                        if (!account.successCounter) account.successCounter = 0;
                                                        account.successCounter++;
                                                        account.save(function (err, account) {
                                                            if (err) return console.log(err);
                                                            getAndSaveSkinData(account, {
                                                                type: "upload",
                                                                model: model,
                                                                visibility: visibility,
                                                                name: name,
                                                                via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                                                                ua: req.headers["user-agent"]
                                                            }, fileHash, uuid(), genStart, function (err, skin) {
                                                                if (err) {
                                                                    var reason = "skin_data_fetch_failed";
                                                                    res.status(500).json({error: "Failed to get skin data", err: err, accountId: account.id, reason: reason});
                                                                    console.log(("Failed to download skin data").warn)

                                                                    console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                                    logFail(account, "upload", reason);
                                                                } else {
                                                                    res.json(Util.skinToJson(skin, generatorDelay));

                                                                    console.log("=> SUCCESS\n".green);
                                                                    logSuccess(account, "upload");
                                                                }
                                                            });
                                                        })
                                                    } else {
                                                        var reason = errorCause || "skin_data_generation_failed";
                                                        res.status(500).json({error: "Failed to upload skin data (" + result + ")", err: result, accountId: account.id, reason:reason});
                                                        console.log(("Failed to upload skin data").warn)

                                                        console.log(("=> FAIL #" + account.errorCounter + "\n").red);
                                                        logFail(account, "upload", reason);
                                                    }
                                                })
                                            })
                                        })
                                    }
                                });
                            }
                        })
                    });
                })
            })
        })
    });

    app.get("/generate/user/:uuid", function (req, res) {
        var visibility = parseInt(req.body.visibility || req.query.visibility) || 0;
        var name = req.body.name || req.query.name || "";
        var uuid = req.params.uuid;

        console.log(("USER:       " + uuid).debug);
        console.log(("Visibility: " + visibility).debug);
        console.log(("Name:       " + name).debug);

        var shortUuid = uuid;
        var longUuid = uuid;
        if (shortUuid.indexOf("-") > -1) {
            shortUuid = shortUuid.replace(/-/g, "");
        }
        if (longUuid.indexOf("-") < 0) {
            longUuid = longUuid.substring(0, 8) + "-" + longUuid.substring(8, 8 + 4) + "-" + longUuid.substring(12, 12 + 4) + "-" + longUuid.substring(16, 16 + 4) + "-" + longUuid.substring(20, 20 + 12);
        }

        if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(longUuid)) {
            res.status(400).json({error: "Invalid UUID"});
            return;
        }

        var genStart = Date.now();

        Util.checkTraffic(req, res).then(function (allowed, generatorDelay) {
            if (!allowed) return;
            Skin.findOne({uuid: longUuid, name: name, visibility: visibility}, function (err, skin) {
                if (err) return console.log(err);
                if (skin) {// Skin already generated
                    var time = Date.now() / 1000;
                    if (skin.time > time - 1800) {// Wait 30 minutes before generating again
                        skin.duplicate += 1;
                        skin.save(function (err, skin) {
                            if (err) return console.log(err);

                            res.json(Util.skinToJson(skin, generatorDelay));
                        })
                        return;
                    }
                }

                // Don't generate anything, just need to get the user's live skin data

                getAndSaveSkinData({uuid: shortUuid}, {
                    type: "user",
                    model: "unknown",
                    visibility: visibility,
                    name: name,
                    via: (req.headers["referer"] && req.headers["referer"].indexOf("mineskin.org") > -1) ? "website" : "api",
                    ua: req.headers["user-agent"]
                }, function (skinTexture, cb) {// Generate the file hash from the skin's texture url
                    if (!skinTexture) return;
                    tmp.file(function (err, path, fd, fileCleanup) {
                        if (err) throw err;

                        var file = fs.createWriteStream(path);
                        console.log("Downloading user texture from " + skinTexture.url + " to " + path);
                        request(skinTexture.url).pipe(file)
                            .on("error", function (err) {
                                if (err) {
                                    fileCleanup();
                                    fs.close(fd);
                                    return console.log(err);
                                }
                            })
                            .on("close", function () {
                                imageHash(path, function (err, fileHash) {
                                    if (err) {
                                        fileCleanup();
                                        fs.close(fd);
                                        return console.log(err);
                                    }
                                    console.log("Hash: " + fileHash);


                                    cb(fileHash);
                                    fs.close(fd);
                                    fileCleanup();
                                });
                            });
                    })
                }, longUuid, genStart, function (err, skin) {
                    if (err) {
                        var reason = "skin_data_fetch_failed";
                        res.status(500).json({error: "Failed to get skin data", err: err, reason: reason});
                        console.log(("Failed to download skin data").warn)

                        console.log(("=> FAIL\n").red);
                        logFail(null, "user", reason);
                    } else {
                        res.json(Util.skinToJson(skin, generatorDelay));

                        console.log("=> SUCCESS\n".green);
                        logSuccess(null, "user");
                    }
                })
            })
{'fraction_non_alphanumeric': 0.10234766552360855, 'fraction_numerical': 0.005947099589937891, 'mean_word_length': 0.7563173854447439, 'pattern_counts': {'":': 4, '<': 9, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 474, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1503211', 'n_tokens_mistral': 8374, 'n_tokens_neox': 7856, 'n_words': 1700}