var _ = require('../lib/underscore'), caps = require('../server/caps'), config = require('../config'), db = require('../db'), hooks = require('../hooks'), web = require('../server/web'), winston = require('winston'); var RES = require('../server/state').resources; hooks.hook_sync('temporalAccessCheck', function (info) { if (under_curfew(info.ident, info.board)) info.access = false; }); hooks.hook_sync('boardDiversion', function (info) { if (info.diverted) return; if (under_curfew(info.ident, info.board)) { info.diverted = true; var resp = info.resp; resp.writeHead(200, web.noCacheHeaders); resp.write(RES.curfewTmpl[0]); resp.write('/' + info.board + '/'); resp.write(RES.curfewTmpl[1]); var ending = curfew_ending_time(info.board); resp.write(ending ? ''+ending.getTime() : 'null'); resp.end(RES.curfewTmpl[2]); } }); function under_curfew(ident, board) { if (caps.can_administrate(ident)) return false; var curfew = config.CURFEW_HOURS; if (!curfew || (config.CURFEW_BOARDS || []).indexOf(board) < 0) return false; var hour = new Date().getUTCHours(); return curfew.indexOf(hour) < 0; } function curfew_ending_time(board) { var curfew = config.CURFEW_HOURS; if (!curfew || (config.CURFEW_BOARDS || []).indexOf(board) < 0) return null; var now = new Date(); var tomorrow = day_after(now); var makeToday = hour_date_maker(now); var makeTomorrow = hour_date_maker(tomorrow); /* Dumb brute-force algorithm */ var candidates = []; config.CURFEW_HOURS.forEach(function (hour) { candidates.push(makeToday(hour), makeTomorrow(hour)); }); candidates.sort(compare_dates); for (var i = 0; i < candidates.length; i++) if (candidates[i] > now) return candidates[i]; return null; } function curfew_starting_time(board) { var curfew = config.CURFEW_HOURS; if (!curfew || (config.CURFEW_BOARDS || []).indexOf(board) < 0) return null; var now = new Date(); var tomorrow = day_after(now); var makeToday = hour_date_maker(now); var makeTomorrow = hour_date_maker(tomorrow); /* Even dumber brute-force algorithm */ var candidates = []; config.CURFEW_HOURS.forEach(function (hour) { hour = (hour + 1) % 24; if (config.CURFEW_HOURS.indexOf(hour) < 0) candidates.push(makeToday(hour), makeTomorrow(hour)); }); candidates.sort(compare_dates); for (var i = 0; i < candidates.length; i++) if (candidates[i] > now) return candidates[i]; return null; }; function compare_dates(a, b) { return a.getTime() - b.getTime(); } function day_after(today) { /* Leap shenanigans? This is probably broken somehow. Yay dates. */ var tomorrow = new Date(today.getTime() + 24*3600*1000); if (tomorrow.getUTCDate() == today.getUTCDate()) tomorrow = new Date(tomorrow.getTime() + 12*3600*1000); return tomorrow; } function hour_date_maker(date) { var prefix = date.getUTCFullYear() + '/' + (date.getUTCMonth()+1) + '/' + date.getUTCDate() + ' '; return (function (hour) { return new Date(prefix + hour + ':00:00 GMT'); }); } /* DAEMON */ function shutdown(board, cb) { var yaku = new db.Yakusoku(board, db.UPKEEP_IDENT); yaku.teardown(board, function (err) { yaku.disconnect(); cb(err); }); } function at_next_curfew_start(board, func) { var when = curfew_starting_time(board); winston.info('Next curfew for ' + board + ' at ' + when.toUTCString()); setTimeout(func, when.getTime() - Date.now()); } function enforce(board) { at_next_curfew_start(board, function () { winston.info('Curfew ' + board + ' at ' + new Date().toUTCString()); shutdown(board, function (err) { if (err) winston.error(err); }); setTimeout(enforce.bind(null, board), 30 * 1000); }); } if (config.CURFEW_BOARDS && config.CURFEW_HOURS) config.CURFEW_BOARDS.forEach(enforce);