'use strict'; // modules const fs = require('fs'); const mkdirp = require('mkdirp'); const express = require('express'); const multer = require('multer'); const storage = multer.memoryStorage(); const upload = multer({storage: storage}); // HTTP status codes by name const codes = require('./http-codes'); // access check const apiAuthenticationMiddleware = require('../middleware/auth-middleware'); const checkMT = require('../middleware/permission-check').checkMT; const routerHandling = require('../middleware/router-handling'); const idValidator = require('../middleware/validators').idValidator; const resourceLocation = require('../middleware/resource-location').resourceLocation().concat('/logs/'); // log paser tool const parseWarLog = require('../tools/log-parse-tool'); // Mongoose Model using mongoDB const WarModel = require('../models/war'); const PlayerModel = require('../models/player'); const LogKillModel = require('../models/logs/kill'); const LogVehicleKillModel = require('../models/logs/vehicle'); const LogRespawnModel = require('../models/logs/respawn'); const LogReviveModel = require('../models/logs/revive'); const LogTransportModel = require('../models/logs/transport'); const LogFlagModel = require('../models/logs/flag'); const LogBudgetModel = require('../models/logs/budget'); const LogPointsModel = require('../models/logs/points'); const LogPlayerCountModel = require('../models/logs/player-count'); const LogServerFpsModel = require('../models/logs/server-fps'); // util const genericPatch = require('./_generic').genericPatch; const wars = new express.Router(); // routes ********************** wars.route('/') .get((req, res, next) => { const filter = {}; if (req.query.campaignId) { filter.campaign = req.query.campaignId; } WarModel.find(filter, {}, {sort: {date: 'desc'}}, (err, wars) => { if (err) { err.status = codes.servererror; return next(err); } res.locals.items = wars; res.locals.processed = true; next(); }); }) .post(apiAuthenticationMiddleware, checkMT, upload.single('log'), (req, res, next) => { const body = req.body; const warBody = new WarModel(body); if (req.file) { fs.readFile(req.file.buffer, (file, err) => { if (err) { return next(err); } const lineArray = file.toString().split('\n'); const statsResult = parseWarLog(lineArray, warBody); statsResult.war.save((err, war) => { if (err) { return next(err); } LogKillModel.create(statsResult.kills, () => { LogVehicleKillModel.create(statsResult.vehicles, () => { LogRespawnModel.create(statsResult.respawn, () => { LogReviveModel.create(statsResult.revive, () => { LogFlagModel.create(statsResult.flag, () => { LogBudgetModel.create(statsResult.budget, () => { LogTransportModel.create(statsResult.transport, () => { LogPlayerCountModel.create(statsResult.playerCount, () => { LogPointsModel.create(statsResult.points, () => { LogServerFpsModel.create(statsResult.serverFps, (err, serverPerformanceEntries) => { serverPerformanceEntries.forEach((entry) => { const idx = statsResult.players .findIndex((player) => player.name === entry.entityName); if (idx !== -1) { const player = statsResult.players[idx]; player['performance'] = entry._id; statsResult.players[idx] = player; } }); PlayerModel.create(statsResult.players, (err) => { if (err) { return next(err); } const folderName = resourceLocation.concat(war._id); mkdirp(folderName, (err) => { if (err) return next(err); // save clean log file const cleanFile = fs.createWriteStream(folderName + '/clean.log'); statsResult.clean.forEach((cleanLine) => { cleanFile.write(cleanLine + '\n\n'); }); cleanFile.end(); // save raw log file const rawFile = fs.createWriteStream(folderName + '/war.log'); lineArray.forEach((rawLine) => { rawFile.write(rawLine + '\n'); }); rawFile.end(); res.status(codes.created); res.locals.items = war; next(); }); }); }); }); }); }); }); }); }); }); }); }); }); }); } else { const err = new Error('no Logfile provided'); err.status = codes.wrongmediasend; next(err); } } ) .all( routerHandling.httpMethodNotAllowed ); wars.route('/:id') .get(idValidator, (req, res, next) => { WarModel.findById(req.params.id, (err, item) => { if (err) { err.status = codes.servererror; return next(err); } else if (!item) { err = new Error('item not found'); err.status = codes.notfound; return next(err); } PlayerModel.find({warId: item._id}, {}, {sort: {kill: 'desc'}}, (err, items) => { if (err) { return next(err); } const responseObj = item.toObject(); responseObj.players = items; res.locals.items = responseObj; return next(); }); }); }) .patch(apiAuthenticationMiddleware, checkMT, (req, res, next) => { return genericPatch(req, res, next, WarModel); }) .delete(apiAuthenticationMiddleware, checkMT, (req, res, next) => { WarModel.findByIdAndRemove(req.params.id, (err, item) => { if (err) { err.status = codes.wrongrequest; return next(err); } else if (!item) { err = new Error('item not found'); err.status = codes.notfound; return next(err); } // delete linked appearances PlayerModel.find({warId: item._id}).remove().exec(); LogKillModel.find({war: item._id}).remove().exec(); LogVehicleKillModel.find({war: item._id}).remove().exec(); LogRespawnModel.find({war: item._id}).remove().exec(); LogReviveModel.find({war: item._id}).remove().exec(); LogFlagModel.find({war: item._id}).remove().exec(); LogBudgetModel.find({war: item._id}).remove().exec(); LogTransportModel.find({war: item._id}).remove().exec(); LogPointsModel.find({war: item._id}).remove().exec(); LogPlayerCountModel.find({war: item._id}).remove().exec(); // check if logfiles exist and delete from fs const warDir = resourceLocation + req.params.id; if (fs.existsSync(warDir)) { const cleanLog = warDir + '/clean.log'; if (fs.existsSync(cleanLog)) { fs.unlink(cleanLog, (err) => { }); } const sourceLog = warDir + '/war.log'; if (fs.existsSync(sourceLog)) { fs.unlink(sourceLog, (err) => { }); } fs.rmdir(warDir, (err) => { }); } // we don't set res.locals.items and thus it will send a 204 (no content) at the end. see last handler // user.use(..) res.locals.processed = true; next(); }); }) .all( routerHandling.httpMethodNotAllowed ); // this middleware function can be used, if you like or remove it // it looks for object(s) in res.locals.items and if they exist, they are send to the client as json wars.use(routerHandling.emptyResponse); module.exports = wars;