PageRenderTime 45ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 0ms

/rcon/executors/rcon2irc-core.php

https://gitlab.com/mattia.basaglia/Melanobot
PHP | 727 lines | 576 code | 66 blank | 85 comment | 69 complexity | e5a52c7b8b10be924bd6234204dc041f MD5 | raw file
Possible License(s): AGPL-3.0
  1. <?php
  2. /**
  3. * \file
  4. * \author Mattia Basaglia
  5. * \copyright Copyright 2013-2014 Mattia Basaglia
  6. * \section License
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU Affero General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU Affero General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Affero General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. require_once("rcon/executors/rcon-abstract.php");
  21. /**
  22. * \brief Send chat messages from rcon to IRC
  23. *
  24. * \bug If a player has the string "^7: " in their nick it won't be shown correctlt
  25. * This can be fixed by checking all the player names with the beginning of the string (passed \1)
  26. * But maybe it's not worth doing
  27. */
  28. class Rcon2Irc_Say extends Rcon2Irc_Executor
  29. {
  30. function __construct()
  31. {
  32. parent::__construct("{^\1(.*?)\^7: (.*)}");
  33. }
  34. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  35. {
  36. $nick = Color::dp2irc($cmd->params[1]);
  37. $text = Color::dp2irc($cmd->params[2]);
  38. $bot->say($cmd->channel,"{$rcon->out_prefix}<$nick\xf> $text",-16);
  39. return true;
  40. }
  41. }
  42. /**
  43. * \brief Ban by nick
  44. */
  45. class Rcon2Irc_BanNick extends Rcon2Irc_Executor
  46. {
  47. public $banned = array();
  48. public $case_sensitive = false;
  49. function __construct($banned)
  50. {
  51. parent::__construct("{^:join:(\d+):(\d+):((?:[0-9]+(?:\.[0-9]+){3})|(?:[[:xdigit:]](?::[[:xdigit:]]){7})):(.*)}");
  52. $this->banned = $banned;
  53. }
  54. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  55. {
  56. list ($id, $slot, $ip, $name) = array_splice($cmd->params,1);
  57. $name_plain = Color::dp2none($name);
  58. foreach( $this->banned as $ban )
  59. if ( stripos($name_plain,$ban) !== false )
  60. {
  61. $bot->say($cmd->channel,$rcon->out_prefix.Color::dp2irc($name)." ($ip) has been auto-banned",16);
  62. $rcon->send("kickban #$slot");
  63. break;
  64. }
  65. return false;
  66. }
  67. }
  68. /**
  69. *
  70. * Format variables:
  71. * - %name% player name (colored)
  72. * - %ip% player IP address
  73. * - %slot% player slot
  74. * - %country% player country
  75. * - %region% player region
  76. * - %city% player city
  77. * - %players% number of connected players (not bots)
  78. * - %bots% number of bots
  79. * - %total% number of clients (players+bots)
  80. * - %max% maximum number of players
  81. * - %free% free slots
  82. * - %gametype% long gametype name (eg: deathmatch)
  83. * - %gt% short gametype name (eg: dm)
  84. * - %sv_host% server host name
  85. * - %sv_ip% server IP address
  86. */
  87. abstract class Rcon2Irc_JoinPart_Base extends Rcon2Irc_Executor
  88. {
  89. public $format;
  90. function __construct($regex,$format)
  91. {
  92. parent::__construct($regex);
  93. $this->format = $format;
  94. }
  95. protected function string_replace($string,RconPlayer $player,Rcon_Communicator $rcon)
  96. {
  97. $gametype = isset($rcon->data->gametype) ? $rcon->data->gametype : "";
  98. $geoip = $player->geoip_record();
  99. $values = array(
  100. '%name%' => Color::dp2irc($player->name),
  101. '%ip%' => $player->ip,
  102. '%slot%' => $player->slot,
  103. '%players%' => $rcon->data->player->count_players(),
  104. '%bots%' => $rcon->data->player->count_bots(),
  105. '%total%' => $rcon->data->player->count_all(),
  106. '%max%' => $rcon->data->player->max,
  107. '%free%' => ($rcon->data->player->max-$rcon->data->player->count_players()),
  108. '%map%' => $rcon->data->map,
  109. '%country%' => $geoip ? $geoip->country_name : $player->country(),
  110. '%region%' => $geoip ? $geoip->region_name : "",
  111. '%city%' => $geoip ? $geoip->city : "",
  112. '%gametype%'=> $rcon->gametype_name($gametype),
  113. '%gt%' => $gametype,
  114. '%sv_host%' => $rcon->data->hostname,
  115. '%sv_ip%' => $rcon->write_server,
  116. );
  117. return str_replace(array_keys($values),array_values($values),$string);
  118. }
  119. protected function send_message(MelanoBot $bot,$channel,$player,Rcon_Communicator $rcon)
  120. {
  121. if ( !$player || $player->is_bot() )
  122. return;
  123. $bot->say($channel,$rcon->out_prefix.$this->string_replace($this->format,$player,$rcon),1);
  124. }
  125. }
  126. /**
  127. * \brief Show +join messages
  128. */
  129. class Rcon2Irc_Join extends Rcon2Irc_JoinPart_Base
  130. {
  131. function __construct($format="\00309+ join\xf: %name% \00304%map%\xf [\00304%players%\xf/\00304%max%\xf]")
  132. {
  133. parent::__construct("{^:join:(\d+):(\d+):((?:[0-9]+(?:\.[0-9]+){3})|(?:[[:xdigit:]](?::[[:xdigit:]]){7})):(.*)}", $format);
  134. }
  135. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  136. {
  137. $player = new RconPlayer();
  138. list ($player->id, $player->slot, $player->ip, $player->name) = array_splice($cmd->params,1);
  139. $already = $rcon->data->player->find($player->slot);
  140. $rcon->data->player->add($player);
  141. if ( $already == null || $already->name != $player->name || $already->id != $player->id )
  142. $this->send_message($bot,$cmd->channel,$player,$rcon);
  143. return true;
  144. }
  145. }
  146. /**
  147. * \brief Show -part messages
  148. */
  149. class Rcon2Irc_Part extends Rcon2Irc_JoinPart_Base
  150. {
  151. function __construct($format="\00304- part\xf: %name% \00304%map%\xf [\00304%players%\xf/\00304%max%\xf]")
  152. {
  153. parent::__construct("{^:part:(\d+)}",$format);
  154. }
  155. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  156. {
  157. $player = $rcon->data->player->find_by_id($cmd->params[1]);
  158. if ( $player && !$player->is_bot() )
  159. {
  160. $rcon->data->player->remove($player->slot);
  161. $this->send_message($bot,$cmd->channel,$player,$rcon);
  162. }
  163. return true;
  164. }
  165. }
  166. /**
  167. * \brief Remove most of the useless Xonotic garbage log
  168. */
  169. class Rcon2Irc_Filter_BlahBlah extends Rcon2Irc_Filter
  170. {
  171. public $stuff = array(
  172. "^Map .* supports unknown game type .*",
  173. "^LHNET_Write: sendto returned error: Network is unreachable",
  174. "^Invalid sound info line: .*",
  175. '^[-_./a-zA-Z0-9]+ parsing warning: unknown surfaceparm "[a-zA-Z]+"',
  176. "^waypoint_load_links: couldn't find .*",
  177. "^WARNING: weapon model .*",
  178. "^Shader '.*' already defined.*",
  179. "^PRVM_LoadProgs: no cvar for autocvar global .*",
  180. "^plane [-0-9. ]* mismatches dist .*",
  181. "^Couldn't select .*",
  182. "^SHUFFLE: insert pos .*",
  183. "^Map .* contains the legacy 'type' keyword.*",
  184. "^Map .* provides unknown info item .*",
  185. "^Mod_LoadQ3Shaders: .*",
  186. "^Unstuck player entity .*",
  187. "^WARNING: autogenerated mapinfo file .*",
  188. );
  189. function filter(Rcon_Command $cmd,Rcon_Communicator $rcon)
  190. {
  191. foreach($this->stuff as $r)
  192. if ( preg_match("{{$r}}",$cmd->data) )
  193. return false;
  194. return !preg_match("{server received rcon command from {$rcon->read_server}:.*}",$cmd->data);
  195. }
  196. }
  197. /**
  198. * \brief Show score table at the end of each match
  199. */
  200. class Rcon2Irc_Score extends Rcon2Irc_Executor
  201. {
  202. protected $player_scores= array();
  203. protected $spectators = array();
  204. protected $team_scores = array();
  205. public $team_colors = array(5 => Color::RED,
  206. 14 => Color::BLUE,
  207. 13 => Color::YELLOW,
  208. 10 => Color::MAGENTA );
  209. protected $lms = false;
  210. protected $sort_reverse = false;
  211. public $show_spectators;
  212. function __construct($show_spectators = true)
  213. {
  214. $re=array("(:end)",// 1
  215. "(:teamscores:see-labels:(-?\d+)[-0-9,]*:(\d+))", // 2 - score=3 id=4
  216. "(:player:see-labels:(-?\d+)[-0-9,]*:(\d+):([^:]+):(\d+):(.*))",// 5 - score=6 time=7 team=8 id=9 name=10
  217. "(:scores:([a-z]+)_(.*)):",//11 gametype=12 map=13
  218. "(:labels:player:([^[,<!]*)(<?)!!,.*)",//14 primary=15 sort=16
  219. );
  220. parent::__construct("{^".implode("|",$re)."}");
  221. $this->show_spectators = $show_spectators;
  222. }
  223. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  224. {
  225. if ( !empty($cmd->params[1]) )
  226. {
  227. if ( !empty($this->player_scores) )
  228. {
  229. $gametype = "";
  230. if ( isset($rcon->data->gametype) )
  231. $gametype = "\00310".$rcon->gametype_name($rcon->data->gametype)."\xf on ";
  232. $map = isset($rcon->data->map) && $rcon->data->map ? $rcon->data->map : "?";
  233. $show_scores = $this->show_spectators ||
  234. ($rcon->data->player->count_players()-count($this->spectators) > 0);
  235. $bot->say($cmd->channel,"{$rcon->out_prefix}$gametype\00304$map\017 ended".
  236. ($show_scores?":":""));
  237. if ($show_scores)
  238. $this->print_scores($cmd,$bot);
  239. $this->player_scores= array();
  240. $this->spectators = array();
  241. $this->team_scores = array();
  242. $this->lms = false;
  243. $this->sort_reverse = false;
  244. $rcon->data->gametype=null;
  245. return true;
  246. }
  247. }
  248. else if ( !empty($cmd->params[2]) )
  249. {
  250. $this->gather_team($cmd,$rcon);
  251. }
  252. else if ( !empty($cmd->params[5]) )
  253. {
  254. $this->gather_player($cmd,$rcon);
  255. }
  256. else if ( !empty($cmd->params[11]) )
  257. {
  258. $rcon->data->map = $cmd->params[13];
  259. $rcon->data->gametype = $cmd->params[12];
  260. }
  261. else if ( !empty($cmd->params[14]) )
  262. {
  263. $this->seen_labels($cmd);
  264. }
  265. return false;
  266. }
  267. protected function seen_labels(Rcon_Command $cmd)
  268. {
  269. if ( $cmd->params[15] == "rank" )
  270. $this->lms = true;
  271. if ( $cmd->params[16] == "<" )
  272. $this->sort_reverse = true;
  273. }
  274. protected function player_score( $player,$color)
  275. {
  276. $name = $player->name;
  277. if ( $color != null )
  278. $name = $color->irc().Color::dp2none($name)."\xf";
  279. else
  280. $name = Color::dp2irc($name);
  281. $score = $player->frags;
  282. return "\002".sprintf('%3s',$score)."\xf $name";
  283. }
  284. protected function print_spectators(Rcon_Command $cmd, MelanoBot $bot)
  285. {
  286. if ( $this->show_spectators )
  287. foreach($this->spectators as $p )
  288. $bot->say($cmd->channel," ".Color::dp2irc($p->name),-1);
  289. }
  290. protected function score_compare($a,$b)
  291. {
  292. /*if ( $a->team == 'spectator' && $b->team == 'spectator' ) return 0;
  293. if ( $a->team == 'spectator' ) return 1;
  294. if ( $b->team == 'spectator' ) return -1;*/
  295. return $a->frags == $b->frags ? 0 : ( $a->frags > $b->frags ? -1 : +1 );
  296. }
  297. protected function sort_players()
  298. {
  299. usort($this->player_scores,'Rcon2Irc_Score::score_compare');
  300. if ( $this->sort_reverse )
  301. $this->player_scores = array_reverse($this->player_scores);
  302. }
  303. protected function print_scores(Rcon_Command $cmd, MelanoBot $bot)
  304. {
  305. $this->sort_players();
  306. if ( empty($this->team_scores) )
  307. {
  308. foreach($this->player_scores as $p )
  309. $bot->say($cmd->channel,$this->player_score($p,null),-1);
  310. $this->print_spectators($cmd,$bot);
  311. }
  312. else
  313. {
  314. $ts = array();
  315. foreach($this->team_scores as $team => $score )
  316. {
  317. $color = new Color($this->team_colors[$team],true);
  318. $ts[$team] = $color->irc()."$score\xf";
  319. }
  320. $bot->say($cmd->channel,"Team Scores: ".implode(":",array_values($ts)));
  321. foreach(array_keys($ts) as $team )
  322. {
  323. $color = isset($this->team_colors[$team]) ? new Color($this->team_colors[$team],true) : null;
  324. foreach($this->player_scores as $p )
  325. {
  326. if ( $p->team == $team )
  327. $bot->say($cmd->channel,$this->player_score($p,$color),-1);
  328. }
  329. }
  330. $this->print_spectators($cmd,$bot);
  331. }
  332. }
  333. protected function gather_team(Rcon_Command $cmd, Rcon_Communicator $rcon)
  334. {
  335. $this->team_scores[ $cmd->params[4] ] = $cmd->params[3];
  336. }
  337. protected function gather_player(Rcon_Command $cmd, Rcon_Communicator $rcon)
  338. {
  339. $player = new RconPlayer;
  340. list ($player->frags, $player->time, $player->team, $player->id, $player->name) = array_splice($cmd->params,6);
  341. $is_player = true;
  342. if ( $existing_player = $rcon->data->player->find_by_id($player->id) )
  343. {
  344. if ( $existing_player->is_bot() )
  345. $is_player = false;
  346. $existing_player->merge($player);
  347. }
  348. if ( $this->lms && $player->frags == 0 && $player->team == -1 )
  349. $player->team = "spectator";
  350. if ( $player->team == "spectator" )
  351. {
  352. $this->spectators []= $player;
  353. }
  354. else
  355. {
  356. $this->player_scores []= $player;
  357. }
  358. }
  359. }
  360. class Rcon2Irc_Score_Inline extends Rcon2Irc_Score
  361. {
  362. function __construct($show_spectators = false)
  363. {
  364. parent::__construct($show_spectators);
  365. }
  366. protected function player_score( $player,$color)
  367. {
  368. $name = $player->name;
  369. if ( $color != null )
  370. $name = $color->irc().Color::dp2none($name)."\xf";
  371. else
  372. $name = Color::dp2irc($name);
  373. $score = $player->frags;
  374. return "\002$score\xf $name";
  375. }
  376. protected function print_spectators(Rcon_Command $cmd, MelanoBot $bot)
  377. {
  378. if ( $this->show_spectators )
  379. {
  380. $score_string = array();
  381. foreach($this->player_scores as $p )
  382. if ( $p->team == 'spectator' )
  383. $score_string[] = Color::dp2irc($p->name);
  384. $bot->say($cmd->channel,implode(", ",$score_string),-1);
  385. }
  386. }
  387. protected function print_scores(Rcon_Command $cmd, MelanoBot $bot)
  388. {
  389. usort($this->player_scores,'Rcon2Irc_Score::score_compare');
  390. if ( empty($this->team_scores) )
  391. {
  392. $score_string = array();
  393. foreach($this->player_scores as $p )
  394. if ( $this->show_spectators || $p->team != 'spectator' )
  395. $score_string[] = $this->player_score($p,null);
  396. $bot->say($cmd->channel,implode(", ",$score_string),-1);
  397. $this->print_spectators($cmd,$bot);
  398. }
  399. else
  400. {
  401. $ts = array();
  402. foreach($this->team_scores as $team => $score )
  403. {
  404. $color = new Color($this->team_colors[$team],true);
  405. $ts[$team] = $color->irc()."$score\xf";
  406. }
  407. $bot->say($cmd->channel,"Team Scores: ".implode(":",array_values($ts)));
  408. foreach(array_keys($ts) as $team )
  409. {
  410. $color = isset($this->team_colors[$team]) ? new Color($this->team_colors[$team],true) : null;
  411. $score_string = array();
  412. foreach($this->player_scores as $p )
  413. {
  414. if ( $p->team == $team )
  415. $score_string[] = $this->player_score($p,$color);
  416. }
  417. $bot->say($cmd->channel,implode(", ",$score_string),-1);
  418. }
  419. $this->print_spectators($cmd,$bot);
  420. }
  421. }
  422. }
  423. /**
  424. * \brief Notify that a new match has started
  425. *
  426. * Format variables:
  427. * - %players% number of connected players (not bots)
  428. * - %bots% number of bots
  429. * - %total% number of clients (players+bots)
  430. * - %max% maximum number of players
  431. * - %free% free slots
  432. * - %gametype% long gametype name (eg: deathmatch)
  433. * - %gt% short gametype name (eg: dm)
  434. * - %sv_host% server host name
  435. * - %sv_ip% server IP address
  436. */
  437. class Rcon2Irc_MatchStart extends Rcon2Irc_Executor
  438. {
  439. public $message;
  440. function __construct($message = "Playing \00310%gametype%\xf on \00304%map%\xf (%free% free slots); join now: \2xonotic +connect %sv_ip%")
  441. {
  442. parent::__construct("{^:gamestart:([a-z]+)_(.*):[0-9.]*}");
  443. $this->message = $message;
  444. }
  445. protected function send_message(MelanoBot $bot,$channel,Rcon_Communicator $rcon)
  446. {
  447. $gametype = isset($rcon->data->gametype) ? $rcon->data->gametype : "";
  448. $values = array(
  449. '%players%' => $rcon->data->player->count_players(),
  450. '%bots%' => $rcon->data->player->count_bots(),
  451. '%total%' => $rcon->data->player->count_all(),
  452. '%max%' => $rcon->data->player->max,
  453. '%free%' => ($rcon->data->player->max-$rcon->data->player->count_players()),
  454. '%map%' => $rcon->data->map,
  455. '%gametype%'=> $rcon->gametype_name($gametype),
  456. '%gt%' => $gametype,
  457. '%sv_host%' => $rcon->data->hostname,
  458. '%sv_ip%' => $rcon->write_server,
  459. );
  460. $bot->say($channel,$rcon->out_prefix.str_replace(array_keys($values),array_values($values),$this->message),-1);
  461. }
  462. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  463. {
  464. if ( $rcon->data->player->count_players() < 1 )
  465. return false;
  466. $rcon->data->gametype=$cmd->params[1];
  467. $rcon->data->map = $cmd->params[2];
  468. $this->send_message($bot,$cmd->channel,$rcon);
  469. return true;
  470. }
  471. }
  472. /**
  473. * \brief instead of polling regularly only poll on game start
  474. * \note Install before Rcon2Irc_MatchStart
  475. */
  476. class Rcon2Irc_SlowPolling extends Rcon2Irc_Executor
  477. {
  478. public $commands;
  479. function __construct($commands)
  480. {
  481. parent::__construct("{^:gamestart:.*}");
  482. $this->commands = $commands;
  483. }
  484. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  485. {
  486. foreach($this->commands as $pc )
  487. $rcon->send($pc);
  488. return false;
  489. }
  490. }
  491. /**
  492. * \brief Detect cvar changes and save them to data
  493. * \note it won't work properly for cvars that have " in their value
  494. */
  495. class Rcon2Irc_GetCvars extends Rcon2Irc_Executor
  496. {
  497. function __construct()
  498. {
  499. parent::__construct('{^"([^"]+)" is "([^"]*)"}');
  500. }
  501. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  502. {
  503. $rcon->data->cvar[$cmd->params[1]] = $cmd->params[2];
  504. return false;
  505. }
  506. }
  507. class Rcon2Irc_Votes extends Rcon2Irc_Executor
  508. {
  509. function __construct()
  510. {
  511. $re=array("(vcall:(\d+):(.*))",// 1 - userid=2 vote=3
  512. // 4 - result=5 yes=6 no=7 abstain=8 not=9 min=10
  513. "(v(yes|no|timeout):(\d+):(\d+):(\d+):(\d+):(-?\d+))",
  514. "(vstop:(\d+))", // 11 - userid=12
  515. "(vlogin:(\d+))", // 13 - userid=14
  516. "(vdo:(\d+):(.*))",// 15 - userid=16 vote=17
  517. );
  518. parent::__construct("{^:vote:".implode("|",$re)."}");
  519. }
  520. function id2nick($id,Rcon_Communicator $rcon)
  521. {
  522. $name = "(unknown)";
  523. if ( $id == 0 )
  524. {
  525. if ( !empty($rcon->data->cvar["sv_adminnick"]) )
  526. $name = $rcon->data->cvar["sv_adminnick"];
  527. else
  528. $name = "(server admin)";
  529. }
  530. else if ( $player = $rcon->data->player->find_by_id($id) )
  531. $name = Color::dp2irc($player->name);
  532. return $name;
  533. }
  534. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  535. {
  536. $p="{$rcon->out_prefix}\00312*\xf";
  537. if ( !empty($cmd->params[1]) )
  538. {
  539. $name = $this->id2nick($cmd->params[2],$rcon);
  540. $vote = Color::dp2irc($cmd->params[3]);
  541. $bot->say($cmd->channel,"$p $name calls a vote for $vote");
  542. }
  543. else if ( !empty($cmd->params[4]) )
  544. {
  545. list($result,$yes,$no,$abstain,$not,$min) = array_slice($cmd->params,5);
  546. $msg = "$p vote ";
  547. switch($result)
  548. {
  549. case "yes": $msg.="\00303passed\xf"; break;
  550. case "no": $msg.="\00304failed\xf"; break;
  551. case "timeout": $msg.="\00307timed out\xf"; break;
  552. }
  553. $msg .= ": \00303$yes\xf:\00304$no\xf";
  554. if ( $abstain+=$not ) $msg .= ", $abstain didn't vote";
  555. if ( $min > 0 ) $msg .= " ($min needed)";
  556. $bot->say($cmd->channel,$msg);
  557. }
  558. else if ( !empty($cmd->params[11]) )
  559. {
  560. $name = $this->id2nick($cmd->params[12],$rcon);
  561. $bot->say($cmd->channel,"$p $name stopped the vote");
  562. }
  563. else if ( !empty($cmd->params[13]) )
  564. {
  565. $name = $this->id2nick($cmd->params[14],$rcon);
  566. $bot->say($cmd->channel,"$p $name logged in as \00307master\xf");
  567. }
  568. else if ( !empty($cmd->params[15]) )
  569. {
  570. $name = $this->id2nick($cmd->params[16],$rcon);
  571. $bot->say($cmd->channel,"$p $name used their master status to do ".Color::dp2irc($cmd->params[17]));
  572. }
  573. Rcon_Communicator::restore_sv_adminnick($rcon->data);
  574. return true;
  575. }
  576. }
  577. class Rcon2Irc_UpdateBans extends Rcon2Irc_Executor
  578. {
  579. function __construct()
  580. {
  581. $re=array("(\^2Listing all existing active bans:)",// 1
  582. // 2 - banid=3 ip=4 time=5
  583. "\s*(#([0-9]+): ([./0-9]+) is still banned for (inf|[0-9]+)(?:\.[0-9]+)? seconds)"
  584. );
  585. parent::__construct("{^".implode("|",$re)."}");
  586. }
  587. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  588. {
  589. if ( !empty($cmd->params[1]) )
  590. {
  591. $rcon->data->bans = array();
  592. Logger::log("dp","!", "Ban list \x1b[31mcleared\x1b[0m",3);
  593. }
  594. else if ( !empty($cmd->params[2]) )
  595. {
  596. $b = new StdClass;
  597. $b->ip = $cmd->params[4];
  598. $b->time = $cmd->params[5];
  599. $rcon->data->bans[$cmd->params[3]] = $b;
  600. Logger::log("dp","!",
  601. "\x1b[32mAdding\x1b[0m ban #\x1b[31m{$cmd->params[3]}\x1b[0m: \x1b[36m$b->ip\x1b[0m",3);
  602. }
  603. return false;
  604. }
  605. }
  606. /**
  607. * \brief Show nick changes
  608. */
  609. class Rcon2Irc_Name extends Rcon2Irc_Executor
  610. {
  611. function __construct()
  612. {
  613. parent::__construct("{^:name:(\d+):(.*)}");
  614. }
  615. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  616. {
  617. $player = $rcon->data->player->find_by_id($cmd->params[1]);
  618. if ( $player && !$player->is_bot() )
  619. {
  620. $bot->say($cmd->channel,"{$rcon->out_prefix}\00312*\xf ".Color::dp2irc($player->name).
  621. " is now known as ".Color::dp2irc($cmd->params[2]),-16);
  622. $player->name = $cmd->params[2];
  623. }
  624. return true;
  625. }
  626. }
  627. /**
  628. * \brief Detect active mutators and save them to data
  629. */
  630. class Rcon2Irc_GetMutators extends Rcon2Irc_Executor
  631. {
  632. function __construct()
  633. {
  634. parent::__construct('{^:gameinfo:mutators:LIST:(.*)}');
  635. }
  636. function execute(Rcon_Command $cmd, MelanoBot $bot, Rcon_Communicator $rcon)
  637. {
  638. $rcon->data->mutators = explode(":",$cmd->params[1]);
  639. Logger::log("dp","!","Mutators: \x1b[1m".
  640. implode("\x1b[22m, \x1b[1m",$rcon->data->mutators)."\x1b[0m");
  641. return false;
  642. }
  643. }