From ca6cc4db75e179978f26506c678cbc24729b956e Mon Sep 17 00:00:00 2001 From: mercury233 Date: Mon, 15 Nov 2021 09:54:03 +0800 Subject: [PATCH] add save duel log to json back --- data/default_config.json | 1 + data/default_data.json | 4 + ygopro-server.coffee | 125 ++++++++++++++++++++++------ ygopro-server.js | 174 ++++++++++++++++++++++++++++++--------- 4 files changed, 240 insertions(+), 64 deletions(-) diff --git a/data/default_config.json b/data/default_config.json index ed345da9..f69cae00 100644 --- a/data/default_config.json +++ b/data/default_config.json @@ -185,6 +185,7 @@ "enable_recover": false, "show_ip": true, "show_info": true, + "log_save_json": false, "log_save_path": "./config/", "port": 7933 }, diff --git a/data/default_data.json b/data/default_data.json index 30c3d7b5..de7d67d4 100644 --- a/data/default_data.json +++ b/data/default_data.json @@ -24,6 +24,10 @@ ] } }, + "duel_log": { + "file": "./config/duel_log.json", + "duel_log": [] + }, "users": { "file": "./config/admin_user.json", "permission_examples": { diff --git a/ygopro-server.coffee b/ygopro-server.coffee index 16c1d6a9..3b1a08d5 100644 --- a/ygopro-server.coffee +++ b/ygopro-server.coffee @@ -364,6 +364,12 @@ init = () -> catch badwords = global.badwords = default_data.badwords await setting_save(badwords) + if settings.modules.tournament_mode.log_save_json + try + duel_log = global.duel_log = await loadJSONAsync('./config/duel_log.json') + catch + duel_log = global.duel_log = default_data.duel_log + await setting_save(duel_log) if settings.modules.chat_color.enabled and await checkFileExists('./config/chat_color.json') try chat_color = await loadJSONAsync('./config/chat_color.json') @@ -3565,9 +3571,10 @@ ygopro.stoc_follow 'REPLAY', true, (buffer, info, client, server, datas)-> if !room.replays[room.duel_count - 1] # console.log("Replay saved: ", room.duel_count - 1, client.pos) room.replays[room.duel_count - 1] = buffer - if settings.modules.mysql.enabled or room.has_ygopro_error + if settings.modules.mysql.enabled or room.has_ygopro_error or (settings.modules.tournament_mode.enabled and settings.modules.tournament_mode.replay_safe) if client.pos == 0 - replay_filename=moment_now.format("YYYY-MM-DD HH-mm-ss") + dueltime=moment_now.format('YYYY-MM-DD HH-mm-ss') + replay_filename=dueltime if room.hostinfo.mode != 2 for player,i in room.dueling_players replay_filename=replay_filename + (if i > 0 then " VS " else " ") + player.name @@ -3578,6 +3585,21 @@ ygopro.stoc_follow 'REPLAY', true, (buffer, info, client, server, datas)-> fs.writeFile(settings.modules.tournament_mode.replay_path + replay_filename, buffer, (err)-> if err then log.warn "SAVE REPLAY ERROR", replay_filename, err ) + if settings.modules.tournament_mode.log_save_json + duellog = { + time: dueltime, + name: room.name + (if settings.modules.tournament_mode.show_info then (" (Duel:" + room.duel_count + ")") else ""), + roomid: room.process_pid.toString(), + cloud_replay_id: "R#"+room.cloud_replay_id, + replay_filename: replay_filename, + roommode: room.hostinfo.mode, + players: (for player in room.dueling_players + name: player.name + (if settings.modules.tournament_mode.show_ip and !player.is_local then (" (IP: " + player.ip.slice(7) + ")") else "") + (if settings.modules.tournament_mode.show_info and not (room.hostinfo.mode == 2 and player.pos % 2 > 0) then (" (Score:" + room.scores[player.name_vpass] + " LP:" + (if player.lp? then player.lp else room.hostinfo.start_lp) + (if room.hostinfo.mode != 2 then (" Cards:" + (if player.card_count? then player.card_count else room.hostinfo.start_hand)) else "") + ")") else ""), + winner: player.pos == room.winner + ) + } + duel_log.duel_log.unshift duellog + setting_save(duel_log) if settings.modules.mysql.enabled playerInfos = room.dueling_players.map((player) -> return { @@ -3705,42 +3727,83 @@ if true ) - else if u.pathname == '/api/duellog' and settings.modules.mysql.enabled + else if u.pathname == '/api/duellog' and (settings.modules.mysql.enabled or settings.modules.tournament_mode.log_save_json) if !await auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log") response.writeHead(200) response.end(addCallback(u.query.callback, "[{name:'密码错误'}]")) return else response.writeHead(200) - duellog = JSON.stringify(await dataManager.getDuelLogJSONFromCondition(settings.modules.tournament_mode, getDuelLogQueryFromQs(u.query)), null, 2) + if settings.modules.mysql.enabled + duellog = JSON.stringify(await dataManager.getDuelLogJSONFromCondition(settings.modules.tournament_mode, getDuelLogQueryFromQs(u.query)), null, 2) + else + duellog = JSON.stringify duel_log.duel_log, null, 2 response.end(addCallback(u.query.callback, duellog)) - else if u.pathname == '/api/archive.zip' and settings.modules.mysql.enabled + else if u.pathname == '/api/archive.zip' and (settings.modules.mysql.enabled or settings.modules.tournament_mode.log_save_json) if !await auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay_archive") response.writeHead(403) response.end("Invalid password.") return else - try - archiveStream = await dataManager.getReplayArchiveStreamFromCondition(settings.modules.tournament_mode.replay_path, getDuelLogQueryFromQs(u.query)) - if !archiveStream + if settings.modules.mysql.enabled + try + archiveStream = await dataManager.getReplayArchiveStreamFromCondition(settings.modules.tournament_mode.replay_path, getDuelLogQueryFromQs(u.query)) + if !archiveStream + response.writeHead(403) + response.end("Replay not found.") + return + response.writeHead(200, { "Content-Type": "application/octet-stream", "Content-Disposition": "attachment" }) + archiveStream.on "data", (data) -> + response.write data + archiveStream.on "end", () -> + response.end() + archiveStream.on "close", () -> + log.warn("Archive closed") + archiveStream.on "error", (error) -> + log.warn("Archive error: #{error}") + catch error response.writeHead(403) - response.end("Replay not found.") - return - response.writeHead(200, { "Content-Type": "application/octet-stream", "Content-Disposition": "attachment" }) - archiveStream.on "data", (data) -> - response.write data - archiveStream.on "end", () -> - response.end() - archiveStream.on "close", () -> - log.warn("Archive closed") - archiveStream.on "error", (error) -> - log.warn("Archive error: #{error}") - catch error - response.writeHead(403) - response.end("Failed reading replays. " + error) - - else if u.pathname == '/api/clearlog' and settings.modules.mysql.enabled + response.end("Failed reading replays. " + error) + else + try + archive_name = moment_now.format('YYYY-MM-DD HH-mm-ss') + ".zip" + archive_args = ["a", "-mx0", "-y", archive_name] + check = false + for replay in duel_log.duel_log + check = true + archive_args.push(replay.replay_filename) + if !check + response.writeHead(403) + response.end("Duel logs not found.") + return + archive_process = spawn settings.modules.tournament_mode.replay_archive_tool, archive_args, {cwd: settings.modules.tournament_mode.replay_path} + archive_process.on 'error', (err)=> + response.writeHead(403) + response.end("Failed packing replays. " + err) + return + archive_process.on 'exit', (code)=> + fs.readFile(settings.modules.tournament_mode.replay_path + archive_name, (error, buffer)-> + if error + response.writeHead(403) + response.end("Failed sending replays. " + error) + return + else + response.writeHead(200, { "Content-Type": "application/octet-stream", "Content-Disposition": "attachment" }) + response.end(buffer) + return + ) + archive_process.stdout.setEncoding 'utf8' + archive_process.stdout.on 'data', (data)=> + log.info "archive process: " + data + archive_process.stderr.setEncoding 'utf8' + archive_process.stderr.on 'data', (data)=> + log.warn "archive error: " + data + catch error + response.writeHead(403) + response.end("Failed reading replays. " + error) + + else if u.pathname == '/api/clearlog' and (settings.modules.mysql.enabled or settings.modules.tournament_mode.log_save_json) if !await auth.auth(u.query.username, u.query.pass, "clear_duel_log", "clear_duel_log") response.writeHead(200) response.end(addCallback(u.query.callback, "[{name:'密码错误'}]")) @@ -3748,14 +3811,22 @@ if true else response.writeHead(200) if settings.modules.tournament_mode.log_save_path - fs.writeFile(settings.modules.tournament_mode.log_save_path + 'duel_log.' + moment_now.format('YYYY-MM-DD HH-mm-ss') + '.json', JSON.stringify(await dataManager.getDuelLogJSON(settings.modules.tournament_mode), null, 2), (err) -> + if settings.modules.mysql.enabled + duellog = JSON.stringify(await dataManager.getDuelLogJSON(settings.modules.tournament_mode), null, 2) + else + duellog = JSON.stringify duel_log, null, 2 + fs.writeFile(settings.modules.tournament_mode.log_save_path + 'duel_log.' + moment_now.format('YYYY-MM-DD HH-mm-ss') + '.json', duellog, (err) -> if err log.warn 'DUEL LOG SAVE ERROR', err ) - await dataManager.clearDuelLog() + if settings.modules.mysql.enabled + await dataManager.clearDuelLog() + else + duel_log.duel_log = [] + setting_save(duel_log) response.end(addCallback(u.query.callback, "[{name:'Success'}]")) - else if _.startsWith(u.pathname, '/api/replay') and settings.modules.mysql.enabled + else if _.startsWith(u.pathname, '/api/replay') and (settings.modules.mysql.enabled or settings.modules.tournament_mode.replay_safe) if !await auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay") response.writeHead(403) response.end("密码错误") diff --git a/ygopro-server.js b/ygopro-server.js index 2aeb9800..e7e7ff98 100644 --- a/ygopro-server.js +++ b/ygopro-server.js @@ -307,7 +307,7 @@ }; init = async function() { - var AthleticChecker, DataManager, challonge_module_name, challonge_type, chat_color, config, cppversion, defaultConfig, default_data, dirPath, dns, e, get_rooms_count, http_server, https, https_server, imported, j, l, len, len1, len2, m, mkdirList, options, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, postData, ref; + var AthleticChecker, DataManager, challonge_module_name, challonge_type, chat_color, config, cppversion, defaultConfig, default_data, dirPath, dns, duel_log, e, get_rooms_count, http_server, https, https_server, imported, j, l, len, len1, len2, m, mkdirList, options, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, postData, ref; log.info('Reading config.'); await createDirectoryIfNotExists("./config"); await importOldConfig(); @@ -471,6 +471,14 @@ badwords = global.badwords = default_data.badwords; await setting_save(badwords); } + if (settings.modules.tournament_mode.log_save_json) { + try { + duel_log = global.duel_log = (await loadJSONAsync('./config/duel_log.json')); + } catch (error1) { + duel_log = global.duel_log = default_data.duel_log; + await setting_save(duel_log); + } + } if (settings.modules.chat_color.enabled && (await checkFileExists('./config/chat_color.json'))) { try { chat_color = (await loadJSONAsync('./config/chat_color.json')); @@ -4769,7 +4777,7 @@ }); ygopro.stoc_follow('REPLAY', true, async function(buffer, info, client, server, datas) { - var i, j, l, len, len1, player, playerInfos, ref, ref1, replay_filename, room; + var duellog, dueltime, i, j, l, len, len1, player, playerInfos, ref, ref1, replay_filename, room; room = ROOM_all[client.rid]; if (!room) { return settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.block_replay_to_player || settings.modules.replay_delay; @@ -4778,9 +4786,10 @@ // console.log("Replay saved: ", room.duel_count - 1, client.pos) room.replays[room.duel_count - 1] = buffer; } - if (settings.modules.mysql.enabled || room.has_ygopro_error) { + if (settings.modules.mysql.enabled || room.has_ygopro_error || (settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe)) { if (client.pos === 0) { - replay_filename = moment_now.format("YYYY-MM-DD HH-mm-ss"); + dueltime = moment_now.format('YYYY-MM-DD HH-mm-ss'); + replay_filename = dueltime; if (room.hostinfo.mode !== 2) { ref = room.dueling_players; for (i = j = 0, len = ref.length; j < len; i = ++j) { @@ -4800,6 +4809,31 @@ return log.warn("SAVE REPLAY ERROR", replay_filename, err); } }); + if (settings.modules.tournament_mode.log_save_json) { + duellog = { + time: dueltime, + name: room.name + (settings.modules.tournament_mode.show_info ? " (Duel:" + room.duel_count + ")" : ""), + roomid: room.process_pid.toString(), + cloud_replay_id: "R#" + room.cloud_replay_id, + replay_filename: replay_filename, + roommode: room.hostinfo.mode, + players: (function() { + var len2, m, ref2, results; + ref2 = room.dueling_players; + results = []; + for (m = 0, len2 = ref2.length; m < len2; m++) { + player = ref2[m]; + results.push({ + name: player.name + (settings.modules.tournament_mode.show_ip && !player.is_local ? " (IP: " + player.ip.slice(7) + ")" : "") + (settings.modules.tournament_mode.show_info && !(room.hostinfo.mode === 2 && player.pos % 2 > 0) ? " (Score:" + room.scores[player.name_vpass] + " LP:" + (player.lp != null ? player.lp : room.hostinfo.start_lp) + (room.hostinfo.mode !== 2 ? " Cards:" + (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : "") + ")" : ""), + winner: player.pos === room.winner + }); + } + return results; + })() + }; + duel_log.duel_log.unshift(duellog); + setting_save(duel_log); + } if (settings.modules.mysql.enabled) { playerInfos = room.dueling_players.map(function(player) { return { @@ -4906,7 +4940,7 @@ return callback + "( " + text + " );"; }; httpRequestListener = async function(request, response) { - var archiveStream, buffer, death_room_found, duellog, e, err, error, filename, getpath, parseQueryString, pass_validated, roomsjson, success, u; + var archiveStream, archive_args, archive_name, archive_process, buffer, check, death_room_found, duellog, e, err, error, filename, getpath, j, len, parseQueryString, pass_validated, ref, replay, roomsjson, success, u; parseQueryString = true; u = url.parse(request.url, parseQueryString); //pass_validated = u.query.pass == settings.modules.http.password @@ -4962,52 +4996,108 @@ }))); }); } - } else if (u.pathname === '/api/duellog' && settings.modules.mysql.enabled) { + } else if (u.pathname === '/api/duellog' && (settings.modules.mysql.enabled || settings.modules.tournament_mode.log_save_json)) { if (!(await auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log"))) { response.writeHead(200); response.end(addCallback(u.query.callback, "[{name:'密码错误'}]")); return; } else { response.writeHead(200); - duellog = JSON.stringify((await dataManager.getDuelLogJSONFromCondition(settings.modules.tournament_mode, getDuelLogQueryFromQs(u.query))), null, 2); + if (settings.modules.mysql.enabled) { + duellog = JSON.stringify((await dataManager.getDuelLogJSONFromCondition(settings.modules.tournament_mode, getDuelLogQueryFromQs(u.query))), null, 2); + } else { + duellog = JSON.stringify(duel_log.duel_log, null, 2); + } response.end(addCallback(u.query.callback, duellog)); } - } else if (u.pathname === '/api/archive.zip' && settings.modules.mysql.enabled) { + } else if (u.pathname === '/api/archive.zip' && (settings.modules.mysql.enabled || settings.modules.tournament_mode.log_save_json)) { if (!(await auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay_archive"))) { response.writeHead(403); response.end("Invalid password."); return; } else { - try { - archiveStream = (await dataManager.getReplayArchiveStreamFromCondition(settings.modules.tournament_mode.replay_path, getDuelLogQueryFromQs(u.query))); - if (!archiveStream) { + if (settings.modules.mysql.enabled) { + try { + archiveStream = (await dataManager.getReplayArchiveStreamFromCondition(settings.modules.tournament_mode.replay_path, getDuelLogQueryFromQs(u.query))); + if (!archiveStream) { + response.writeHead(403); + response.end("Replay not found."); + return; + } + response.writeHead(200, { + "Content-Type": "application/octet-stream", + "Content-Disposition": "attachment" + }); + archiveStream.on("data", function(data) { + return response.write(data); + }); + archiveStream.on("end", function() { + return response.end(); + }); + archiveStream.on("close", function() { + return log.warn("Archive closed"); + }); + archiveStream.on("error", function(error) { + return log.warn(`Archive error: ${error}`); + }); + } catch (error1) { + error = error1; response.writeHead(403); - response.end("Replay not found."); - return; + response.end("Failed reading replays. " + error); + } + } else { + try { + archive_name = moment_now.format('YYYY-MM-DD HH-mm-ss') + ".zip"; + archive_args = ["a", "-mx0", "-y", archive_name]; + check = false; + ref = duel_log.duel_log; + for (j = 0, len = ref.length; j < len; j++) { + replay = ref[j]; + check = true; + archive_args.push(replay.replay_filename); + } + if (!check) { + response.writeHead(403); + response.end("Duel logs not found."); + return; + } + archive_process = spawn(settings.modules.tournament_mode.replay_archive_tool, archive_args, { + cwd: settings.modules.tournament_mode.replay_path + }); + archive_process.on('error', (err) => { + response.writeHead(403); + response.end("Failed packing replays. " + err); + }); + archive_process.on('exit', (code) => { + return fs.readFile(settings.modules.tournament_mode.replay_path + archive_name, function(error, buffer) { + if (error) { + response.writeHead(403); + response.end("Failed sending replays. " + error); + } else { + response.writeHead(200, { + "Content-Type": "application/octet-stream", + "Content-Disposition": "attachment" + }); + response.end(buffer); + } + }); + }); + archive_process.stdout.setEncoding('utf8'); + archive_process.stdout.on('data', (data) => { + return log.info("archive process: " + data); + }); + archive_process.stderr.setEncoding('utf8'); + archive_process.stderr.on('data', (data) => { + return log.warn("archive error: " + data); + }); + } catch (error1) { + error = error1; + response.writeHead(403); + response.end("Failed reading replays. " + error); } - response.writeHead(200, { - "Content-Type": "application/octet-stream", - "Content-Disposition": "attachment" - }); - archiveStream.on("data", function(data) { - return response.write(data); - }); - archiveStream.on("end", function() { - return response.end(); - }); - archiveStream.on("close", function() { - return log.warn("Archive closed"); - }); - archiveStream.on("error", function(error) { - return log.warn(`Archive error: ${error}`); - }); - } catch (error1) { - error = error1; - response.writeHead(403); - response.end("Failed reading replays. " + error); } } - } else if (u.pathname === '/api/clearlog' && settings.modules.mysql.enabled) { + } else if (u.pathname === '/api/clearlog' && (settings.modules.mysql.enabled || settings.modules.tournament_mode.log_save_json)) { if (!(await auth.auth(u.query.username, u.query.pass, "clear_duel_log", "clear_duel_log"))) { response.writeHead(200); response.end(addCallback(u.query.callback, "[{name:'密码错误'}]")); @@ -5015,16 +5105,26 @@ } else { response.writeHead(200); if (settings.modules.tournament_mode.log_save_path) { - fs.writeFile(settings.modules.tournament_mode.log_save_path + 'duel_log.' + moment_now.format('YYYY-MM-DD HH-mm-ss') + '.json', JSON.stringify((await dataManager.getDuelLogJSON(settings.modules.tournament_mode)), null, 2), function(err) { + if (settings.modules.mysql.enabled) { + duellog = JSON.stringify((await dataManager.getDuelLogJSON(settings.modules.tournament_mode)), null, 2); + } else { + duellog = JSON.stringify(duel_log, null, 2); + } + fs.writeFile(settings.modules.tournament_mode.log_save_path + 'duel_log.' + moment_now.format('YYYY-MM-DD HH-mm-ss') + '.json', duellog, function(err) { if (err) { return log.warn('DUEL LOG SAVE ERROR', err); } }); } - await dataManager.clearDuelLog(); + if (settings.modules.mysql.enabled) { + await dataManager.clearDuelLog(); + } else { + duel_log.duel_log = []; + setting_save(duel_log); + } response.end(addCallback(u.query.callback, "[{name:'Success'}]")); } - } else if (_.startsWith(u.pathname, '/api/replay') && settings.modules.mysql.enabled) { + } else if (_.startsWith(u.pathname, '/api/replay') && (settings.modules.mysql.enabled || settings.modules.tournament_mode.replay_safe)) { if (!(await auth.auth(u.query.username, u.query.pass, "download_replay", "download_replay"))) { response.writeHead(403); response.end("密码错误");