ygopro-server.js 97.2 KB
Newer Older
mercury233's avatar
mercury233 committed
1
// Generated by CoffeeScript 1.12.7
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2
(function() {
3
  var Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_players_banned, ROOM_players_oppentlist, ROOM_unwelcome, ROOM_validate, Room, _, addCallback, ban_user, bunyan, cppversion, crypto, date, defaultconfig, execFile, fs, geoip, get_memory_usage, http, http_server, https, https_server, list, load_dialogues, load_tips, log, moment, nconf, net, options, os, path, pgClient, pg_client, pg_query, redis, redisdb, report_to_big_brother, request, requestListener, roomlist, settings, spawn, spawnSync, url, users_cache, wait_room_start, wait_room_start_arena, windbot_bin, windbot_parameters, windbot_process, ygopro, zlib;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
4

神楽坂玲奈's avatar
神楽坂玲奈 committed
5
  net = require('net');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
6

神楽坂玲奈's avatar
神楽坂玲奈 committed
7 8 9
  http = require('http');

  url = require('url');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
10

神楽坂玲奈's avatar
神楽坂玲奈 committed
11 12 13 14
  path = require('path');

  fs = require('fs');

mercury233's avatar
mercury233 committed
15 16
  os = require('os');

17 18
  crypto = require('crypto');

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
19 20
  execFile = require('child_process').execFile;

mercury233's avatar
mercury233 committed
21 22 23 24
  spawn = require('child_process').spawn;

  spawnSync = require('child_process').spawnSync;

神楽坂玲奈's avatar
神楽坂玲奈 committed
25 26
  _ = require('underscore');

神楽坂玲奈's avatar
tip  
神楽坂玲奈 committed
27 28 29 30 31 32
  _.str = require('underscore.string');

  _.mixin(_.str.exports());

  request = require('request');

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
33 34
  bunyan = require('bunyan');

mercury233's avatar
mercury233 committed
35 36 37 38
  log = bunyan.createLogger({
    name: "mycard"
  });

39 40
  moment = require('moment');

mercury233's avatar
mercury233 committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
  moment.locale('zh-cn', {
    relativeTime: {
      future: '%s内',
      past: '%s前',
      s: '%d秒',
      m: '1分钟',
      mm: '%d分钟',
      h: '1小时',
      hh: '%d小时',
      d: '1天',
      dd: '%d天',
      M: '1个月',
      MM: '%d个月',
      y: '1年',
      yy: '%d年'
    }
  });

mercury233's avatar
mercury233 committed
59 60
  nconf = require('nconf');

mercury233's avatar
mercury233 committed
61
  nconf.file('./config.user.json');
mercury233's avatar
mercury233 committed
62 63 64 65 66 67 68 69 70 71

  defaultconfig = require('./config.json');

  nconf.defaults(defaultconfig);

  settings = global.settings = nconf.get();

  nconf.myset = function(settings, path, val) {
    var key, target;
    nconf.set(path, val);
mercury233's avatar
mercury233 committed
72 73 74 75
    nconf.save();
    if (_.isString(val)) {
      log.info("setting changed", path, val);
    }
mercury233's avatar
mercury233 committed
76 77 78 79 80 81 82 83 84 85 86 87 88
    path = path.split(':');
    if (path.length === 0) {
      settings[path[0]] = val;
    } else {
      target = settings;
      while (path.length > 1) {
        key = path.shift();
        target = target[key];
      }
      key = path.shift();
      target[key] = val;
    }
  };
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
89

90
  try {
mercury233's avatar
mercury233 committed
91 92
    cppversion = parseInt(fs.readFileSync('ygopro/gframe/game.cpp', 'utf8').match(/PRO_VERSION = ([x\dABCDEF]+)/)[1], '16');
    nconf.myset(settings, "version", cppversion);
mercury233's avatar
fix  
mercury233 committed
93
    log.info("ygopro version 0x" + settings.version.toString(16), "(from source code)");
94
  } catch (error1) {
mercury233's avatar
fix  
mercury233 committed
95
    log.info("ygopro version 0x" + settings.version.toString(16), "(from config)");
96
  }
97

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
98
  settings.lflist = (function() {
mercury233's avatar
mercury233 committed
99
    var j, len, ref, results;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
100
    ref = fs.readFileSync('ygopro/lflist.conf', 'utf8').match(/!.*/g);
神楽坂玲奈's avatar
神楽坂玲奈 committed
101
    results = [];
mercury233's avatar
mercury233 committed
102 103
    for (j = 0, len = ref.length; j < len; j++) {
      list = ref[j];
mercury233's avatar
mercury233 committed
104 105 106 107
      date = list.match(/!([\d\.]+)/);
      if (!date) {
        continue;
      }
神楽坂玲奈's avatar
神楽坂玲奈 committed
108
      results.push({
神楽坂玲奈's avatar
神楽坂玲奈 committed
109
        date: moment(list.match(/!([\d\.]+)/)[1], 'YYYY.MM.DD').utcOffset("-08:00"),
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
110
        tcg: list.indexOf('TCG') !== -1
神楽坂玲奈's avatar
神楽坂玲奈 committed
111 112 113 114 115
      });
    }
    return results;
  })();

mercury233's avatar
mercury233 committed
116
  if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
117 118 119 120
    redis = require('redis');
    zlib = require('zlib');
    redisdb = redis.createClient({
      host: "127.0.0.1",
mercury233's avatar
mercury233 committed
121
      port: settings.modules.cloud_replay.redis_port
mercury233's avatar
mercury233 committed
122
    });
mercury233's avatar
mercury233 committed
123 124 125
    redisdb.on('error', function(err) {
      log.warn(err);
    });
mercury233's avatar
mercury233 committed
126 127
  }

mercury233's avatar
mercury233 committed
128 129
  if (settings.modules.windbot.enabled) {
    settings.modules.windbots = require(settings.modules.windbot.botlist).windbots;
mercury233's avatar
mercury233 committed
130 131
  }

神楽坂玲奈's avatar
神楽坂玲奈 committed
132
  ygopro = require('./ygopro.js');
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
133

mercury233's avatar
mercury233 committed
134
  if (settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
135 136
    roomlist = require('./roomlist.js');
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
137

mercury233's avatar
mercury233 committed
138 139 140 141
  if (settings.modules.i18n.auto_pick) {
    geoip = require('geoip-country-lite');
  }

神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
142 143
  users_cache = {};

mercury233's avatar
mercury233 committed
144
  if (settings.modules.mycard.enabled) {
mercury233's avatar
merge  
mercury233 committed
145
    pgClient = require('pg').Client;
mercury233's avatar
mercury233 committed
146
    pg_client = new pgClient(settings.modules.mycard.auth_database);
mercury233's avatar
fix  
mercury233 committed
147 148 149
    pg_client.on('error', function(err) {
      log.warn("PostgreSQL ERROR: ", err);
    });
mercury233's avatar
merge  
mercury233 committed
150
    pg_query = pg_client.query('SELECT username, id from users');
mercury233's avatar
fix  
mercury233 committed
151 152 153
    pg_query.on('error', function(err) {
      log.warn("PostgreSQL Query ERROR: ", err);
    });
mercury233's avatar
merge  
mercury233 committed
154 155 156 157 158 159 160 161 162 163 164
    pg_query.on('row', function(row) {
      users_cache[row.username] = row.id;
    });
    pg_query.on('end', function(result) {
      log.info("users loaded", result.rowCount);
    });
    pg_client.on('drain', pg_client.end.bind(pg_client));
    log.info("loading mycard user...");
    pg_client.connect();
  }

mercury233's avatar
mercury233 committed
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
  get_memory_usage = function() {
    var actualFree, buffers, cached, free, line, lines, percentUsed, prc_free, total;
    prc_free = spawnSync("free", []);
    if (prc_free.stdout) {
      lines = prc_free.stdout.toString().split(/\n/g);
      line = lines[1].split(/\s+/);
      total = parseInt(line[1], 10);
      free = parseInt(line[3], 10);
      buffers = parseInt(line[5], 10);
      cached = parseInt(line[6], 10);
      actualFree = free + buffers + cached;
      percentUsed = parseFloat(((1 - (actualFree / total)) * 100).toFixed(2));
    } else {
      percentUsed = 0;
    }
    return percentUsed;
  };

mercury233's avatar
mercury233 committed
183 184
  Cloud_replay_ids = [];

mercury233's avatar
mercury233 committed
185 186 187 188 189 190
  ROOM_all = [];

  ROOM_players_oppentlist = {};

  ROOM_players_banned = [];

mercury233's avatar
mercury233 committed
191 192 193 194
  ROOM_connected_ip = {};

  ROOM_bad_ip = {};

mercury233's avatar
mercury233 committed
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
  ban_user = function(name) {
    var bad_ip, j, k, len, len1, player, ref, room;
    settings.ban.banned_user.push(name);
    nconf.myset(settings, "ban:banned_user", settings.ban.banned_user);
    bad_ip = 0;
    for (j = 0, len = ROOM_all.length; j < len; j++) {
      room = ROOM_all[j];
      if (room && room.established) {
        ref = room.players;
        for (k = 0, len1 = ref.length; k < len1; k++) {
          player = ref[k];
          if (player && (player.name === name || player.ip === bad_ip)) {
            bad_ip = player.ip;
            ROOM_bad_ip[bad_ip] = 99;
            settings.ban.banned_ip.push(player.ip);
            ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
            player.destroy();
            continue;
          }
        }
      }
    }
  };

mercury233's avatar
mercury233 committed
219
  ROOM_ban_player = function(name, ip, reason, countadd) {
mercury233's avatar
mercury233 committed
220
    var bannedplayer, bantime;
mercury233's avatar
mercury233 committed
221 222 223
    if (countadd == null) {
      countadd = 1;
    }
224 225 226
    if (settings.modules.test_mode.no_ban_player) {
      return;
    }
mercury233's avatar
mercury233 committed
227 228 229 230
    bannedplayer = _.find(ROOM_players_banned, function(bannedplayer) {
      return ip === bannedplayer.ip;
    });
    if (bannedplayer) {
mercury233's avatar
mercury233 committed
231
      bannedplayer.count = bannedplayer.count + countadd;
mercury233's avatar
mercury233 committed
232 233 234 235 236 237 238 239 240 241 242 243
      bantime = bannedplayer.count > 3 ? Math.pow(2, bannedplayer.count - 3) * 2 : 0;
      bannedplayer.time = moment() < bannedplayer.time ? moment(bannedplayer.time).add(bantime, 'm') : moment().add(bantime, 'm');
      if (!_.find(bannedplayer.reasons, function(bannedreason) {
        return bannedreason === reason;
      })) {
        bannedplayer.reasons.push(reason);
      }
      bannedplayer.need_tip = true;
    } else {
      bannedplayer = {
        "ip": ip,
        "time": moment(),
mercury233's avatar
mercury233 committed
244
        "count": countadd,
mercury233's avatar
mercury233 committed
245 246 247 248 249 250 251 252
        "reasons": [reason],
        "need_tip": true
      };
      ROOM_players_banned.push(bannedplayer);
    }
  };

  ROOM_find_or_create_by_name = function(name, player_ip) {
mercury233's avatar
mercury233 committed
253 254
    var room, uname;
    uname = name.toUpperCase();
mercury233's avatar
mercury233 committed
255
    if (settings.modules.windbot.enabled && (uname.slice(0, 2) === 'AI' || (!settings.modules.random_duel.enabled && uname === ''))) {
mercury233's avatar
mercury233 committed
256 257
      return ROOM_find_or_create_ai(name);
    }
mercury233's avatar
mercury233 committed
258
    if (settings.modules.random_duel.enabled && (uname === '' || uname === 'S' || uname === 'M' || uname === 'T')) {
mercury233's avatar
mercury233 committed
259
      return ROOM_find_or_create_random(uname, player_ip);
mercury233's avatar
mercury233 committed
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277
    }
    if (room = ROOM_find_by_name(name)) {
      return room;
    } else if (get_memory_usage() >= 90) {
      return null;
    } else {
      return new Room(name);
    }
  };

  ROOM_find_or_create_random = function(type, player_ip) {
    var bannedplayer, max_player, name, playerbanned, result;
    bannedplayer = _.find(ROOM_players_banned, function(bannedplayer) {
      return player_ip === bannedplayer.ip;
    });
    if (bannedplayer) {
      if (bannedplayer.count > 6 && moment() < bannedplayer.time) {
        return {
mercury233's avatar
mercury233 committed
278
          "error": "${random_banned_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_banned_part2}" + (moment(bannedplayer.time).fromNow(true)) + "${random_banned_part3}"
mercury233's avatar
mercury233 committed
279 280
        };
      }
mercury233's avatar
mercury233 committed
281
      if (bannedplayer.count > 3 && moment() < bannedplayer.time && bannedplayer.need_tip && type !== 'T') {
mercury233's avatar
mercury233 committed
282 283
        bannedplayer.need_tip = false;
        return {
mercury233's avatar
mercury233 committed
284
          "error": "${random_deprecated_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_deprecated_part2}" + (moment(bannedplayer.time).fromNow(true)) + "${random_deprecated_part3}"
mercury233's avatar
mercury233 committed
285 286 287 288
        };
      } else if (bannedplayer.need_tip) {
        bannedplayer.need_tip = false;
        return {
mercury233's avatar
mercury233 committed
289
          "error": "${random_warn_part1}" + (bannedplayer.reasons.join('${random_ban_reason_separator}')) + "${random_warn_part2}"
mercury233's avatar
mercury233 committed
290 291 292 293 294 295 296 297
        };
      } else if (bannedplayer.count > 2) {
        bannedplayer.need_tip = true;
      }
    }
    max_player = type === 'T' ? 4 : 2;
    playerbanned = bannedplayer && bannedplayer.count > 3 && moment() < bannedplayer.time;
    result = _.find(ROOM_all, function(room) {
298
      return room && room.random_type !== '' && !room.started && ((type === '' && room.random_type !== 'T') || room.random_type === type) && room.get_playing_player().length < max_player && (settings.modules.random_duel.no_rematch_check || room.get_host() === null || room.get_host().ip !== ROOM_players_oppentlist[player_ip]) && (playerbanned === room.deprecated || type === 'T');
mercury233's avatar
mercury233 committed
299 300
    });
    if (result) {
mercury233's avatar
mercury233 committed
301
      result.welcome = '${random_duel_enter_room_waiting}';
mercury233's avatar
mercury233 committed
302
    } else if (get_memory_usage() < 90) {
mercury233's avatar
mercury233 committed
303 304 305 306 307
      type = type ? type : 'S';
      name = type + ',RANDOM#' + Math.floor(Math.random() * 100000);
      result = new Room(name);
      result.random_type = type;
      result.max_player = max_player;
mercury233's avatar
mercury233 committed
308
      result.welcome = '${random_duel_enter_room_new}';
mercury233's avatar
mercury233 committed
309
      result.deprecated = playerbanned;
mercury233's avatar
mercury233 committed
310 311
    } else {
      return null;
mercury233's avatar
mercury233 committed
312 313
    }
    if (result.random_type === 'M') {
mercury233's avatar
mercury233 committed
314
      result.welcome = result.welcome + '\n${random_duel_enter_room_match}';
mercury233's avatar
mercury233 committed
315 316 317 318
    }
    return result;
  };

mercury233's avatar
mercury233 committed
319
  ROOM_find_or_create_ai = function(name) {
320
    var ainame, namea, result, room, uname, windbot;
mercury233's avatar
mercury233 committed
321 322 323
    if (name === '') {
      name = 'AI';
    }
mercury233's avatar
mercury233 committed
324
    namea = name.split('#');
325
    uname = name.toUpperCase();
mercury233's avatar
mercury233 committed
326 327
    if (room = ROOM_find_by_name(name)) {
      return room;
328
    } else if (uname === 'AI') {
mercury233's avatar
mercury233 committed
329 330
      windbot = _.sample(settings.modules.windbots);
      name = 'AI#' + Math.floor(Math.random() * 100000);
mercury233's avatar
mercury233 committed
331 332
    } else if (namea.length > 1) {
      ainame = namea[namea.length - 1];
mercury233's avatar
mercury233 committed
333 334 335 336 337
      windbot = _.sample(_.filter(settings.modules.windbots, function(w) {
        return w.name === ainame || w.deck === ainame;
      }));
      if (!windbot) {
        return {
mercury233's avatar
mercury233 committed
338
          "error": "${windbot_deck_not_found}"
mercury233's avatar
mercury233 committed
339 340 341 342 343 344 345
        };
      }
      name = name + ',' + Math.floor(Math.random() * 100000);
    } else {
      windbot = _.sample(settings.modules.windbots);
      name = name + '#' + Math.floor(Math.random() * 100000);
    }
mercury233's avatar
mercury233 committed
346 347 348
    if (name.replace(/[^\x00-\xff]/g, "00").length > 20) {
      log.info("long ai name", name);
      return {
mercury233's avatar
mercury233 committed
349
        "error": "${windbot_name_too_long}"
mercury233's avatar
mercury233 committed
350 351
      };
    }
mercury233's avatar
mercury233 committed
352 353
    result = new Room(name);
    result.windbot = windbot;
mercury233's avatar
merge  
mercury233 committed
354
    result["private"] = true;
mercury233's avatar
mercury233 committed
355 356 357
    return result;
  };

mercury233's avatar
mercury233 committed
358 359 360
  ROOM_find_by_name = function(name) {
    var result;
    result = _.find(ROOM_all, function(room) {
361
      return room && room.name === name;
mercury233's avatar
mercury233 committed
362 363 364 365
    });
    return result;
  };

mercury233's avatar
mercury233 committed
366 367 368 369 370 371 372 373
  ROOM_find_by_title = function(title) {
    var result;
    result = _.find(ROOM_all, function(room) {
      return room && room.title === title;
    });
    return result;
  };

mercury233's avatar
mercury233 committed
374 375
  ROOM_find_by_port = function(port) {
    return _.find(ROOM_all, function(room) {
376
      return room && room.port === port;
mercury233's avatar
mercury233 committed
377 378 379 380 381 382 383 384 385 386 387 388 389
    });
  };

  ROOM_validate = function(name) {
    var client_name, client_name_and_pass, client_pass;
    client_name_and_pass = name.split('$', 2);
    client_name = client_name_and_pass[0];
    client_pass = client_name_and_pass[1];
    if (!client_pass) {
      return true;
    }
    return !_.find(ROOM_all, function(room) {
      var room_name, room_name_and_pass, room_pass;
390 391 392
      if (!room) {
        return false;
      }
mercury233's avatar
mercury233 committed
393 394 395 396 397 398 399
      room_name_and_pass = room.name.split('$', 2);
      room_name = room_name_and_pass[0];
      room_pass = room_name_and_pass[1];
      return client_name === room_name && client_pass !== room_pass;
    });
  };

mercury233's avatar
mercury233 committed
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416
  ROOM_unwelcome = function(room, bad_player, reason) {
    var j, len, player, ref;
    if (!room) {
      return;
    }
    ref = room.players;
    for (j = 0, len = ref.length; j < len; j++) {
      player = ref[j];
      if (player && player === bad_player) {
        ygopro.stoc_send_chat(player, "${unwelcome_warn_part1}" + reason + "${unwelcome_warn_part2}", ygopro.constants.COLORS.RED);
      } else if (player && player.pos !== 7 && player !== bad_player) {
        player.flee_free = true;
        ygopro.stoc_send_chat(player, "${unwelcome_tip_part1}" + reason + "${unwelcome_tip_part2}", ygopro.constants.COLORS.BABYBLUE);
      }
    }
  };

mercury233's avatar
mercury233 committed
417 418
  Room = (function() {
    function Room(name, hostinfo) {
mercury233's avatar
mercury233 committed
419
      var draw_count, lflist, param, rule, start_hand, start_lp, time_limit;
mercury233's avatar
mercury233 committed
420 421 422 423 424 425 426 427 428 429
      this.hostinfo = hostinfo;
      this.name = name;
      this.alive = true;
      this.players = [];
      this.player_datas = [];
      this.status = 'starting';
      this.started = false;
      this.established = false;
      this.watcher_buffers = [];
      this.recorder_buffers = [];
430
      this.cloud_replay_id = Math.floor(Math.random() * 100000000);
mercury233's avatar
mercury233 committed
431 432 433
      this.watchers = [];
      this.random_type = '';
      this.welcome = '';
mercury233's avatar
mercury233 committed
434
      this.scores = {};
435
      this.duel_count = 0;
nanahira's avatar
nanahira committed
436
      this.death = 0;
mercury233's avatar
mercury233 committed
437
      ROOM_all.push(this);
mercury233's avatar
fix  
mercury233 committed
438
      this.hostinfo || (this.hostinfo = JSON.parse(JSON.stringify(settings.hostinfo)));
439 440 441 442 443 444 445 446 447
      if (settings.lflist.length) {
        if (this.hostinfo.rule === 1 && this.hostinfo.lflist === 0) {
          this.hostinfo.lflist = _.findIndex(settings.lflist, function(list) {
            return list.tcg;
          });
        }
      } else {
        this.hostinfo.lflist = -1;
      }
mercury233's avatar
mercury233 committed
448
      this.hostinfo.replay_mode = settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe ? 1 : 0;
mercury233's avatar
mercury233 committed
449 450 451 452 453
      if (name.slice(0, 2) === 'M#') {
        this.hostinfo.mode = 1;
      } else if (name.slice(0, 2) === 'T#') {
        this.hostinfo.mode = 2;
        this.hostinfo.start_lp = 16000;
mercury233's avatar
mercury233 committed
454 455 456
      } else if (name.slice(0, 3) === 'AI#') {
        this.hostinfo.rule = 2;
        this.hostinfo.lflist = -1;
mercury233's avatar
mercury233 committed
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477
      } else if ((param = name.match(/^(\d)(\d)(T|F)(T|F)(T|F)(\d+),(\d+),(\d+)/i))) {
        this.hostinfo.rule = parseInt(param[1]);
        this.hostinfo.mode = parseInt(param[2]);
        this.hostinfo.enable_priority = param[3] === 'T';
        this.hostinfo.no_check_deck = param[4] === 'T';
        this.hostinfo.no_shuffle_deck = param[5] === 'T';
        this.hostinfo.start_lp = parseInt(param[6]);
        this.hostinfo.start_hand = parseInt(param[7]);
        this.hostinfo.draw_count = parseInt(param[8]);
      } else if ((param = name.match(/(.+)#/)) !== null) {
        rule = param[1].toUpperCase();
        if (rule.match(/(^|,|,)(M|MATCH)(,|,|$)/)) {
          this.hostinfo.mode = 1;
        }
        if (rule.match(/(^|,|,)(T|TAG)(,|,|$)/)) {
          this.hostinfo.mode = 2;
          this.hostinfo.start_lp = 16000;
        }
        if (rule.match(/(^|,|,)(TCGONLY|TO)(,|,|$)/)) {
          this.hostinfo.rule = 1;
          this.hostinfo.lflist = _.findIndex(settings.lflist, function(list) {
mercury233's avatar
mercury233 committed
478
            return list.tcg;
mercury233's avatar
mercury233 committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
          });
        }
        if (rule.match(/(^|,|,)(OCGONLY|OO)(,|,|$)/)) {
          this.hostinfo.rule = 0;
        }
        if (rule.match(/(^|,|,)(OT|TCG)(,|,|$)/)) {
          this.hostinfo.rule = 2;
        }
        if ((param = rule.match(/(^|,|,)LP(\d+)(,|,|$)/))) {
          start_lp = parseInt(param[2]);
          if (start_lp <= 0) {
            start_lp = 1;
          }
          if (start_lp >= 99999) {
            start_lp = 99999;
          }
          this.hostinfo.start_lp = start_lp;
        }
        if ((param = rule.match(/(^|,|,)(TIME|TM|TI)(\d+)(,|,|$)/))) {
          time_limit = parseInt(param[3]);
          if (time_limit < 0) {
            time_limit = 180;
          }
          if (time_limit >= 1 && time_limit <= 60) {
            time_limit = time_limit * 60;
          }
          if (time_limit >= 999) {
            time_limit = 999;
          }
          this.hostinfo.time_limit = time_limit;
        }
        if ((param = rule.match(/(^|,|,)(START|ST)(\d+)(,|,|$)/))) {
          start_hand = parseInt(param[3]);
          if (start_hand <= 0) {
            start_hand = 1;
          }
          if (start_hand >= 40) {
            start_hand = 40;
          }
          this.hostinfo.start_hand = start_hand;
        }
        if ((param = rule.match(/(^|,|,)(DRAW|DR)(\d+)(,|,|$)/))) {
          draw_count = parseInt(param[3]);
          if (draw_count >= 35) {
            draw_count = 35;
          }
          this.hostinfo.draw_count = draw_count;
        }
        if ((param = rule.match(/(^|,|,)(LFLIST|LF)(\d+)(,|,|$)/))) {
          lflist = parseInt(param[3]) - 1;
          this.hostinfo.lflist = lflist;
        }
        if (rule.match(/(^|,|,)(NOLFLIST|NF)(,|,|$)/)) {
          this.hostinfo.lflist = -1;
        }
        if (rule.match(/(^|,|,)(NOUNIQUE|NU)(,|,|$)/)) {
          this.hostinfo.rule = 3;
        }
        if (rule.match(/(^|,|,)(NOCHECK|NC)(,|,|$)/)) {
          this.hostinfo.no_check_deck = true;
        }
        if (rule.match(/(^|,|,)(NOSHUFFLE|NS)(,|,|$)/)) {
          this.hostinfo.no_shuffle_deck = true;
        }
        if (rule.match(/(^|,|,)(IGPRIORITY|PR)(,|,|$)/)) {
          this.hostinfo.enable_priority = true;
        }
      }
mercury233's avatar
mercury233 committed
547
      param = [0, this.hostinfo.lflist, this.hostinfo.rule, this.hostinfo.mode, (this.hostinfo.enable_priority ? 'T' : 'F'), (this.hostinfo.no_check_deck ? 'T' : 'F'), (this.hostinfo.no_shuffle_deck ? 'T' : 'F'), this.hostinfo.start_lp, this.hostinfo.start_hand, this.hostinfo.draw_count, this.hostinfo.time_limit, this.hostinfo.replay_mode];
mercury233's avatar
mercury233 committed
548 549
      try {
        this.process = spawn('./ygopro', param, {
mercury233's avatar
mercury233 committed
550
          cwd: 'ygopro'
mercury233's avatar
mercury233 committed
551
        });
mercury233's avatar
fix  
mercury233 committed
552 553 554
        this.process.on('error', (function(_this) {
          return function(err) {
            _.each(_this.players, function(player) {
mercury233's avatar
mercury233 committed
555
              return ygopro.stoc_die(player, "${create_room_failed}");
mercury233's avatar
fix  
mercury233 committed
556 557 558 559
            });
            _this["delete"]();
          };
        })(this));
mercury233's avatar
mercury233 committed
560 561 562 563 564 565 566 567 568 569 570 571
        this.process.on('exit', (function(_this) {
          return function(code) {
            if (!_this.disconnector) {
              _this.disconnector = 'server';
            }
            _this["delete"]();
          };
        })(this));
        this.process.stdout.setEncoding('utf8');
        this.process.stdout.once('data', (function(_this) {
          return function(data) {
            _this.established = true;
mercury233's avatar
mercury233 committed
572
            if (!_this.windbot && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
573 574 575 576 577
              roomlist.create(_this);
            }
            _this.port = parseInt(data);
            _.each(_this.players, function(player) {
              player.server.connect(_this.port, '127.0.0.1', function() {
mercury233's avatar
mercury233 committed
578
                var buffer, j, len, ref;
mercury233's avatar
mercury233 committed
579
                ref = player.pre_establish_buffers;
mercury233's avatar
mercury233 committed
580 581
                for (j = 0, len = ref.length; j < len; j++) {
                  buffer = ref[j];
mercury233's avatar
mercury233 committed
582 583 584 585 586 587 588
                  player.server.write(buffer);
                }
                player.established = true;
                player.pre_establish_buffers = [];
              });
            });
            if (_this.windbot) {
mercury233's avatar
mercury233 committed
589 590 591
              setTimeout(function() {
                return _this.add_windbot(_this.windbot);
              }, 200);
mercury233's avatar
mercury233 committed
592 593 594
            }
          };
        })(this));
mercury233's avatar
mercury233 committed
595 596
        this.process.stderr.on('data', (function(_this) {
          return function(data) {
mercury233's avatar
mercury233 committed
597 598 599 600
            data = "Debug: " + data;
            data = data.replace(/\n$/, "");
            log.info("YGOPRO " + data);
            ygopro.stoc_send_chat_to_room(_this, data, ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
601 602 603
            _this.has_ygopro_error = true;
          };
        })(this));
mercury233's avatar
mercury233 committed
604
      } catch (error1) {
mercury233's avatar
mercury233 committed
605
        this.error = "${create_room_failed}";
mercury233's avatar
mercury233 committed
606 607 608 609
      }
    }

    Room.prototype["delete"] = function() {
610
      var end_time, index, log_rep_id, name, player_ips, player_names, recorder_buffer, ref, replay_id, score, score_array;
mercury233's avatar
mercury233 committed
611 612 613
      if (this.deleted) {
        return;
      }
614 615 616 617 618 619 620 621 622 623
      score_array = [];
      ref = this.scores;
      for (name in ref) {
        score = ref[name];
        score_array.push({
          name: name,
          score: score
        });
      }
      if (score_array.length > 0 && settings.modules.arena_mode.enabled && this.arena) {
mercury233's avatar
merge  
mercury233 committed
624
        if (score_array.length === 2) {
625 626 627 628
          end_time = moment().format();
          if (!this.start_time) {
            this.start_time = end_time;
          }
mercury233's avatar
merge  
mercury233 committed
629 630 631
          request.post({
            url: settings.modules.arena_mode.post_score,
            form: {
mercury233's avatar
mercury233 committed
632
              accesskey: settings.modules.arena_mode.accesskey,
mercury233's avatar
merge  
mercury233 committed
633 634 635 636 637
              usernameA: score_array[0].name,
              usernameB: score_array[1].name,
              userscoreA: score_array[0].score,
              userscoreB: score_array[1].score,
              start: this.start_time,
638
              end: end_time,
mercury233's avatar
mercury233 committed
639
              arena: this.arena
mercury233's avatar
merge  
mercury233 committed
640 641 642 643
            }
          }, (function(_this) {
            return function(error, response, body) {
              if (error) {
mercury233's avatar
merge  
mercury233 committed
644
                log.warn('SCORE POST ERROR', error);
mercury233's avatar
mercury233 committed
645
              } else {
mercury233's avatar
fix  
mercury233 committed
646
                if (response.statusCode !== 204 && response.statusCode !== 200) {
mercury233's avatar
merge  
mercury233 committed
647 648
                  log.warn('SCORE POST FAIL', response.statusCode, response.statusMessage, _this.name, body);
                }
mercury233's avatar
mercury233 committed
649
              }
mercury233's avatar
merge  
mercury233 committed
650 651 652
            };
          })(this));
        }
mercury233's avatar
mercury233 committed
653
      }
mercury233's avatar
mercury233 committed
654
      if (this.player_datas.length && settings.modules.cloud_replay.enabled) {
655
        replay_id = this.cloud_replay_id;
mercury233's avatar
mercury233 committed
656 657 658
        if (this.has_ygopro_error) {
          log_rep_id = true;
        }
mercury233's avatar
mercury233 committed
659 660 661 662 663 664 665
        player_names = this.player_datas[0].name + (this.player_datas[2] ? "+" + this.player_datas[2].name : "") + " VS " + (this.player_datas[1] ? this.player_datas[1].name : "AI") + (this.player_datas[3] ? "+" + this.player_datas[3].name : "");
        player_ips = [];
        _.each(this.player_datas, function(player) {
          player_ips.push(player.ip);
        });
        recorder_buffer = Buffer.concat(this.recorder_buffers);
        zlib.deflate(recorder_buffer, function(err, replay_buffer) {
666
          var date_time, recorded_ip;
mercury233's avatar
mercury233 committed
667 668 669
          replay_buffer = replay_buffer.toString('binary');
          date_time = moment().format('YYYY-MM-DD HH:mm:ss');
          redisdb.hmset("replay:" + replay_id, "replay_id", replay_id, "replay_buffer", replay_buffer, "player_names", player_names, "date_time", date_time);
mercury233's avatar
mercury233 committed
670 671 672
          if (!log_rep_id) {
            redisdb.expire("replay:" + replay_id, 60 * 60 * 24);
          }
mercury233's avatar
mercury233 committed
673 674 675 676 677 678 679 680
          recorded_ip = [];
          _.each(player_ips, function(player_ip) {
            if (_.contains(recorded_ip, player_ip)) {
              return;
            }
            recorded_ip.push(player_ip);
            redisdb.lpush(player_ip + ":replays", replay_id);
          });
mercury233's avatar
mercury233 committed
681
          if (log_rep_id) {
mercury233's avatar
mercury233 committed
682 683
            log.info("error replay: R#" + replay_id);
          }
mercury233's avatar
mercury233 committed
684 685 686 687 688 689
        });
      }
      this.watcher_buffers = [];
      this.recorder_buffers = [];
      this.players = [];
      if (this.watcher) {
mercury233's avatar
mercury233 committed
690
        this.watcher.destroy();
mercury233's avatar
mercury233 committed
691
      }
mercury233's avatar
fix  
mercury233 committed
692 693 694
      if (this.recorder) {
        this.recorder.destroy();
      }
mercury233's avatar
mercury233 committed
695 696 697
      this.deleted = true;
      index = _.indexOf(ROOM_all, this);
      if (index !== -1) {
698
        ROOM_all[index] = null;
mercury233's avatar
mercury233 committed
699
      }
mercury233's avatar
mercury233 committed
700
      if (!this.windbot && this.established && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
701
        roomlist["delete"](this);
mercury233's avatar
mercury233 committed
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726
      }
    };

    Room.prototype.get_playing_player = function() {
      var playing_player;
      playing_player = [];
      _.each(this.players, function(player) {
        if (player.pos < 4) {
          playing_player.push(player);
        }
      });
      return playing_player;
    };

    Room.prototype.get_host = function() {
      var host_player;
      host_player = null;
      _.each(this.players, function(player) {
        if (player.is_host) {
          host_player = player;
        }
      });
      return host_player;
    };

mercury233's avatar
mercury233 committed
727 728 729
    Room.prototype.add_windbot = function(botdata) {
      this.windbot = botdata;
      request({
mercury233's avatar
mercury233 committed
730
        url: "http://127.0.0.1:" + settings.modules.windbot.port + "/?name=" + (encodeURIComponent(botdata.name)) + "&deck=" + (encodeURIComponent(botdata.deck)) + "&host=127.0.0.1&port=" + settings.port + "&dialog=" + (encodeURIComponent(botdata.dialog)) + "&version=" + settings.version + "&password=" + (encodeURIComponent(this.name))
mercury233's avatar
mercury233 committed
731 732 733
      }, (function(_this) {
        return function(error, response, body) {
          if (error) {
mercury233's avatar
merge  
mercury233 committed
734
            log.warn('windbot add error', error, _this.name);
mercury233's avatar
mercury233 committed
735
            ygopro.stoc_send_chat_to_room(_this, "${add_windbot_failed}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
736 737 738 739 740
          }
        };
      })(this));
    };

mercury233's avatar
mercury233 committed
741
    Room.prototype.connect = function(client) {
mercury233's avatar
mercury233 committed
742
      var host_player;
mercury233's avatar
mercury233 committed
743 744
      this.players.push(client);
      if (this.random_type) {
mercury233's avatar
mercury233 committed
745
        client.abuse_count = 0;
mercury233's avatar
mercury233 committed
746 747
        host_player = this.get_host();
        if (host_player && (host_player !== client)) {
mercury233's avatar
mercury233 committed
748 749
          ROOM_players_oppentlist[host_player.ip] = client.ip;
          ROOM_players_oppentlist[client.ip] = host_player.ip;
mercury233's avatar
mercury233 committed
750
        } else {
mercury233's avatar
mercury233 committed
751
          ROOM_players_oppentlist[client.ip] = null;
mercury233's avatar
mercury233 committed
752 753 754
        }
      }
      if (this.established) {
mercury233's avatar
mercury233 committed
755
        if (!this.windbot && !this.started && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
756 757 758
          roomlist.update(this);
        }
        client.server.connect(this.port, '127.0.0.1', function() {
mercury233's avatar
mercury233 committed
759
          var buffer, j, len, ref;
mercury233's avatar
mercury233 committed
760
          ref = client.pre_establish_buffers;
mercury233's avatar
mercury233 committed
761 762
          for (j = 0, len = ref.length; j < len; j++) {
            buffer = ref[j];
mercury233's avatar
mercury233 committed
763 764 765 766 767 768 769 770 771
            client.server.write(buffer);
          }
          client.established = true;
          client.pre_establish_buffers = [];
        });
      }
    };

    Room.prototype.disconnect = function(client, error) {
772
      var index, j, len, player, ref;
mercury233's avatar
mercury233 committed
773
      if (client.is_post_watcher) {
mercury233's avatar
mercury233 committed
774
        ygopro.stoc_send_chat_to_room(this, (client.name + " ${quit_watch}") + (error ? ": " + error : ''));
mercury233's avatar
mercury233 committed
775 776 777 778 779
        index = _.indexOf(this.watchers, client);
        if (index !== -1) {
          this.watchers.splice(index, 1);
        }
      } else {
780 781 782 783 784 785 786 787 788 789
        if (this.arena === "athletic" && !this.started && this.players.length === 2) {
          ref = this.players;
          for (j = 0, len = ref.length; j < len; j++) {
            player = ref[j];
            if (player.pos !== 7) {
              this.scores[player.name] = 0;
            }
          }
          this.scores[client.name] = -9;
        }
mercury233's avatar
mercury233 committed
790 791 792 793
        index = _.indexOf(this.players, client);
        if (index !== -1) {
          this.players.splice(index, 1);
        }
mercury233's avatar
mercury233 committed
794 795
        if (this.started && this.disconnector !== 'server' && (client.pos < 4 || client.is_host)) {
          this.finished = true;
mercury233's avatar
mercury233 committed
796
          this.scores[client.name] = -9;
mercury233's avatar
mercury233 committed
797
          if (this.random_type && !client.flee_free) {
mercury233's avatar
mercury233 committed
798
            ROOM_ban_player(client.name, client.ip, "${random_ban_reason_flee}");
mercury233's avatar
mercury233 committed
799
          }
mercury233's avatar
mercury233 committed
800
        }
mercury233's avatar
mercury233 committed
801
        if (this.players.length && !(this.windbot && client.is_host)) {
mercury233's avatar
mercury233 committed
802
          ygopro.stoc_send_chat_to_room(this, (client.name + " ${left_game}") + (error ? ": " + error : ''));
mercury233's avatar
mercury233 committed
803
          if (!this.windbot && !this.started && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
804 805 806 807 808 809 810 811 812 813 814 815 816
            roomlist.update(this);
          }
        } else {
          this.process.kill();
          this["delete"]();
        }
      }
    };

    return Room;

  })();

神楽坂玲奈's avatar
神楽坂玲奈 committed
817
  net.createServer(function(client) {
mercury233's avatar
mercury233 committed
818 819 820
    var connect_count, server;
    client.ip = client.remoteAddress;
    connect_count = ROOM_connected_ip[client.ip] || 0;
821
    if (!settings.modules.test_mode.no_connect_count_limit && client.ip !== '::ffff:127.0.0.1') {
mercury233's avatar
mercury233 committed
822 823 824
      connect_count++;
    }
    ROOM_connected_ip[client.ip] = connect_count;
神楽坂玲奈's avatar
神楽坂玲奈 committed
825 826
    server = new net.Socket();
    client.server = server;
mercury233's avatar
mercury233 committed
827
    client.setTimeout(2000);
828
    client.on('close', function(had_error) {
mercury233's avatar
mercury233 committed
829
      var room;
830
      room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
831 832 833 834 835
      connect_count = ROOM_connected_ip[client.ip];
      if (connect_count > 0) {
        connect_count--;
      }
      ROOM_connected_ip[client.ip] = connect_count;
836
      if (!client.closed) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
837
        client.closed = true;
838 839
        if (room) {
          room.disconnect(client);
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
840
        }
mercury233's avatar
mercury233 committed
841
      }
mercury233's avatar
mercury233 committed
842
      server.destroy();
mercury233's avatar
mercury233 committed
843
    });
844
    client.on('error', function(error) {
mercury233's avatar
mercury233 committed
845
      var room;
846
      room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
847 848 849 850 851
      connect_count = ROOM_connected_ip[client.ip];
      if (connect_count > 0) {
        connect_count--;
      }
      ROOM_connected_ip[client.ip] = connect_count;
852 853
      if (!client.closed) {
        client.closed = error;
854 855
        if (room) {
          room.disconnect(client, error);
856
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
857
      }
mercury233's avatar
mercury233 committed
858
      server.destroy();
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
859
    });
860
    client.on('timeout', function() {
mercury233's avatar
mercury233 committed
861
      server.destroy();
862
    });
863
    server.on('close', function(had_error) {
864 865 866 867 868
      var room;
      room = ROOM_all[client.rid];
      if (room) {
        room.disconnector = 'server';
      }
869 870
      if (!server.closed) {
        server.closed = true;
mercury233's avatar
mercury233 committed
871
      }
872
      if (!client.closed) {
mercury233's avatar
mercury233 committed
873
        ygopro.stoc_send_chat(client, "${server_closed}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
874
        client.destroy();
mercury233's avatar
mercury233 committed
875 876
      }
    });
877
    server.on('error', function(error) {
878 879 880 881 882
      var room;
      room = ROOM_all[client.rid];
      if (room) {
        room.disconnector = 'server';
      }
883 884
      server.closed = error;
      if (!client.closed) {
mercury233's avatar
mercury233 committed
885
        ygopro.stoc_send_chat(client, "${server_error}: " + error, ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
886
        client.destroy();
mercury233's avatar
mercury233 committed
887 888
      }
    });
mercury233's avatar
mercury233 committed
889
    if (ROOM_bad_ip[client.ip] > 5 || ROOM_connected_ip[client.ip] > 10) {
mercury233's avatar
mercury233 committed
890 891
      log.info('BAD IP', client.ip);
      client.destroy();
mercury233's avatar
mercury233 committed
892 893
      return;
    }
mercury233's avatar
mercury233 committed
894
    if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
895 896 897
      client.open_cloud_replay = function(err, replay) {
        var buffer;
        if (err || !replay) {
mercury233's avatar
mercury233 committed
898
          ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
899
          return;
mercury233's avatar
mercury233 committed
900
        }
mercury233's avatar
mercury233 committed
901 902
        redisdb.expire("replay:" + replay.replay_id, 60 * 60 * 48);
        buffer = new Buffer(replay.replay_buffer, 'binary');
mercury233's avatar
mercury233 committed
903 904
        zlib.unzip(buffer, function(err, replay_buffer) {
          if (err) {
mercury233's avatar
mercury233 committed
905
            log.info("cloud replay unzip error: " + err);
mercury233's avatar
mercury233 committed
906
            ygopro.stoc_send_chat(client, "${cloud_replay_error}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
907
            client.destroy();
mercury233's avatar
mercury233 committed
908 909
            return;
          }
mercury233's avatar
mercury233 committed
910
          ygopro.stoc_send_chat(client, "${cloud_replay_playing} R#" + replay.replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
911
          client.write(replay_buffer, function() {
mercury233's avatar
fix  
mercury233 committed
912
            client.destroy();
mercury233's avatar
mercury233 committed
913
          });
mercury233's avatar
mercury233 committed
914
        });
mercury233's avatar
mercury233 committed
915 916
      };
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
917
    client.pre_establish_buffers = new Array();
mercury233's avatar
mercury233 committed
918
    client.on('data', function(ctos_buffer) {
919
      var b, bad_ip_count, buffer, cancel, ctos_message_length, ctos_proto, datas, info, j, k, len, len1, looplimit, room, struct;
920
      if (client.is_post_watcher) {
921 922
        room = ROOM_all[client.rid];
        if (room) {
mercury233's avatar
mercury233 committed
923
          room.watcher.write(ctos_buffer);
924
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
925
      } else {
mercury233's avatar
mercury233 committed
926 927
        ctos_message_length = 0;
        ctos_proto = 0;
928
        datas = [];
mercury233's avatar
mercury233 committed
929
        looplimit = 0;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
930
        while (true) {
931 932
          if (ctos_message_length === 0) {
            if (ctos_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
933
              ctos_message_length = ctos_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
934
            } else {
mercury233's avatar
mercury233 committed
935 936 937
              if (ctos_buffer.length !== 0) {
                log.warn("bad ctos_buffer length", client.ip);
              }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
938 939
              break;
            }
940 941
          } else if (ctos_proto === 0) {
            if (ctos_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
942
              ctos_proto = ctos_buffer.readUInt8(2);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
943
            } else {
mercury233's avatar
mercury233 committed
944
              log.warn("bad ctos_proto length", client.ip);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
945
              break;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
946 947
            }
          } else {
948
            if (ctos_buffer.length >= 2 + ctos_message_length) {
949
              cancel = false;
950 951
              if (ygopro.ctos_follows[ctos_proto]) {
                b = ctos_buffer.slice(3, ctos_message_length - 1 + 3);
952
                info = null;
953
                if (struct = ygopro.structs[ygopro.proto_structs.CTOS[ygopro.constants.CTOS[ctos_proto]]]) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
954
                  struct._setBuff(b);
955 956 957 958
                  info = _.clone(struct.fields);
                }
                if (ygopro.ctos_follows[ctos_proto].synchronous) {
                  cancel = ygopro.ctos_follows[ctos_proto].callback(b, info, client, server);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
959
                } else {
960
                  ygopro.ctos_follows[ctos_proto].callback(b, info, client, server);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
961 962
                }
              }
963 964 965
              if (!cancel) {
                datas.push(ctos_buffer.slice(0, 2 + ctos_message_length));
              }
966 967
              ctos_buffer = ctos_buffer.slice(2 + ctos_message_length);
              ctos_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
968
              ctos_proto = 0;
mercury233's avatar
fix  
mercury233 committed
969 970 971 972
            } else {
              if (ctos_message_length !== 17735) {
                log.warn("bad ctos_message length", client.ip, ctos_buffer.length, ctos_message_length, ctos_proto);
              }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
973 974
              break;
            }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
975
          }
mercury233's avatar
mercury233 committed
976
          looplimit++;
mercury233's avatar
mercury233 committed
977 978 979
          if (looplimit > 800 || ROOM_bad_ip[client.ip] > 5) {
            log.info("error ctos", client.name, client.ip);
            bad_ip_count = ROOM_bad_ip[client.ip];
mercury233's avatar
mercury233 committed
980
            if (bad_ip_count) {
mercury233's avatar
mercury233 committed
981
              ROOM_bad_ip[client.ip] = bad_ip_count + 1;
mercury233's avatar
mercury233 committed
982
            } else {
mercury233's avatar
mercury233 committed
983
              ROOM_bad_ip[client.ip] = 1;
mercury233's avatar
mercury233 committed
984
            }
mercury233's avatar
mercury233 committed
985
            client.destroy();
mercury233's avatar
mercury233 committed
986 987
            break;
          }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
988
        }
989
        if (client.established) {
mercury233's avatar
mercury233 committed
990 991
          for (j = 0, len = datas.length; j < len; j++) {
            buffer = datas[j];
992 993 994
            server.write(buffer);
          }
        } else {
mercury233's avatar
mercury233 committed
995 996
          for (k = 0, len1 = datas.length; k < len1; k++) {
            buffer = datas[k];
997 998 999
            client.pre_establish_buffers.push(buffer);
          }
        }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1000 1001
      }
    });
mercury233's avatar
mercury233 committed
1002
    server.on('data', function(stoc_buffer) {
1003
      var b, buffer, cancel, datas, info, j, len, looplimit, stanzas, stoc_message_length, stoc_proto, struct;
mercury233's avatar
mercury233 committed
1004 1005
      stoc_message_length = 0;
      stoc_proto = 0;
1006
      datas = [];
mercury233's avatar
mercury233 committed
1007
      looplimit = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
1008
      while (true) {
1009 1010
        if (stoc_message_length === 0) {
          if (stoc_buffer.length >= 2) {
mercury233's avatar
test3  
mercury233 committed
1011
            stoc_message_length = stoc_buffer.readUInt16LE(0);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1012
          } else {
mercury233's avatar
mercury233 committed
1013 1014 1015
            if (stoc_buffer.length !== 0) {
              log.warn("bad stoc_buffer length", client.ip);
            }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1016 1017
            break;
          }
1018 1019
        } else if (stoc_proto === 0) {
          if (stoc_buffer.length >= 3) {
mercury233's avatar
test3  
mercury233 committed
1020
            stoc_proto = stoc_buffer.readUInt8(2);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1021
          } else {
mercury233's avatar
mercury233 committed
1022
            log.warn("bad stoc_proto length", client.ip);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1023 1024 1025
            break;
          }
        } else {
1026
          if (stoc_buffer.length >= 2 + stoc_message_length) {
1027
            cancel = false;
1028 1029 1030
            stanzas = stoc_proto;
            if (ygopro.stoc_follows[stoc_proto]) {
              b = stoc_buffer.slice(3, stoc_message_length - 1 + 3);
1031
              info = null;
1032
              if (struct = ygopro.structs[ygopro.proto_structs.STOC[ygopro.constants.STOC[stoc_proto]]]) {
神楽坂玲奈's avatar
神楽坂玲奈 committed
1033
                struct._setBuff(b);
1034 1035 1036 1037
                info = _.clone(struct.fields);
              }
              if (ygopro.stoc_follows[stoc_proto].synchronous) {
                cancel = ygopro.stoc_follows[stoc_proto].callback(b, info, client, server);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1038
              } else {
1039
                ygopro.stoc_follows[stoc_proto].callback(b, info, client, server);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1040 1041
              }
            }
1042 1043 1044
            if (!cancel) {
              datas.push(stoc_buffer.slice(0, 2 + stoc_message_length));
            }
1045 1046
            stoc_buffer = stoc_buffer.slice(2 + stoc_message_length);
            stoc_message_length = 0;
mercury233's avatar
test3  
mercury233 committed
1047
            stoc_proto = 0;
神楽坂玲奈's avatar
神楽坂玲奈 committed
1048
          } else {
mercury233's avatar
mercury233 committed
1049
            log.warn("bad stoc_message length", client.ip);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1050 1051 1052
            break;
          }
        }
mercury233's avatar
mercury233 committed
1053 1054
        looplimit++;
        if (looplimit > 800) {
mercury233's avatar
fix  
mercury233 committed
1055
          log.info("error stoc", client.name);
mercury233's avatar
mercury233 committed
1056
          server.destroy();
mercury233's avatar
mercury233 committed
1057 1058
          break;
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
1059
      }
mercury233's avatar
mercury233 committed
1060 1061
      for (j = 0, len = datas.length; j < len; j++) {
        buffer = datas[j];
1062 1063
        client.write(buffer);
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1064
    });
神楽坂玲奈's avatar
神楽坂玲奈 committed
1065
  }).listen(settings.port, function() {
mercury233's avatar
mercury233 committed
1066
    log.info("server started", settings.port);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1067
  });
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1068

神楽坂玲奈's avatar
神楽坂玲奈 committed
1069
  ygopro.ctos_follow('PLAYER_INFO', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1070
    var geo, lang, name, struct;
1071
    name = info.name.split("$")[0];
mercury233's avatar
mercury233 committed
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083
    if (_.any(settings.ban.illegal_id, function(badid) {
      var matchs, regexp;
      regexp = new RegExp(badid, 'i');
      matchs = name.match(regexp);
      if (matchs) {
        name = matchs[1];
        return true;
      }
      return false;
    }, name)) {
      client.rag = true;
    }
1084 1085 1086 1087 1088
    struct = ygopro.structs["CTOS_PlayerInfo"];
    struct._setBuff(buffer);
    struct.set("name", name);
    buffer = struct.buffer;
    client.name = name;
mercury233's avatar
mercury233 committed
1089
    if (!settings.modules.i18n.auto_pick || client.ip === "::ffff:127.0.0.1") {
mercury233's avatar
mercury233 committed
1090 1091 1092 1093
      client.lang = settings.modules.i18n["default"];
    } else {
      geo = geoip.lookup(client.ip);
      if (!geo) {
mercury233's avatar
mercury233 committed
1094
        log.warn("fail to locate ip", client.name, client.ip);
mercury233's avatar
mercury233 committed
1095 1096 1097 1098 1099 1100 1101 1102
        client.lang = settings.modules.i18n.fallback;
      } else {
        if (lang = settings.modules.i18n.map[geo.country]) {
          client.lang = lang;
        } else {
          client.lang = settings.modules.i18n.fallback;
        }
      }
mercury233's avatar
mercury233 committed
1103
    }
1104
    return false;
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1105 1106
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
1107
  ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1108
    var check, decrypted_buffer, finish, i, id, j, k, len, len1, name, ref, ref1, replay_id, room, secret;
mercury233's avatar
mercury233 committed
1109
    info.pass = info.pass.trim();
mercury233's avatar
fix  
mercury233 committed
1110
    if (settings.modules.stop) {
mercury233's avatar
mercury233 committed
1111
      ygopro.stoc_die(client, settings.modules.stop);
mercury233's avatar
mercury233 committed
1112
    } else if (info.pass.toUpperCase() === "R" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
1113
      ygopro.stoc_send_chat(client, "${cloud_replay_hint}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1114
      redisdb.lrange(client.ip + ":replays", 0, 2, function(err, result) {
mercury233's avatar
mercury233 committed
1115 1116 1117
        _.each(result, function(replay_id, id) {
          redisdb.hgetall("replay:" + replay_id, function(err, replay) {
            if (err || !replay) {
mercury233's avatar
mercury233 committed
1118 1119 1120
              if (err) {
                log.info("cloud replay getall error: " + err);
              }
mercury233's avatar
mercury233 committed
1121 1122 1123
              return;
            }
            ygopro.stoc_send_chat(client, "<" + (id - 0 + 1) + "> R#" + replay_id + " " + replay.player_names + " " + replay.date_time, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1124
          });
mercury233's avatar
mercury233 committed
1125 1126 1127 1128 1129
        });
      });
      setTimeout((function() {
        ygopro.stoc_send(client, 'ERROR_MSG', {
          msg: 1,
mercury233's avatar
mercury233 committed
1130
          code: 9
mercury233's avatar
mercury233 committed
1131
        });
mercury233's avatar
mercury233 committed
1132
        client.destroy();
mercury233's avatar
mercury233 committed
1133
      }), 500);
mercury233's avatar
mercury233 committed
1134
    } else if (info.pass.slice(0, 2).toUpperCase() === "R#" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
1135
      replay_id = info.pass.split("#")[1];
mercury233's avatar
fix  
mercury233 committed
1136
      if (replay_id > 0 && replay_id <= 9) {
mercury233's avatar
mercury233 committed
1137
        redisdb.lindex(client.ip + ":replays", replay_id - 1, function(err, replay_id) {
mercury233's avatar
mercury233 committed
1138
          if (err || !replay_id) {
mercury233's avatar
mercury233 committed
1139 1140 1141
            if (err) {
              log.info("cloud replay replayid error: " + err);
            }
mercury233's avatar
mercury233 committed
1142
            ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
1143 1144 1145 1146
            return;
          }
          redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
        });
mercury233's avatar
mercury233 committed
1147 1148 1149
      } else if (replay_id) {
        redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
      } else {
mercury233's avatar
mercury233 committed
1150
        ygopro.stoc_die(client, "${cloud_replay_no}");
mercury233's avatar
mercury233 committed
1151
      }
mercury233's avatar
mercury233 committed
1152
    } else if (info.pass.toUpperCase() === "W" && settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
1153 1154
      replay_id = Cloud_replay_ids[Math.floor(Math.random() * Cloud_replay_ids.length)];
      redisdb.hgetall("replay:" + replay_id, client.open_cloud_replay);
mercury233's avatar
mercury233 committed
1155
    } else if (info.version !== settings.version) {
mercury233's avatar
mercury233 committed
1156
      ygopro.stoc_send_chat(client, settings.modules.update, ygopro.constants.COLORS.RED);
mercury233's avatar
fix  
mercury233 committed
1157 1158 1159 1160
      ygopro.stoc_send(client, 'ERROR_MSG', {
        msg: 4,
        code: settings.version
      });
mercury233's avatar
mercury233 committed
1161
      client.destroy();
mercury233's avatar
mercury233 committed
1162
    } else if (!info.pass.length && !settings.modules.random_duel.enabled && !settings.modules.windbot.enabled) {
mercury233's avatar
mercury233 committed
1163
      ygopro.stoc_die(client, "${blank_room_name}");
mercury233's avatar
fix  
mercury233 committed
1164
    } else if (info.pass.length && settings.modules.mycard.enabled && info.pass.slice(0, 3) !== 'AI#') {
mercury233's avatar
mercury233 committed
1165
      ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1166
      if (info.pass.length <= 8) {
mercury233's avatar
mercury233 committed
1167
        ygopro.stoc_die(client, '${invalid_password_length}');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1168 1169 1170
        return;
      }
      buffer = new Buffer(info.pass.slice(0, 8), 'base64');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1171
      if (buffer.length !== 6) {
mercury233's avatar
mercury233 committed
1172
        ygopro.stoc_die(client, '${invalid_password_payload}');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1173 1174
        return;
      }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1175
      check = function(buf) {
mercury233's avatar
mercury233 committed
1176
        var checksum, i, j, ref;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1177
        checksum = 0;
mercury233's avatar
mercury233 committed
1178
        for (i = j = 0, ref = buf.length; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1179
          checksum += buf.readUInt8(i);
1180
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1181 1182 1183
        return (checksum & 0xFF) === 0;
      };
      finish = function(buffer) {
mercury233's avatar
mercury233 committed
1184
        var action, j, len, name, opt1, opt2, opt3, options, ref, room, title;
1185 1186
        action = buffer.readUInt8(1) >> 4;
        if (buffer !== decrypted_buffer && (action === 1 || action === 2 || action === 4)) {
mercury233's avatar
mercury233 committed
1187
          ygopro.stoc_die(client, '${invalid_password_unauthorized}');
1188 1189 1190 1191 1192 1193
          return;
        }
        switch (action) {
          case 1:
          case 2:
            name = crypto.createHash('md5').update(info.pass + client.name).digest('base64').slice(0, 10).replace('+', '-').replace('/', '_');
mercury233's avatar
mercury233 committed
1194
            if (ROOM_find_by_name(name)) {
mercury233's avatar
mercury233 committed
1195
              ygopro.stoc_die(client, '${invalid_password_existed}');
1196 1197 1198
              return;
            }
            opt1 = buffer.readUInt8(2);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1199
            opt2 = buffer.readUInt16LE(3);
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212
            opt3 = buffer.readUInt8(5);
            options = {
              lflist: 0,
              time_limit: 180,
              rule: (opt1 >> 5) & 3,
              mode: (opt1 >> 3) & 3,
              enable_priority: !!((opt1 >> 2) & 1),
              no_check_deck: !!((opt1 >> 1) & 1),
              no_shuffle_deck: !!(opt1 & 1),
              start_lp: opt2,
              start_hand: opt3 >> 4,
              draw_count: opt3 & 0xF
            };
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1213 1214
            options.lflist = _.findIndex(settings.lflist, function(list) {
              return ((options.rule === 1) === list.tcg) && list.date.isBefore();
神楽坂玲奈's avatar
神楽坂玲奈 committed
1215
            });
1216
            room = new Room(name, options);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1217
            room.title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
神楽坂玲奈's avatar
神楽坂玲奈 committed
1218
            room["private"] = action === 2;
1219 1220 1221
            break;
          case 3:
            name = info.pass.slice(8);
mercury233's avatar
mercury233 committed
1222
            room = ROOM_find_by_name(name);
1223
            if (!room) {
mercury233's avatar
mercury233 committed
1224
              ygopro.stoc_die(client, '${invalid_password_not_found}');
1225 1226 1227 1228
              return;
            }
            break;
          case 4:
mercury233's avatar
mercury233 committed
1229
            room = ROOM_find_or_create_by_name('M#' + info.pass.slice(8));
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1230
            room["private"] = true;
1231
            room.arena = settings.modules.arena_mode.mode;
1232 1233 1234 1235
            if (room.arena === "athletic") {
              room.max_player = 2;
              room.welcome = "${athletic_arena_tip}";
            }
1236
            break;
mercury233's avatar
mercury233 committed
1237 1238 1239 1240 1241 1242 1243 1244
          case 5:
            title = info.pass.slice(8).replace(String.fromCharCode(0xFEFF), ' ');
            room = ROOM_find_by_title(title);
            if (!room) {
              ygopro.stoc_die(client, '${invalid_password_not_found}');
              return;
            }
            break;
1245
          default:
mercury233's avatar
mercury233 committed
1246
            ygopro.stoc_die(client, '${invalid_password_action}');
1247 1248
            return;
        }
mercury233's avatar
mercury233 committed
1249
        if (!room) {
mercury233's avatar
mercury233 committed
1250
          ygopro.stoc_die(client, "${server_full}");
mercury233's avatar
mercury233 committed
1251
        } else if (room.error) {
mercury233's avatar
mercury233 committed
1252
          ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268
        } else if (room.started) {
          if (settings.modules.cloud_replay.enable_halfway_watch) {
            client.setTimeout(300000);
            client.rid = _.indexOf(ROOM_all, room);
            client.is_post_watcher = true;
            ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
            room.watchers.push(client);
            ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
            ref = room.watcher_buffers;
            for (j = 0, len = ref.length; j < len; j++) {
              buffer = ref[j];
              client.write(buffer);
            }
          } else {
            ygopro.stoc_die(client, "${watch_denied}");
          }
mercury233's avatar
mercury233 committed
1269
        } else {
mercury233's avatar
mercury233 committed
1270
          client.setTimeout(300000);
1271 1272
          client.rid = _.indexOf(ROOM_all, room);
          room.connect(client);
mercury233's avatar
mercury233 committed
1273
        }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1274 1275 1276 1277 1278
      };
      if (id = users_cache[client.name]) {
        secret = id % 65535 + 1;
        decrypted_buffer = new Buffer(6);
        ref = [0, 2, 4];
mercury233's avatar
mercury233 committed
1279 1280
        for (j = 0, len = ref.length; j < len; j++) {
          i = ref[j];
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1281 1282 1283 1284 1285 1286 1287
          decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
        }
        if (check(decrypted_buffer)) {
          return finish(decrypted_buffer);
        }
      }
      request({
mercury233's avatar
mercury233 committed
1288
        baseUrl: settings.modules.mycard.auth_base_url,
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1289 1290
        url: '/users/' + encodeURIComponent(client.name) + '.json',
        qs: {
mercury233's avatar
fix  
mercury233 committed
1291
          api_key: settings.modules.mycard.auth_key,
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1292 1293 1294 1295 1296
          api_username: client.name,
          skip_track_visit: true
        },
        json: true
      }, function(error, response, body) {
mercury233's avatar
mercury233 committed
1297
        var k, len1, ref1;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1298
        if (body && body.user) {
mercury233's avatar
fix  
mercury233 committed
1299
          users_cache[client.name] = body.user.id;
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1300 1301 1302
          secret = body.user.id % 65535 + 1;
          decrypted_buffer = new Buffer(6);
          ref1 = [0, 2, 4];
mercury233's avatar
mercury233 committed
1303 1304
          for (k = 0, len1 = ref1.length; k < len1; k++) {
            i = ref1[k];
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1305 1306 1307 1308 1309 1310 1311
            decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
          }
          if (check(decrypted_buffer)) {
            buffer = decrypted_buffer;
          }
        }
        if (!check(buffer)) {
mercury233's avatar
mercury233 committed
1312
          ygopro.stoc_die(client, '${invalid_password_checksum}');
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1313 1314 1315
          return;
        }
        return finish(buffer);
1316
      });
mercury233's avatar
mercury233 committed
1317
    } else if (!client.name || client.name === "") {
mercury233's avatar
mercury233 committed
1318
      ygopro.stoc_die(client, "${bad_user_name}");
mercury233's avatar
mercury233 committed
1319 1320
    } else if (ROOM_connected_ip[client.ip] > 5) {
      log.warn("MULTI LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
1321
      ygopro.stoc_die(client, "${too_much_connection}" + client.ip);
mercury233's avatar
mercury233 committed
1322
    } else if (_.indexOf(settings.ban.banned_user, client.name) > -1) {
mercury233's avatar
mercury233 committed
1323 1324
      settings.ban.banned_ip.push(client.ip);
      log.warn("BANNED USER LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
1325
      ygopro.stoc_die(client, "${banned_user_login}");
mercury233's avatar
mercury233 committed
1326 1327
    } else if (_.indexOf(settings.ban.banned_ip, client.ip) > -1) {
      log.warn("BANNED IP LOGIN", client.name, client.ip);
mercury233's avatar
mercury233 committed
1328
      ygopro.stoc_die(client, "${banned_ip_login}");
mercury233's avatar
mercury233 committed
1329 1330
    } else if (_.any(settings.ban.badword_level3, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1331
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1332 1333
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
1334
      log.warn("BAD NAME LEVEL 3", client.name, client.ip);
mercury233's avatar
mercury233 committed
1335
      ygopro.stoc_die(client, "${bad_name_level3}");
mercury233's avatar
mercury233 committed
1336 1337
    } else if (_.any(settings.ban.badword_level2, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1338
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1339 1340
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
1341
      log.warn("BAD NAME LEVEL 2", client.name, client.ip);
mercury233's avatar
mercury233 committed
1342
      ygopro.stoc_die(client, "${bad_name_level2}");
mercury233's avatar
mercury233 committed
1343 1344
    } else if (_.any(settings.ban.badword_level1, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
1345
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
1346 1347
      return name.match(regexp);
    }, name = client.name)) {
mercury233's avatar
mercury233 committed
1348
      log.warn("BAD NAME LEVEL 1", client.name, client.ip);
mercury233's avatar
mercury233 committed
1349
      ygopro.stoc_die(client, "${bad_name_level1}");
mercury233's avatar
mercury233 committed
1350
    } else if (info.pass.length && !ROOM_validate(info.pass)) {
mercury233's avatar
mercury233 committed
1351
      ygopro.stoc_die(client, "${invalid_password_room}");
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1352
    } else {
mercury233's avatar
mercury233 committed
1353
      room = ROOM_find_or_create_by_name(info.pass, client.ip);
mercury233's avatar
mercury233 committed
1354
      if (!room) {
mercury233's avatar
mercury233 committed
1355
        ygopro.stoc_die(client, "${server_full}");
mercury233's avatar
mercury233 committed
1356
      } else if (room.error) {
mercury233's avatar
mercury233 committed
1357
        ygopro.stoc_die(client, room.error);
mercury233's avatar
mercury233 committed
1358
      } else if (room.started) {
mercury233's avatar
mercury233 committed
1359
        if (settings.modules.cloud_replay.enable_halfway_watch) {
mercury233's avatar
mercury233 committed
1360
          client.setTimeout(300000);
1361
          client.rid = _.indexOf(ROOM_all, room);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1362
          client.is_post_watcher = true;
mercury233's avatar
mercury233 committed
1363
          ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
1364
          room.watchers.push(client);
mercury233's avatar
mercury233 committed
1365
          ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
1366
          ref1 = room.watcher_buffers;
mercury233's avatar
mercury233 committed
1367 1368
          for (k = 0, len1 = ref1.length; k < len1; k++) {
            buffer = ref1[k];
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1369 1370 1371
            client.write(buffer);
          }
        } else {
mercury233's avatar
mercury233 committed
1372
          ygopro.stoc_die(client, "${watch_denied}");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1373 1374
        }
      } else {
mercury233's avatar
mercury233 committed
1375
        client.setTimeout(300000);
1376 1377
        client.rid = _.indexOf(ROOM_all, room);
        room.connect(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1378
      }
神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
1379 1380 1381
    }
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
1382
  ygopro.stoc_follow('JOIN_GAME', false, function(buffer, info, client, server) {
1383 1384 1385
    var recorder, room, watcher;
    room = ROOM_all[client.rid];
    if (!room) {
1386 1387
      return;
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1388
    if (settings.modules.welcome) {
mercury233's avatar
mercury233 committed
1389
      ygopro.stoc_send_chat(client, settings.modules.welcome, ygopro.constants.COLORS.GREEN);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1390
    }
1391 1392
    if (room.welcome) {
      ygopro.stoc_send_chat(client, room.welcome, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
add  
mercury233 committed
1393
    }
mercury233's avatar
mercury233 committed
1394
    if (settings.modules.arena_mode.enabled && client.ip !== '::ffff:127.0.0.1') {
mercury233's avatar
mercury233 committed
1395 1396 1397 1398
      request({
        url: settings.modules.arena_mode.get_score + encodeURIComponent(client.name),
        json: true
      }, function(error, response, body) {
mercury233's avatar
merge  
mercury233 committed
1399
        var rank_txt;
mercury233's avatar
merge  
mercury233 committed
1400 1401 1402 1403
        if (error) {
          log.warn('LOAD SCORE ERROR', client.name, error);
        } else if (!body || _.isString(body)) {
          log.warn('LOAD SCORE FAIL', client.name, response.statusCode, response.statusMessage, body);
mercury233's avatar
mercury233 committed
1404
        } else {
mercury233's avatar
mercury233 committed
1405 1406
          rank_txt = body.arena_rank > 0 ? "${rank_arena}" + body.arena_rank : "${rank_blank}";
          ygopro.stoc_send_chat(client, client.name + "${exp_value_part1}" + body.exp + "${exp_value_part2}${exp_value_part3}" + (Math.round(body.pt)) + rank_txt + "${exp_value_part4}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1407 1408 1409
        }
      });
    }
1410 1411
    if (!room.recorder) {
      room.recorder = recorder = net.connect(room.port, function() {
mercury233's avatar
mercury233 committed
1412 1413 1414 1415 1416
        ygopro.ctos_send(recorder, 'PLAYER_INFO', {
          name: "Marshtomp"
        });
        ygopro.ctos_send(recorder, 'JOIN_GAME', {
          version: settings.version,
mercury233's avatar
mercury233 committed
1417
          pass: "Marshtomp"
mercury233's avatar
mercury233 committed
1418
        });
mercury233's avatar
mercury233 committed
1419
        ygopro.ctos_send(recorder, 'HS_TOOBSERVER');
mercury233's avatar
mercury233 committed
1420 1421
      });
      recorder.on('data', function(data) {
1422
        room = ROOM_all[client.rid];
mercury233's avatar
mercury233 committed
1423
        if (!(room && settings.modules.cloud_replay.enabled)) {
mercury233's avatar
mercury233 committed
1424 1425
          return;
        }
mercury233's avatar
mercury233 committed
1426
        room.recorder_buffers.push(data);
mercury233's avatar
mercury233 committed
1427 1428 1429
      });
      recorder.on('error', function(error) {});
    }
mercury233's avatar
mercury233 committed
1430
    if (settings.modules.cloud_replay.enable_halfway_watch && !room.watcher) {
1431
      room.watcher = watcher = settings.modules.test_mode.watch_public_hand ? room.recorder : net.connect(room.port, function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1432 1433 1434 1435 1436
        ygopro.ctos_send(watcher, 'PLAYER_INFO', {
          name: "the Big Brother"
        });
        ygopro.ctos_send(watcher, 'JOIN_GAME', {
          version: settings.version,
mercury233's avatar
mercury233 committed
1437
          pass: "the Big Brother"
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1438
        });
mercury233's avatar
mercury233 committed
1439
        ygopro.ctos_send(watcher, 'HS_TOOBSERVER');
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1440
      });
mercury233's avatar
fix  
mercury233 committed
1441
      watcher.on('data', function(data) {
mercury233's avatar
mercury233 committed
1442
        var j, len, ref, w;
1443 1444
        room = ROOM_all[client.rid];
        if (!room) {
1445 1446
          return;
        }
1447 1448
        room.watcher_buffers.push(data);
        ref = room.watchers;
mercury233's avatar
mercury233 committed
1449 1450
        for (j = 0, len = ref.length; j < len; j++) {
          w = ref[j];
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1451
          if (w) {
mercury233's avatar
test3  
mercury233 committed
1452
            w.write(data);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1453
          }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1454 1455
        }
      });
mercury233's avatar
test3  
mercury233 committed
1456
      watcher.on('error', function(error) {});
神楽坂玲奈's avatar
神楽坂玲奈 committed
1457
    }
神楽坂玲奈's avatar
tip  
神楽坂玲奈 committed
1458
  });
神楽坂玲奈's avatar
神楽坂玲奈 committed
1459

mercury233's avatar
mercury233 committed
1460
  load_dialogues = function() {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1461
    request({
mercury233's avatar
mercury233 committed
1462
      url: settings.modules.dialogues.get,
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1463 1464 1465
      json: true
    }, function(error, response, body) {
      if (_.isString(body)) {
mercury233's avatar
test3  
mercury233 committed
1466
        log.warn("dialogues bad json", body);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1467
      } else if (error || !body) {
mercury233's avatar
test3  
mercury233 committed
1468
        log.warn('dialogues error', error, response);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1469
      } else {
mercury233's avatar
mercury233 committed
1470 1471
        nconf.myset(settings, "dialogues", body);
        log.info("dialogues loaded", _.size(body));
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1472 1473
      }
    });
mercury233's avatar
mercury233 committed
1474 1475
  };

mercury233's avatar
mercury233 committed
1476
  if (settings.modules.dialogues.get) {
mercury233's avatar
mercury233 committed
1477
    load_dialogues();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1478 1479
  }

神楽坂玲奈's avatar
神楽坂玲奈 committed
1480
  ygopro.stoc_follow('GAME_MSG', false, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1481
    var card, j, len, line, msg, playertype, pos, reason, ref, ref1, ref2, room, val;
1482 1483 1484 1485
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1486
    msg = buffer.readInt8(0);
1487
    if (msg >= 10 && msg < 30) {
1488 1489
      room.waiting_for_player = client;
      room.last_active_time = moment();
1490
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1491 1492 1493
    if (ygopro.constants.MSG[msg] === 'START') {
      playertype = buffer.readUInt8(1);
      client.is_first = !(playertype & 0xf);
1494
      client.lp = room.hostinfo.start_lp;
nanahira's avatar
nanahira committed
1495
      if (client.pos === 0) {
1496
        room.turn = 0;
1497
        room.duel_count = room.duel_count + 1;
nanahira's avatar
fix  
nanahira committed
1498
      }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1499
    }
1500
    if (ygopro.constants.MSG[msg] === 'NEW_TURN') {
nanahira's avatar
nanahira committed
1501
      if (client.pos === 0) {
1502
        room.turn = room.turn + 1;
nanahira's avatar
nanahira committed
1503
        if (room.death) {
nanahira's avatar
nanahira committed
1504
          if (room.turn >= room.death) {
nanahira's avatar
fix  
nanahira committed
1505
            if (room.dueling_players[0].lp !== room.dueling_players[1].lp && room.turn > 1) {
nanahira's avatar
nanahira committed
1506 1507 1508
              ygopro.stoc_send_chat_to_room(room, "${death_finish_part1}" + (room.dueling_players[0].lp > room.dueling_players[1].lp ? room.dueling_players[0] : room.dueling_players[1]).name + "${death_finish_part2}", ygopro.constants.COLORS.BABYBLUE);
              ygopro.ctos_send((room.dueling_players[0].lp > room.dueling_players[1].lp ? room.dueling_players[1] : room.dueling_players[0]).server, 'SURRENDER');
            } else {
nanahira's avatar
nanahira committed
1509
              room.death = -1;
nanahira's avatar
nanahira committed
1510 1511 1512 1513 1514 1515
              ygopro.stoc_send_chat_to_room(room, "${death_remain_final}", ygopro.constants.COLORS.BABYBLUE);
            }
          } else {
            ygopro.stoc_send_chat_to_room(room, "${death_remain_part1}" + (room.death - room.turn) + "${death_remain_part2}", ygopro.constants.COLORS.BABYBLUE);
          }
        }
1516 1517 1518 1519 1520
      }
      if (client.surrend_confirm) {
        client.surrend_confirm = false;
        ygopro.stoc_send_chat(client, "${surrender_canceled}", ygopro.constants.COLORS.BABYBLUE);
      }
mercury233's avatar
mercury233 committed
1521
    }
nanahira's avatar
nanahira committed
1522
    if (ygopro.constants.MSG[msg] === 'WIN' && client.pos === 0) {
mercury233's avatar
mercury233 committed
1523 1524 1525 1526 1527 1528
      pos = buffer.readUInt8(1);
      if (!(client.is_first || pos === 2)) {
        pos = 1 - pos;
      }
      reason = buffer.readUInt8(2);
      room.winner = pos;
nanahira's avatar
nanahira committed
1529
      room.turn = 0;
mercury233's avatar
fix  
mercury233 committed
1530
      if (room && !room.finished && room.dueling_players[pos]) {
mercury233's avatar
mercury233 committed
1531 1532 1533
        room.winner_name = room.dueling_players[pos].name;
        room.scores[room.winner_name] = room.scores[room.winner_name] + 1;
      }
nanahira's avatar
fix  
nanahira committed
1534 1535 1536 1537 1538 1539 1540
      if (room.death) {
        if (settings.modules.http.quick_death_rule) {
          room.death = -1;
        } else {
          room.death = 5;
        }
      }
mercury233's avatar
mercury233 committed
1541
    }
nanahira's avatar
nanahira committed
1542
    if (ygopro.constants.MSG[msg] === 'DAMAGE' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1543 1544 1545 1546 1547
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1548 1549
      room.dueling_players[pos].lp -= val;
      if ((0 < (ref = room.dueling_players[pos].lp) && ref <= 100)) {
mercury233's avatar
mercury233 committed
1550
        ygopro.stoc_send_chat_to_room(room, "${lp_low_opponent}", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1551 1552
      }
    }
nanahira's avatar
nanahira committed
1553
    if (ygopro.constants.MSG[msg] === 'RECOVER' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1554 1555 1556 1557 1558
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1559
      room.dueling_players[pos].lp += val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1560
    }
nanahira's avatar
nanahira committed
1561
    if (ygopro.constants.MSG[msg] === 'LPUPDATE' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1562 1563 1564 1565 1566
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1567
      room.dueling_players[pos].lp = val;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1568
    }
nanahira's avatar
nanahira committed
1569
    if (ygopro.constants.MSG[msg] === 'PAY_LPCOST' && client.pos === 0) {
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1570 1571 1572 1573 1574
      pos = buffer.readUInt8(1);
      if (!client.is_first) {
        pos = 1 - pos;
      }
      val = buffer.readInt32LE(2);
1575 1576
      room.dueling_players[pos].lp -= val;
      if ((0 < (ref1 = room.dueling_players[pos].lp) && ref1 <= 100)) {
mercury233's avatar
mercury233 committed
1577
        ygopro.stoc_send_chat_to_room(room, "${lp_low_self}", ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1578 1579
      }
    }
mercury233's avatar
mercury233 committed
1580
    if (settings.modules.dialogues.enabled) {
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1581 1582
      if (ygopro.constants.MSG[msg] === 'SUMMONING' || ygopro.constants.MSG[msg] === 'SPSUMMONING') {
        card = buffer.readUInt32LE(1);
mercury233's avatar
mercury233 committed
1583 1584
        if (settings.dialogues[card]) {
          ref2 = _.lines(settings.dialogues[card][Math.floor(Math.random() * settings.dialogues[card].length)]);
mercury233's avatar
mercury233 committed
1585 1586
          for (j = 0, len = ref2.length; j < len; j++) {
            line = ref2[j];
mercury233's avatar
mercury233 committed
1587
            ygopro.stoc_send_chat(client, line, ygopro.constants.COLORS.PINK);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1588
          }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1589
        }
神楽坂玲奈's avatar
 
神楽坂玲奈 committed
1590 1591 1592 1593
      }
    }
  });

1594 1595 1596 1597 1598 1599
  ygopro.ctos_follow('HS_TOOBSERVER', true, function(buffer, info, client, server) {
    var j, len, player, ref, room;
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
1600
    if (!room.arena || client.ip === "::ffff:127.0.0.1") {
1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612
      return false;
    }
    ref = room.players;
    for (j = 0, len = ref.length; j < len; j++) {
      player = ref[j];
      if (player === client) {
        ygopro.stoc_send_chat(client, "${cannot_to_observer}", ygopro.constants.COLORS.BABYBLUE);
        return true;
      }
    }
    return false;
  });
nanahira's avatar
js  
nanahira committed
1613

1614
  ygopro.ctos_follow('HS_KICK', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1615
    var j, len, player, ref, room;
1616 1617
    room = ROOM_all[client.rid];
    if (!room) {
1618 1619
      return;
    }
1620
    ref = room.players;
mercury233's avatar
mercury233 committed
1621 1622
    for (j = 0, len = ref.length; j < len; j++) {
      player = ref[j];
mercury233's avatar
mercury233 committed
1623
      if (player && player.pos === info.pos && player !== client) {
1624 1625 1626 1627 1628
        if (room.arena === "athletic") {
          ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
          client.destroy();
          return true;
        }
mercury233's avatar
mercury233 committed
1629
        client.kick_count = client.kick_count ? client.kick_count + 1 : 1;
mercury233's avatar
fix  
mercury233 committed
1630
        if (client.kick_count >= 5 && room.random_type) {
mercury233's avatar
mercury233 committed
1631
          ygopro.stoc_send_chat_to_room(room, client.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1632
          ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
mercury233's avatar
mercury233 committed
1633
          client.destroy();
mercury233's avatar
mercury233 committed
1634 1635
          return true;
        }
mercury233's avatar
mercury233 committed
1636
        ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_player}", ygopro.constants.COLORS.RED);
1637 1638 1639 1640 1641
      }
    }
    return false;
  });

神楽坂玲奈's avatar
神楽坂玲奈 committed
1642 1643 1644 1645 1646
  ygopro.stoc_follow('TYPE_CHANGE', false, function(buffer, info, client, server) {
    var is_host, selftype;
    selftype = info.type & 0xf;
    is_host = ((info.type >> 4) & 0xf) !== 0;
    client.is_host = is_host;
mercury233's avatar
test3  
mercury233 committed
1647
    client.pos = selftype;
神楽坂玲奈's avatar
神楽坂玲奈 committed
1648 1649
  });

1650
  ygopro.stoc_follow('HS_PLAYER_CHANGE', false, function(buffer, info, client, server) {
1651
    var is_ready, j, k, len, len1, p1, p2, player, pos, ref, ref1, room;
1652 1653
    room = ROOM_all[client.rid];
    if (!(room && room.max_player && client.is_host)) {
1654 1655 1656 1657
      return;
    }
    pos = info.status >> 4;
    is_ready = (info.status & 0xf) === 9;
1658
    if (pos < room.max_player) {
1659 1660 1661 1662 1663 1664 1665 1666
      if (room.arena) {
        room.ready_player_count = 0;
        ref = room.players;
        for (j = 0, len = ref.length; j < len; j++) {
          player = ref[j];
          if (player.pos === pos) {
            player.is_ready = is_ready;
          }
1667
        }
1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714
        p1 = room.players[0];
        p2 = room.players[1];
        if (!p1 || !p2) {
          if (room.waiting_for_player_interval) {
            clearInterval(room.waiting_for_player_interval);
            room.waiting_for_player_interval = null;
          }
          return;
        }
        room.waiting_for_player2 = room.waiting_for_player;
        room.waiting_for_player = null;
        if (p1.is_ready && p2.is_ready) {
          room.waiting_for_player = p1.is_host ? p1 : p2;
        }
        if (!p1.is_ready && p2.is_ready) {
          room.waiting_for_player = p1;
        }
        if (!p2.is_ready && p1.is_ready) {
          room.waiting_for_player = p2;
        }
        if (room.waiting_for_player !== room.waiting_for_player2) {
          room.waiting_for_player2 = room.waiting_for_player;
          room.waiting_for_player_time = 20;
          room.waiting_for_player_interval = setInterval((function() {
            wait_room_start_arena(ROOM_all[client.rid]);
          }), 1000);
        } else if (!room.waiting_for_player && room.waiting_for_player_interval) {
          clearInterval(room.waiting_for_player_interval);
          room.waiting_for_player_interval = null;
          room.waiting_for_player_time = 20;
        }
      } else {
        room.ready_player_count_without_host = 0;
        ref1 = room.players;
        for (k = 0, len1 = ref1.length; k < len1; k++) {
          player = ref1[k];
          if (player.pos === pos) {
            player.is_ready = is_ready;
          }
          if (!player.is_host) {
            room.ready_player_count_without_host += player.is_ready;
          }
        }
        if (room.ready_player_count_without_host >= room.max_player - 1) {
          setTimeout((function() {
            wait_room_start(ROOM_all[client.rid], 20);
          }), 1000);
1715 1716 1717 1718 1719 1720
        }
      }
    }
  });

  wait_room_start = function(room, time) {
mercury233's avatar
mercury233 committed
1721
    var j, len, player, ref;
1722 1723 1724 1725
    if (!(!room || room.started || room.ready_player_count_without_host < room.max_player - 1)) {
      time -= 1;
      if (time) {
        if (!(time % 5)) {
mercury233's avatar
mercury233 committed
1726
          ygopro.stoc_send_chat_to_room(room, "" + (time <= 9 ? ' ' : '') + time + "${kick_count_down}", time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
1727 1728 1729 1730 1731 1732
        }
        setTimeout((function() {
          wait_room_start(room, time);
        }), 1000);
      } else {
        ref = room.players;
mercury233's avatar
mercury233 committed
1733 1734
        for (j = 0, len = ref.length; j < len; j++) {
          player = ref[j];
mercury233's avatar
fix  
mercury233 committed
1735
          if (player && player.is_host) {
mercury233's avatar
mercury233 committed
1736
            ROOM_ban_player(player.name, player.ip, "${random_ban_reason_zombie}");
mercury233's avatar
mercury233 committed
1737
            ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1738
            player.destroy();
1739 1740 1741 1742 1743 1744
          }
        }
      }
    }
  };

1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762
  wait_room_start_arena = function(room) {
    if (!(!room || room.started || !room.waiting_for_player)) {
      room.waiting_for_player_time = room.waiting_for_player_time - 1;
      if (room.waiting_for_player_time > 0) {
        if (!(room.waiting_for_player_time % 5)) {
          ygopro.stoc_send_chat_to_room(room, "" + (room.waiting_for_player_time <= 9 ? ' ' : '') + room.waiting_for_player_time + "${kick_count_down_arena_part1} " + room.waiting_for_player.name + " ${kick_count_down_arena_part2}", room.waiting_for_player_time <= 9 ? ygopro.constants.COLORS.RED : ygopro.constants.COLORS.LIGHTBLUE);
        }
      } else {
        ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
        room.waiting_for_player.destroy();
        if (room.waiting_for_player_interval) {
          clearInterval(room.waiting_for_player_interval);
          room.waiting_for_player_interval = null;
        }
      }
    }
  };

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1763
  ygopro.stoc_send_random_tip = function(client) {
mercury233's avatar
mercury233 committed
1764
    if (settings.modules.tips.enabled && settings.tips.length) {
mercury233's avatar
mercury233 committed
1765
      ygopro.stoc_send_chat(client, "Tip: " + settings.tips[Math.floor(Math.random() * settings.tips.length)]);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1766
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1767 1768
  };

1769
  ygopro.stoc_send_random_tip_to_room = function(room) {
mercury233's avatar
mercury233 committed
1770
    if (settings.modules.tips.enabled && settings.tips.length) {
mercury233's avatar
mercury233 committed
1771
      ygopro.stoc_send_chat_to_room(room, "Tip: " + settings.tips[Math.floor(Math.random() * settings.tips.length)]);
1772 1773 1774
    }
  };

mercury233's avatar
mercury233 committed
1775
  load_tips = function() {
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1776
    request({
mercury233's avatar
mercury233 committed
1777
      url: settings.modules.tips.get,
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1778 1779
      json: true
    }, function(error, response, body) {
mercury233's avatar
mercury233 committed
1780 1781 1782 1783 1784 1785 1786
      if (_.isString(body)) {
        log.warn("tips bad json", body);
      } else if (error || !body) {
        log.warn('tips error', error, response);
      } else {
        nconf.myset(settings, "tips", body);
        log.info("tips loaded", settings.tips.length);
mercury233's avatar
mercury233 committed
1787
      }
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1788
    });
mercury233's avatar
mercury233 committed
1789 1790
  };

mercury233's avatar
mercury233 committed
1791
  if (settings.modules.tips.get) {
mercury233's avatar
mercury233 committed
1792 1793
    load_tips();
    setInterval(function() {
mercury233's avatar
mercury233 committed
1794 1795 1796
      var j, len, room;
      for (j = 0, len = ROOM_all.length; j < len; j++) {
        room = ROOM_all[j];
1797
        if (room && room.established) {
1798
          if (!room.started || room.changing_side) {
1799 1800
            ygopro.stoc_send_random_tip_to_room(room);
          }
mercury233's avatar
mercury233 committed
1801 1802 1803
        }
      }
    }, 30000);
神楽坂玲奈's avatar
fix  
神楽坂玲奈 committed
1804
  }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1805 1806

  ygopro.stoc_follow('DUEL_START', false, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1807
    var deck_arena, deck_name, deck_text, j, len, player, ref, room;
1808 1809
    room = ROOM_all[client.rid];
    if (!room) {
1810 1811
      return;
    }
1812 1813
    if (!room.started) {
      room.started = true;
mercury233's avatar
mercury233 committed
1814
      room.start_time = moment().format();
mercury233's avatar
mercury233 committed
1815
      if (!room.windbot && settings.modules.http.websocket_roomlist) {
mercury233's avatar
mercury233 committed
1816
        roomlist.start(room);
神楽坂玲奈's avatar
神楽坂玲奈 committed
1817
      }
1818 1819
      room.dueling_players = [];
      ref = room.players;
mercury233's avatar
mercury233 committed
1820 1821
      for (j = 0, len = ref.length; j < len; j++) {
        player = ref[j];
mercury233's avatar
mercury233 committed
1822 1823
        if (!(player.pos !== 7)) {
          continue;
神楽坂玲奈's avatar
12.2  
神楽坂玲奈 committed
1824
        }
1825
        room.dueling_players[player.pos] = player;
mercury233's avatar
mercury233 committed
1826
        room.scores[player.name] = 0;
1827
        room.player_datas.push({
mercury233's avatar
mercury233 committed
1828
          ip: player.ip,
mercury233's avatar
mercury233 committed
1829 1830
          name: player.name
        });
mercury233's avatar
mercury233 committed
1831 1832 1833
        if (room.random_type === 'T') {
          ROOM_players_oppentlist[player.ip] = null;
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1834 1835
      }
    }
mercury233's avatar
mercury233 committed
1836
    if (settings.modules.tips.enabled) {
mercury233's avatar
test3  
mercury233 committed
1837
      ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1838
    }
mercury233's avatar
mercury233 committed
1839
    if (settings.modules.deck_log.enabled && client.main && client.main.length && !client.deck_saved && !room.windbot) {
mercury233's avatar
mercury233 committed
1840
      deck_text = '#ygopro-server deck log\n#main\n' + client.main.join('\n') + '\n!side\n' + client.side.join('\n') + '\n';
mercury233's avatar
mercury233 committed
1841 1842 1843 1844 1845 1846 1847 1848
      deck_arena = settings.modules.deck_log.arena + '-';
      if (room.arena) {
        deck_arena = deck_arena + room.arena;
      } else if (room.hostinfo.mode === 2) {
        deck_arena = deck_arena + 'tag';
      } else if (room.random_type === 'S') {
        deck_arena = deck_arena + 'entertain';
      } else if (room.random_type === 'M') {
mercury233's avatar
mercury233 committed
1849
        deck_arena = deck_arena + 'athletic';
mercury233's avatar
mercury233 committed
1850 1851 1852
      } else {
        deck_arena = deck_arena + 'custom';
      }
mercury233's avatar
mercury233 committed
1853
      if (settings.modules.deck_log.local) {
1854
        deck_name = moment().format('YYYY-MM-DD HH-mm-ss') + ' ' + room.port + ' ' + client.pos + ' ' + client.ip.slice(7) + ' ' + client.name.replace(/[\/\\\?\*]/g, '_');
mercury233's avatar
mercury233 committed
1855
        fs.writeFile(settings.modules.deck_log.local + deck_name + '.ydk', deck_text, 'utf-8', function(err) {
mercury233's avatar
mercury233 committed
1856 1857 1858 1859 1860
          if (err) {
            return log.warn('DECK SAVE ERROR', err);
          }
        });
      }
mercury233's avatar
mercury233 committed
1861
      if (settings.modules.deck_log.post) {
mercury233's avatar
mercury233 committed
1862
        request.post({
mercury233's avatar
mercury233 committed
1863
          url: settings.modules.deck_log.post,
mercury233's avatar
mercury233 committed
1864
          form: {
mercury233's avatar
mercury233 committed
1865
            accesskey: settings.modules.deck_log.accesskey,
mercury233's avatar
mercury233 committed
1866 1867
            deck: deck_text,
            playername: client.name,
mercury233's avatar
mercury233 committed
1868
            arena: deck_arena
mercury233's avatar
mercury233 committed
1869 1870 1871
          }
        }, function(error, response, body) {
          if (error) {
mercury233's avatar
merge  
mercury233 committed
1872
            log.warn('DECK POST ERROR', error);
mercury233's avatar
mercury233 committed
1873 1874
          } else {
            if (response.statusCode !== 200) {
mercury233's avatar
merge  
mercury233 committed
1875
              log.warn('DECK POST FAIL', response.statusCode, client.name, body);
mercury233's avatar
mercury233 committed
1876 1877 1878 1879
            }
          }
        });
      }
mercury233's avatar
mercury233 committed
1880 1881
      client.deck_saved = true;
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1882 1883
  });

1884 1885 1886 1887 1888 1889 1890 1891 1892
  ygopro.ctos_follow('SURRENDER', true, function(buffer, info, client, server) {
    var room;
    room = ROOM_all[client.rid];
    if (!room) {
      return;
    }
    if (!room.started || room.hostinfo.mode === 2) {
      return true;
    }
1893
    if (room.random_type && room.turn < 3 && !client.flee_free) {
1894 1895 1896 1897 1898 1899
      ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE);
      return true;
    }
    return false;
  });

mercury233's avatar
mercury233 committed
1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925
  report_to_big_brother = function(roomname, sender, ip, level, content, match) {
    if (!settings.modules.big_brother.enabled) {
      return;
    }
    request.post({
      url: settings.modules.big_brother.post,
      form: {
        accesskey: settings.modules.big_brother.accesskey,
        roomname: roomname,
        sender: sender,
        ip: ip,
        level: level,
        content: content,
        match: match
      }
    }, function(error, response, body) {
      if (error) {
        log.warn('BIG BROTHER ERROR', error);
      } else {
        if (response.statusCode !== 200) {
          log.warn('BIG BROTHER FAIL', response.statusCode, roomname, body);
        }
      }
    });
  };

1926
  ygopro.ctos_follow('CHAT', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
1927
    var cancel, cmd, msg, name, oldmsg, room, struct, windbot;
1928 1929
    room = ROOM_all[client.rid];
    if (!room) {
mercury233's avatar
mercury233 committed
1930 1931
      return;
    }
mercury233's avatar
mercury233 committed
1932 1933
    msg = _.trim(info.msg);
    cancel = _.startsWith(msg, "/");
mercury233's avatar
fix  
mercury233 committed
1934
    if (!(cancel || !(room.random_type || room.arena))) {
1935
      room.last_active_time = moment();
1936
    }
mercury233's avatar
mercury233 committed
1937 1938
    cmd = msg.split(' ');
    switch (cmd[0]) {
mercury233's avatar
mercury233 committed
1939 1940 1941 1942 1943
      case '/投降':
      case '/surrender':
        if (!room.started || room.hostinfo.mode === 2) {
          return cancel;
        }
1944
        if (room.random_type && room.turn < 3) {
mercury233's avatar
mercury233 committed
1945 1946 1947 1948 1949 1950 1951 1952 1953 1954
          ygopro.stoc_send_chat(client, "${surrender_denied}", ygopro.constants.COLORS.BABYBLUE);
          return cancel;
        }
        if (client.surrend_confirm) {
          ygopro.ctos_send(client.server, 'SURRENDER');
        } else {
          ygopro.stoc_send_chat(client, "${surrender_confirm}", ygopro.constants.COLORS.BABYBLUE);
          client.surrend_confirm = true;
        }
        break;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1955
      case '/help':
mercury233's avatar
mercury233 committed
1956 1957
        ygopro.stoc_send_chat(client, "${chat_order_main}");
        ygopro.stoc_send_chat(client, "${chat_order_help}");
mercury233's avatar
mercury233 committed
1958
        if (!settings.modules.mycard.enabled) {
mercury233's avatar
mercury233 committed
1959
          ygopro.stoc_send_chat(client, "${chat_order_roomname}");
mercury233's avatar
merge  
mercury233 committed
1960
        }
mercury233's avatar
mercury233 committed
1961
        if (settings.modules.windbot.enabled) {
mercury233's avatar
mercury233 committed
1962
          ygopro.stoc_send_chat(client, "${chat_order_windbot}");
mercury233's avatar
mercury233 committed
1963
        }
mercury233's avatar
mercury233 committed
1964
        if (settings.modules.tips.enabled) {
mercury233's avatar
mercury233 committed
1965
          ygopro.stoc_send_chat(client, "${chat_order_tip}");
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1966
        }
mercury233's avatar
mercury233 committed
1967
        break;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1968
      case '/tip':
mercury233's avatar
mercury233 committed
1969
        if (settings.modules.tips.enabled) {
mercury233's avatar
test3  
mercury233 committed
1970
          ygopro.stoc_send_random_tip(client);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
1971
        }
mercury233's avatar
mercury233 committed
1972
        break;
mercury233's avatar
mercury233 committed
1973
      case '/ai':
mercury233's avatar
mercury233 committed
1974
        if (settings.modules.windbot.enabled) {
mercury233's avatar
mercury233 committed
1975 1976 1977 1978 1979
          if (name = cmd[1]) {
            windbot = _.sample(_.filter(settings.modules.windbots, function(w) {
              return w.name === name || w.deck === name;
            }));
            if (!windbot) {
mercury233's avatar
mercury233 committed
1980
              ygopro.stoc_send_chat(client, "${windbot_deck_not_found}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
1981 1982 1983 1984 1985
              return;
            }
          } else {
            windbot = _.sample(settings.modules.windbots);
          }
mercury233's avatar
mercury233 committed
1986 1987 1988
          room.add_windbot(windbot);
        }
        break;
mercury233's avatar
mercury233 committed
1989
      case '/roomname':
1990
        if (room) {
mercury233's avatar
mercury233 committed
1991
          ygopro.stoc_send_chat(client, "${room_name} " + room.name, ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
1992
        }
神楽坂玲奈's avatar
神楽坂玲奈 committed
1993
    }
mercury233's avatar
mercury233 committed
1994 1995 1996 1997 1998 1999 2000 2001
    if (msg.length > 100) {
      log.warn("SPAM WORD", client.name, client.ip, msg);
      if (client.abuse_count) {
        client.abuse_count = client.abuse_count + 2;
      }
      ygopro.stoc_send_chat(client, "${chat_warn_level0}", ygopro.constants.COLORS.RED);
      cancel = true;
    }
mercury233's avatar
mercury233 committed
2002 2003 2004
    if (!(room && room.random_type)) {
      return cancel;
    }
mercury233's avatar
mercury233 committed
2005
    if (client.abuse_count >= 5) {
mercury233's avatar
mercury233 committed
2006
      log.warn("BANNED CHAT", client.name, client.ip, msg);
mercury233's avatar
mercury233 committed
2007
      ygopro.stoc_send_chat(client, "${banned_chat_tip}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2008 2009
      return true;
    }
mercury233's avatar
mercury233 committed
2010 2011 2012
    oldmsg = msg;
    if (_.any(settings.ban.badword_level3, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
2013
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
2014 2015
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
2016 2017
      log.warn("BAD WORD LEVEL 3", client.name, client.ip, oldmsg, RegExp.$1);
      report_to_big_brother(room.name, client.name, client.ip, 3, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
2018
      cancel = true;
mercury233's avatar
mercury233 committed
2019
      if (client.abuse_count > 0) {
mercury233's avatar
mercury233 committed
2020 2021 2022
        ygopro.stoc_send_chat(client, "${banned_duel_tip}", ygopro.constants.COLORS.RED);
        ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}");
        ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}", 3);
mercury233's avatar
mercury233 committed
2023
        client.destroy();
mercury233's avatar
mercury233 committed
2024 2025 2026
        return true;
      } else {
        client.abuse_count = client.abuse_count + 4;
mercury233's avatar
mercury233 committed
2027
        ygopro.stoc_send_chat(client, "${chat_warn_level2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2028
      }
mercury233's avatar
mercury233 committed
2029 2030 2031 2032 2033 2034 2035 2036 2037
    } else if (client.rag && room.started) {
      client.rag = false;
      cancel = true;
    } else if (_.any(settings.ban.spam_word, function(badword) {
      var regexp;
      regexp = new RegExp(badword, 'i');
      return msg.match(regexp);
    }, msg)) {
      client.abuse_count = client.abuse_count + 2;
mercury233's avatar
mercury233 committed
2038
      ygopro.stoc_send_chat(client, "${chat_warn_level0}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2039
      cancel = true;
mercury233's avatar
mercury233 committed
2040 2041
    } else if (_.any(settings.ban.badword_level2, function(badword) {
      var regexp;
mercury233's avatar
fix  
mercury233 committed
2042
      regexp = new RegExp(badword, 'i');
mercury233's avatar
mercury233 committed
2043 2044
      return msg.match(regexp);
    }, msg)) {
mercury233's avatar
mercury233 committed
2045 2046
      log.warn("BAD WORD LEVEL 2", client.name, client.ip, oldmsg, RegExp.$1);
      report_to_big_brother(room.name, client.name, client.ip, 2, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
2047
      client.abuse_count = client.abuse_count + 3;
mercury233's avatar
mercury233 committed
2048
      ygopro.stoc_send_chat(client, "${chat_warn_level2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2049 2050 2051 2052
      cancel = true;
    } else {
      _.each(settings.ban.badword_level1, function(badword) {
        var regexp;
mercury233's avatar
fix  
mercury233 committed
2053
        regexp = new RegExp(badword, "ig");
mercury233's avatar
mercury233 committed
2054 2055 2056
        msg = msg.replace(regexp, "**");
      }, msg);
      if (oldmsg !== msg) {
mercury233's avatar
mercury233 committed
2057 2058
        log.warn("BAD WORD LEVEL 1", client.name, client.ip, oldmsg, RegExp.$1);
        report_to_big_brother(room.name, client.name, client.ip, 1, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
2059
        client.abuse_count = client.abuse_count + 1;
mercury233's avatar
mercury233 committed
2060
        ygopro.stoc_send_chat(client, "${chat_warn_level1}");
mercury233's avatar
mercury233 committed
2061 2062 2063 2064 2065 2066 2067 2068 2069
        struct = ygopro.structs["chat"];
        struct._setBuff(buffer);
        struct.set("msg", msg);
        buffer = struct.buffer;
      } else if (_.any(settings.ban.badword_level0, function(badword) {
        var regexp;
        regexp = new RegExp(badword, 'i');
        return msg.match(regexp);
      }, msg)) {
mercury233's avatar
mercury233 committed
2070 2071
        log.info("BAD WORD LEVEL 0", client.name, client.ip, oldmsg, RegExp.$1);
        report_to_big_brother(room.name, client.name, client.ip, 0, oldmsg, RegExp.$1);
mercury233's avatar
mercury233 committed
2072 2073
      }
    }
mercury233's avatar
mercury233 committed
2074 2075 2076
    if (client.abuse_count >= 2) {
      ROOM_unwelcome(room, client, "${random_ban_reason_abuse}");
    }
mercury233's avatar
mercury233 committed
2077
    if (client.abuse_count >= 5) {
mercury233's avatar
mercury233 committed
2078 2079
      ygopro.stoc_send_chat_to_room(room, client.name + " ${chat_banned}", ygopro.constants.COLORS.RED);
      ROOM_ban_player(client.name, client.ip, "${random_ban_reason_abuse}");
mercury233's avatar
mercury233 committed
2080
    }
2081
    return cancel;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2082 2083
  });

mercury233's avatar
mercury233 committed
2084
  ygopro.ctos_follow('UPDATE_DECK', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
2085
    var buff_main, buff_side, card, current_deck, deck, deck_array, deck_main, deck_side, deck_text, deckbuf, decks, found_deck, i, j, k, len, len1, line, room, struct;
mercury233's avatar
mercury233 committed
2086 2087 2088 2089 2090
    room = ROOM_all[client.rid];
    if (!room) {
      return false;
    }
    buff_main = (function() {
mercury233's avatar
mercury233 committed
2091
      var j, ref, results;
2092
      results = [];
mercury233's avatar
mercury233 committed
2093
      for (i = j = 0, ref = info.mainc; 0 <= ref ? j < ref : j > ref; i = 0 <= ref ? ++j : --j) {
2094
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2095
      }
2096
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2097
    })();
mercury233's avatar
mercury233 committed
2098
    buff_side = (function() {
mercury233's avatar
mercury233 committed
2099
      var j, ref, ref1, results;
2100
      results = [];
mercury233's avatar
mercury233 committed
2101
      for (i = j = ref = info.mainc, ref1 = info.mainc + info.sidec; ref <= ref1 ? j < ref1 : j > ref1; i = ref <= ref1 ? ++j : --j) {
2102
        results.push(info.deckbuf[i]);
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2103
      }
2104
      return results;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2105
    })();
mercury233's avatar
mercury233 committed
2106 2107
    client.main = buff_main;
    client.side = buff_side;
2108
    if (room.random_type || room.arena) {
nanahira's avatar
nanahira committed
2109
      if (client.pos === 0) {
mercury233's avatar
mercury233 committed
2110 2111 2112
        room.waiting_for_player = room.waiting_for_player2;
      }
      room.last_active_time = moment();
mercury233's avatar
mercury233 committed
2113
    } else if (!room.started && room.hostinfo.mode === 1 && settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.deck_check) {
mercury233's avatar
mercury233 committed
2114 2115 2116 2117 2118 2119 2120 2121
      struct = ygopro.structs["deck"];
      struct._setBuff(buffer);
      struct.set("mainc", 1);
      struct.set("sidec", 1);
      struct.set("deckbuf", [4392470, 4392470]);
      buffer = struct.buffer;
      found_deck = false;
      decks = fs.readdirSync(settings.modules.tournament_mode.deck_path);
mercury233's avatar
mercury233 committed
2122 2123
      for (j = 0, len = decks.length; j < len; j++) {
        deck = decks[j];
mercury233's avatar
mercury233 committed
2124 2125 2126
        if (_.endsWith(deck, client.name + ".ydk")) {
          found_deck = deck;
        }
mercury233's avatar
fix  
mercury233 committed
2127 2128 2129
        if (_.endsWith(deck, client.name + ".ydk.ydk")) {
          found_deck = deck;
        }
mercury233's avatar
mercury233 committed
2130 2131
      }
      if (found_deck) {
mercury233's avatar
mercury233 committed
2132
        deck_text = fs.readFileSync(settings.modules.tournament_mode.deck_path + found_deck, {
mercury233's avatar
mercury233 committed
2133 2134 2135 2136 2137 2138
          encoding: "ASCII"
        });
        deck_array = deck_text.split("\n");
        deck_main = [];
        deck_side = [];
        current_deck = deck_main;
mercury233's avatar
mercury233 committed
2139 2140
        for (k = 0, len1 = deck_array.length; k < len1; k++) {
          line = deck_array[k];
mercury233's avatar
mercury233 committed
2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154
          if (line.indexOf("!side") >= 0) {
            current_deck = deck_side;
          }
          card = parseInt(line);
          if (!isNaN(card)) {
            current_deck.push(card);
          }
        }
        if (_.isEqual(buff_main, deck_main) && _.isEqual(buff_side, deck_side)) {
          deckbuf = deck_main.concat(deck_side);
          struct.set("mainc", deck_main.length);
          struct.set("sidec", deck_side.length);
          struct.set("deckbuf", deckbuf);
          buffer = struct.buffer;
mercury233's avatar
mercury233 committed
2155
          ygopro.stoc_send_chat(client, "${deck_correct_part1} " + found_deck + " ${deck_correct_part2}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
2156
        } else {
mercury233's avatar
mercury233 committed
2157
          ygopro.stoc_send_chat(client, "${deck_incorrect_part1} " + found_deck + " ${deck_incorrect_part2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2158 2159
        }
      } else {
mercury233's avatar
mercury233 committed
2160
        ygopro.stoc_send_chat(client, client.name + "${deck_not_found}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2161
      }
mercury233's avatar
mercury233 committed
2162
    }
mercury233's avatar
mercury233 committed
2163
    return false;
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2164 2165
  });

2166
  ygopro.ctos_follow('RESPONSE', false, function(buffer, info, client, server) {
2167 2168
    var room;
    room = ROOM_all[client.rid];
2169
    if (!(room && (room.random_type || room.arena))) {
2170 2171
      return;
    }
2172
    room.last_active_time = moment();
2173 2174 2175
  });

  ygopro.ctos_follow('HAND_RESULT', false, function(buffer, info, client, server) {
2176 2177
    var room;
    room = ROOM_all[client.rid];
mercury233's avatar
fix  
mercury233 committed
2178
    if (!(room && (room.random_type || room.arena))) {
2179 2180
      return;
    }
nanahira's avatar
nanahira committed
2181
    if (client.pos === 0) {
2182
      room.waiting_for_player = room.waiting_for_player2;
2183
    }
mercury233's avatar
mercury233 committed
2184
    room.last_active_time = moment().subtract(settings.modules.random_duel.hang_timeout - 19, 's');
2185 2186 2187
  });

  ygopro.ctos_follow('TP_RESULT', false, function(buffer, info, client, server) {
2188 2189
    var room;
    room = ROOM_all[client.rid];
mercury233's avatar
fix  
mercury233 committed
2190
    if (!(room && (room.random_type || room.arena))) {
2191 2192
      return;
    }
2193
    room.last_active_time = moment();
2194 2195 2196
  });

  ygopro.stoc_follow('SELECT_HAND', false, function(buffer, info, client, server) {
2197 2198
    var room;
    room = ROOM_all[client.rid];
mercury233's avatar
fix  
mercury233 committed
2199
    if (!(room && (room.random_type || room.arena))) {
2200 2201
      return;
    }
nanahira's avatar
nanahira committed
2202
    if (client.pos === 0) {
2203
      room.waiting_for_player = client;
2204
    } else {
2205
      room.waiting_for_player2 = client;
2206
    }
mercury233's avatar
mercury233 committed
2207
    room.last_active_time = moment().subtract(settings.modules.random_duel.hang_timeout - 19, 's');
2208 2209 2210
  });

  ygopro.stoc_follow('SELECT_TP', false, function(buffer, info, client, server) {
2211 2212
    var room;
    room = ROOM_all[client.rid];
2213
    if (!room) {
2214 2215
      return;
    }
2216
    room.changing_side = false;
mercury233's avatar
fix  
mercury233 committed
2217
    if (room.random_type || room.arena) {
2218 2219 2220
      room.waiting_for_player = client;
      room.last_active_time = moment();
    }
2221 2222
  });

mercury233's avatar
mercury233 committed
2223
  ygopro.stoc_follow('CHANGE_SIDE', false, function(buffer, info, client, server) {
2224 2225
    var room;
    room = ROOM_all[client.rid];
2226
    if (!room) {
mercury233's avatar
mercury233 committed
2227 2228
      return;
    }
2229 2230
    room.changing_side = true;
    if (room.random_type || room.arena) {
nanahira's avatar
nanahira committed
2231
      if (client.pos === 0) {
2232 2233 2234 2235 2236
        room.waiting_for_player = client;
      } else {
        room.waiting_for_player2 = client;
      }
      room.last_active_time = moment();
mercury233's avatar
mercury233 committed
2237 2238 2239
    }
  });

2240
  ygopro.stoc_follow('REPLAY', true, function(buffer, info, client, server) {
mercury233's avatar
mercury233 committed
2241
    var duellog, dueltime, i, j, len, player, ref, replay_filename, room;
2242 2243
    room = ROOM_all[client.rid];
    if (!room) {
mercury233's avatar
mercury233 committed
2244
      return settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe;
2245
    }
mercury233's avatar
mercury233 committed
2246
    if (settings.modules.cloud_replay.enabled && room.random_type) {
mercury233's avatar
fix  
mercury233 committed
2247 2248
      Cloud_replay_ids.push(room.cloud_replay_id);
    }
mercury233's avatar
mercury233 committed
2249
    if (settings.modules.tournament_mode.enabled && settings.modules.tournament_mode.replay_safe) {
nanahira's avatar
nanahira committed
2250
      if (client.pos === 0) {
mercury233's avatar
mercury233 committed
2251 2252 2253
        dueltime = moment().format('YYYY-MM-DD HH:mm:ss');
        replay_filename = dueltime;
        ref = room.dueling_players;
mercury233's avatar
mercury233 committed
2254
        for (i = j = 0, len = ref.length; j < len; i = ++j) {
mercury233's avatar
mercury233 committed
2255 2256 2257 2258
          player = ref[i];
          replay_filename = replay_filename + (i > 0 ? " VS " : " ") + player.name;
        }
        replay_filename = replay_filename.replace(/[\/\\\?\*]/g, '_') + ".yrp";
mercury233's avatar
mercury233 committed
2259
        duellog = {
mercury233's avatar
mercury233 committed
2260
          time: dueltime,
2261
          name: room.name + (settings.modules.tournament_mode.show_info ? " (Duel:" + room.duel_count + ")" : ""),
mercury233's avatar
mercury233 committed
2262 2263
          roomid: room.port.toString(),
          cloud_replay_id: "R#" + room.cloud_replay_id,
mercury233's avatar
mercury233 committed
2264
          replay_filename: replay_filename,
mercury233's avatar
mercury233 committed
2265
          players: (function() {
mercury233's avatar
mercury233 committed
2266
            var k, len1, ref1, results;
mercury233's avatar
mercury233 committed
2267
            ref1 = room.dueling_players;
mercury233's avatar
mercury233 committed
2268
            results = [];
mercury233's avatar
mercury233 committed
2269 2270
            for (k = 0, len1 = ref1.length; k < len1; k++) {
              player = ref1[k];
mercury233's avatar
mercury233 committed
2271
              results.push({
2272
                name: player.name + (settings.modules.tournament_mode.show_ip && player.ip !== '::ffff:127.0.0.1' ? " (IP: " + player.ip.slice(7) + ")" : "") + (settings.modules.tournament_mode.show_info && !(room.hostinfo.mode === 2 && player.pos > 1) ? " (Score:" + room.scores[player.name] + " LP:" + (player.lp != null ? player.lp : room.hostinfo.start_lp) + ")" : ""),
mercury233's avatar
mercury233 committed
2273 2274 2275 2276 2277 2278
                winner: player.pos === room.winner
              });
            }
            return results;
          })()
        };
mercury233's avatar
mercury233 committed
2279
        settings.modules.tournament_mode.duel_log.unshift(duellog);
mercury233's avatar
mercury233 committed
2280
        nconf.myset(settings, "modules:tournament_mode:duel_log", settings.modules.tournament_mode.duel_log);
mercury233's avatar
mercury233 committed
2281 2282 2283 2284 2285
        fs.writeFile(settings.modules.tournament_mode.replay_path + replay_filename, buffer, function(err) {
          if (err) {
            return log.warn("SAVE REPLAY ERROR", replay_filename, err);
          }
        });
mercury233's avatar
mercury233 committed
2286
      }
mercury233's avatar
mercury233 committed
2287
      if (settings.modules.cloud_replay.enabled) {
mercury233's avatar
mercury233 committed
2288
        ygopro.stoc_send_chat(client, "${cloud_replay_delay_part1}R#" + room.cloud_replay_id + "${cloud_replay_delay_part2}", ygopro.constants.COLORS.BABYBLUE);
mercury233's avatar
mercury233 committed
2289
      }
2290 2291 2292 2293 2294 2295
      return true;
    } else {
      return false;
    }
  });

mercury233's avatar
mercury233 committed
2296
  if (settings.modules.random_duel.enabled) {
mercury233's avatar
mercury233 committed
2297
    setInterval(function() {
mercury233's avatar
mercury233 committed
2298 2299 2300
      var j, len, room, time_passed;
      for (j = 0, len = ROOM_all.length; j < len; j++) {
        room = ROOM_all[j];
mercury233's avatar
mercury233 committed
2301 2302 2303 2304
        if (!(room && room.started && room.random_type && room.last_active_time && room.waiting_for_player)) {
          continue;
        }
        time_passed = Math.floor((moment() - room.last_active_time) / 1000);
mercury233's avatar
mercury233 committed
2305
        if (time_passed >= settings.modules.random_duel.hang_timeout) {
mercury233's avatar
mercury233 committed
2306
          room.last_active_time = moment();
mercury233's avatar
mercury233 committed
2307 2308
          ROOM_ban_player(room.waiting_for_player.name, room.waiting_for_player.ip, "${random_ban_reason_AFK}");
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2309
          room.waiting_for_player.server.destroy();
mercury233's avatar
mercury233 committed
2310
        } else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
mercury233's avatar
mercury233 committed
2311
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2312
          ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}");
mercury233's avatar
mercury233 committed
2313
        }
2314
      }
mercury233's avatar
mercury233 committed
2315 2316 2317
    }, 1000);
  }

2318 2319 2320 2321 2322
  if (settings.modules.mycard.enabled) {
    setInterval(function() {
      var j, len, room, time_passed;
      for (j = 0, len = ROOM_all.length; j < len; j++) {
        room = ROOM_all[j];
mercury233's avatar
mercury233 committed
2323
        if (!(room && room.started && room.arena && room.last_active_time && room.waiting_for_player)) {
2324 2325 2326 2327 2328 2329
          continue;
        }
        time_passed = Math.floor((moment() - room.last_active_time) / 1000);
        if (time_passed >= settings.modules.random_duel.hang_timeout) {
          room.last_active_time = moment();
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
mercury233's avatar
mercury233 committed
2330
          room.scores[room.waiting_for_player.name] = -9;
2331 2332 2333 2334 2335 2336 2337 2338
          room.waiting_for_player.server.destroy();
        } else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
          ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
        }
      }
    }, 1000);
  }

mercury233's avatar
mercury233 committed
2339
  if (settings.modules.windbot.spawn) {
mercury233's avatar
mercury233 committed
2340 2341 2342 2343 2344 2345 2346 2347 2348 2349
    if (/^win/.test(process.platform)) {
      windbot_bin = 'WindBot.exe';
      windbot_parameters = [];
    } else {
      windbot_bin = 'mono';
      windbot_parameters = ['WindBot.exe'];
    }
    windbot_parameters.push('ServerMode=true');
    windbot_parameters.push('ServerPort=' + settings.modules.windbot.port);
    windbot_process = spawn(windbot_bin, windbot_parameters, {
mercury233's avatar
mercury233 committed
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361
      cwd: 'windbot'
    });
    windbot_process.on('error', function(err) {
      log.warn('WindBot ERROR', err);
    });
    windbot_process.on('exit', function(code) {
      log.warn('WindBot EXIT', code);
    });
    windbot_process.stdout.setEncoding('utf8');
    windbot_process.stdout.on('data', function(data) {
      log.info('WindBot:', data);
    });
mercury233's avatar
fix  
mercury233 committed
2362
    windbot_process.stderr.setEncoding('utf8');
mercury233's avatar
mercury233 committed
2363 2364 2365 2366
    windbot_process.stderr.on('data', function(data) {
      log.warn('WindBot Error:', data);
    });
  }
2367

神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2368
  if (settings.modules.http) {
mercury233's avatar
mercury233 committed
2369 2370 2371 2372 2373 2374
    addCallback = function(callback, text) {
      if (!callback) {
        return text;
      }
      return callback + "( " + text + " );";
    };
2375
    requestListener = function(request, response) {
nanahira's avatar
fix  
nanahira committed
2376
      var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, j, k, l, len, len1, len2, len3, m, parseQueryString, pass_validated, player, ref, replay, room, roomsjson, u;
2377 2378 2379 2380
      parseQueryString = true;
      u = url.parse(request.url, parseQueryString);
      pass_validated = u.query.pass === settings.modules.http.password;
      if (u.pathname === '/api/getrooms') {
mercury233's avatar
mercury233 committed
2381
        if (!pass_validated && !settings.modules.http.public_roomlist) {
2382
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2383
          response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}'));
2384 2385 2386 2387
        } else {
          response.writeHead(200);
          roomsjson = JSON.stringify({
            rooms: (function() {
mercury233's avatar
mercury233 committed
2388
              var j, len, results;
2389
              results = [];
mercury233's avatar
mercury233 committed
2390 2391
              for (j = 0, len = ROOM_all.length; j < len; j++) {
                room = ROOM_all[j];
2392
                if (room && room.established) {
2393
                  results.push({
mercury233's avatar
mercury233 committed
2394
                    pid: room.process.pid.toString(),
2395 2396 2397 2398
                    roomid: room.port.toString(),
                    roomname: pass_validated ? room.name : room.name.split('$', 2)[0],
                    needpass: (room.name.indexOf('$') !== -1).toString(),
                    users: (function() {
mercury233's avatar
mercury233 committed
2399
                      var k, len1, ref, results1;
mercury233's avatar
mercury233 committed
2400
                      ref = room.players;
2401
                      results1 = [];
mercury233's avatar
mercury233 committed
2402 2403
                      for (k = 0, len1 = ref.length; k < len1; k++) {
                        player = ref[k];
2404 2405 2406
                        if (player.pos != null) {
                          results1.push({
                            id: (-1).toString(),
2407
                            name: player.name + (settings.modules.http.show_ip && pass_validated && player.ip !== '::ffff:127.0.0.1' ? " (IP: " + player.ip.slice(7) + ")" : "") + (settings.modules.http.show_info && room.started && !(room.hostinfo.mode === 2 && player.pos > 1) ? " (Score:" + room.scores[player.name] + " LP:" + (player.lp != null ? player.lp : room.hostinfo.start_lp) + ")" : ""),
2408 2409 2410
                            pos: player.pos
                          });
                        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2411
                      }
2412 2413
                      return results1;
                    })(),
nanahira's avatar
nanahira committed
2414
                    istart: room.started ? (settings.modules.http.show_info ? "Duel:" + room.duel_count + " " + (room.changing_side ? "Siding" : "Turn:" + (room.turn != null ? room.turn : 0) + (room.death ? "/" + (room.death > 0 ? room.death - 1 : "Death") : "")) : 'start') : 'wait'
2415 2416
                  });
                }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2417
              }
2418 2419
              return results;
            })()
mercury233's avatar
mercury233 committed
2420 2421
          }, null, 2);
          response.end(addCallback(u.query.callback, roomsjson));
2422
        }
mercury233's avatar
mercury233 committed
2423
      } else if (u.pathname === '/api/duellog' && settings.modules.tournament_mode.enabled) {
mercury233's avatar
mercury233 committed
2424
        if (!(u.query.pass === settings.modules.tournament_mode.password)) {
mercury233's avatar
mercury233 committed
2425
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2426
          response.end(addCallback(u.query.callback, "[{name:'密码错误'}]"));
mercury233's avatar
mercury233 committed
2427 2428 2429
          return;
        } else {
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2430
          duellog = JSON.stringify(settings.modules.tournament_mode.duel_log, null, 2);
mercury233's avatar
mercury233 committed
2431
          response.end(addCallback(u.query.callback, duellog));
mercury233's avatar
mercury233 committed
2432
        }
nanahira's avatar
nanahira committed
2433
      } else if (u.pathname === '/api/archive.zip' && settings.modules.tournament_mode.enabled) {
nanahira's avatar
nanahira committed
2434 2435 2436 2437 2438 2439
        if (!(u.query.pass === settings.modules.tournament_mode.password)) {
          response.writeHead(403);
          response.end("Invalid password.");
          return;
        } else {
          try {
nanahira's avatar
nanahira committed
2440
            archive_name = moment().format('YYYY-MM-DD HH:mm:ss') + ".zip";
nanahira's avatar
nanahira committed
2441
            archive_args = ["a", "-mx0", "-y", archive_name];
nanahira's avatar
fix  
nanahira committed
2442
            check = false;
nanahira's avatar
nanahira committed
2443 2444 2445
            ref = settings.modules.tournament_mode.duel_log;
            for (j = 0, len = ref.length; j < len; j++) {
              replay = ref[j];
nanahira's avatar
fix  
nanahira committed
2446
              check = true;
nanahira's avatar
nanahira committed
2447 2448
              archive_args.push(replay.replay_filename);
            }
nanahira's avatar
fix  
nanahira committed
2449 2450 2451 2452 2453
            if (!check) {
              response.writeHead(403);
              response.end("Duel logs not found.");
              return;
            }
nanahira's avatar
nanahira committed
2454 2455 2456
            archive_process = spawn(settings.modules.tournament_mode.replay_archive_tool, archive_args, {
              cwd: settings.modules.tournament_mode.replay_path
            });
nanahira's avatar
js  
nanahira committed
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478
            archive_process.on('error', (function(_this) {
              return function(err) {
                response.writeHead(403);
                response.end("Failed packing replays. " + err);
              };
            })(this));
            archive_process.on('exit', (function(_this) {
              return function(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);
                  }
                });
              };
            })(this));
nanahira's avatar
nanahira committed
2479
            archive_process.stdout.setEncoding('utf8');
nanahira's avatar
js  
nanahira committed
2480 2481 2482 2483 2484
            archive_process.stdout.on('data', (function(_this) {
              return function(data) {
                return log.info("archive process: " + data);
              };
            })(this));
nanahira's avatar
nanahira committed
2485
            archive_process.stderr.setEncoding('utf8');
nanahira's avatar
js  
nanahira committed
2486 2487 2488 2489 2490
            archive_process.stderr.on('data', (function(_this) {
              return function(data) {
                return log.warn("archive error: " + data);
              };
            })(this));
nanahira's avatar
nanahira committed
2491 2492 2493 2494 2495 2496
          } catch (error1) {
            error = error1;
            response.writeHead(403);
            response.end("Failed reading replays. " + error);
          }
        }
nanahira's avatar
nanahira committed
2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507
      } else if (u.pathname === '/api/clearlog' && settings.modules.tournament_mode.enabled) {
        if (!(u.query.pass === settings.modules.tournament_mode.password)) {
          response.writeHead(200);
          response.end(addCallback(u.query.callback, "[{name:'密码错误'}]"));
          return;
        } else {
          response.writeHead(200);
          settings.modules.tournament_mode.duel_log = [];
          nconf.myset(settings, "modules:tournament_mode:duel_log", settings.modules.tournament_mode.duel_log);
          response.end(addCallback(u.query.callback, "[{name:'Success'}]"));
        }
mercury233's avatar
mercury233 committed
2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528
      } else if (_.startsWith(u.pathname, '/api/replay') && settings.modules.tournament_mode.enabled) {
        if (!(u.query.pass === settings.modules.tournament_mode.password)) {
          response.writeHead(403);
          response.end("密码错误");
          return;
        } else {
          getpath = u.pathname.split("/");
          filename = decodeURIComponent(getpath.pop());
          fs.readFile(settings.modules.tournament_mode.replay_path + filename, function(error, buffer) {
            if (error) {
              response.writeHead(404);
              return response.end("未找到文件 " + filename);
            } else {
              response.writeHead(200, {
                "Content-Type": "application/octet-stream",
                "Content-Disposition": "attachment"
              });
              return response.end(buffer);
            }
          });
        }
2529 2530 2531
      } else if (u.pathname === '/api/message') {
        if (!pass_validated) {
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2532
          response.end(addCallback(u.query.callback, "['密码错误', 0]"));
2533 2534 2535
          return;
        }
        if (u.query.shout) {
nanahira's avatar
nanahira committed
2536 2537
          for (k = 0, len1 = ROOM_all.length; k < len1; k++) {
            room = ROOM_all[k];
2538 2539 2540
            if (room && room.established) {
              ygopro.stoc_send_chat_to_room(room, u.query.shout, ygopro.constants.COLORS.YELLOW);
            }
2541 2542
          }
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2543
          response.end(addCallback(u.query.callback, "['shout ok', '" + u.query.shout + "']"));
2544 2545 2546 2547 2548 2549
        } else if (u.query.stop) {
          if (u.query.stop === 'false') {
            u.query.stop = false;
          }
          settings.modules.stop = u.query.stop;
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2550
          response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']"));
2551
        } else if (u.query.welcome) {
mercury233's avatar
mercury233 committed
2552 2553
          nconf.myset(settings, 'modules:welcome', u.query.welcome);
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2554
          response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']"));
mercury233's avatar
mercury233 committed
2555
        } else if (u.query.getwelcome) {
2556
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2557
          response.end(addCallback(u.query.callback, "['get ok', '" + settings.modules.welcome + "']"));
mercury233's avatar
mercury233 committed
2558 2559 2560
        } else if (u.query.loadtips) {
          load_tips();
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2561
          response.end(addCallback(u.query.callback, "['loading tip', '" + settings.modules.tips.get + "']"));
mercury233's avatar
mercury233 committed
2562 2563 2564
        } else if (u.query.loaddialogues) {
          load_dialogues();
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2565
          response.end(addCallback(u.query.callback, "['loading dialogues', '" + settings.modules.dialogues.get + "']"));
mercury233's avatar
mercury233 committed
2566
        } else if (u.query.ban) {
mercury233's avatar
mercury233 committed
2567
          ban_user(u.query.ban);
mercury233's avatar
mercury233 committed
2568
          response.writeHead(200);
mercury233's avatar
mercury233 committed
2569
          response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"));
nanahira's avatar
nanahira committed
2570 2571 2572 2573 2574 2575 2576 2577
        } else if (u.query.death) {
          death_room_found = false;
          for (l = 0, len2 = ROOM_all.length; l < len2; l++) {
            room = ROOM_all[l];
            if (!(room && room.established && room.started && !room.death && (u.query.death === "all" || u.query.death === room.port.toString()))) {
              continue;
            }
            death_room_found = true;
nanahira's avatar
nanahira committed
2578
            if (!room.changing_side) {
nanahira's avatar
nanahira committed
2579 2580 2581
              room.death = (room.turn ? room.turn + 4 : 5);
              ygopro.stoc_send_chat_to_room(room, "${death_start}", ygopro.constants.COLORS.BABYBLUE);
            } else {
nanahira's avatar
nanahira committed
2582
              if (settings.modules.http.quick_death_rule) {
nanahira's avatar
fix  
nanahira committed
2583
                room.death = -1;
nanahira's avatar
nanahira committed
2584 2585
                ygopro.stoc_send_chat_to_room(room, "${death_start_quick}", ygopro.constants.COLORS.BABYBLUE);
              } else {
nanahira's avatar
fix  
nanahira committed
2586
                room.death = 5;
nanahira's avatar
nanahira committed
2587 2588
                ygopro.stoc_send_chat_to_room(room, "${death_start_siding}", ygopro.constants.COLORS.BABYBLUE);
              }
nanahira's avatar
nanahira committed
2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613
            }
          }
          response.writeHead(200);
          if (death_room_found) {
            response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']"));
          } else {
            response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']"));
          }
        } else if (u.query.deathcancel) {
          death_room_found = false;
          for (m = 0, len3 = ROOM_all.length; m < len3; m++) {
            room = ROOM_all[m];
            if (!(room && room.established && room.started && room.death && (u.query.deathcancel === "all" || u.query.deathcancel === room.port.toString()))) {
              continue;
            }
            death_room_found = true;
            room.death = 0;
            ygopro.stoc_send_chat_to_room(room, "${death_cancel}", ygopro.constants.COLORS.BABYBLUE);
          }
          response.writeHead(200);
          if (death_room_found) {
            response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']"));
          } else {
            response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']"));
          }
2614
        } else {
mercury233's avatar
mercury233 committed
2615
          response.writeHead(400);
2616
          response.end();
2617
        }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2618
      } else {
mercury233's avatar
mercury233 committed
2619
        response.writeHead(400);
mercury233's avatar
test3  
mercury233 committed
2620
        response.end();
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2621
      }
2622 2623
    };
    http_server = http.createServer(requestListener);
神楽坂玲奈's avatar
神楽坂玲奈 committed
2624
    http_server.listen(settings.modules.http.port);
mercury233's avatar
mercury233 committed
2625
    if (settings.modules.http.ssl.enabled) {
2626 2627 2628 2629 2630 2631
      https = require('https');
      options = {
        cert: fs.readFileSync(settings.modules.http.ssl.cert),
        key: fs.readFileSync(settings.modules.http.ssl.key)
      };
      https_server = https.createServer(options, requestListener);
mercury233's avatar
fix  
mercury233 committed
2632
      roomlist.init(https_server, ROOM_all);
2633 2634
      https_server.listen(settings.modules.http.ssl.port);
    }
神楽坂玲奈's avatar
11.7  
神楽坂玲奈 committed
2635
  }
神楽坂玲奈's avatar
神楽坂玲奈 committed
2636

神楽坂玲奈's avatar
init  
神楽坂玲奈 committed
2637
}).call(this);