29 class IrcParser implements \Erebot\Interfaces\IrcParser
32 const STRIP_NONE = 0x00;
34 const STRIP_COLORS = 0x01;
36 const STRIP_BOLD = 0x02;
38 const STRIP_UNDERLINE = 0x04;
40 const STRIP_REVERSE = 0x08;
42 const STRIP_RESET = 0x10;
44 const STRIP_ALL = 0xFF;
68 public function __construct(\Erebot\Interfaces\Connection $connection)
70 $this->connection = $connection;
71 $this->eventsMapping = array();
88 public static function stripCodes($text, $strip = self::STRIP_ALL)
90 if (!is_int($strip)) {
91 throw new \Erebot\InvalidValueException(
"Invalid stripping flags");
94 if ($strip & self::STRIP_BOLD) {
95 $text = str_replace(
"\002",
'', $text);
98 if ($strip & self::STRIP_COLORS) {
99 $text = preg_replace(
"/\003(?:[0-9]{1,2}(?:,[0-9]{1,2})?)?/",
'', $text);
102 if ($strip & self::STRIP_RESET) {
103 $text = str_replace(
"\017",
'', $text);
106 if ($strip & self::STRIP_REVERSE) {
107 $text = str_replace(
"\026",
'', $text);
110 if ($strip & self::STRIP_UNDERLINE) {
111 $text = str_replace(
"\037",
'', $text);
129 $args = func_get_args();
132 $iface = str_replace(
'!',
'\\Erebot\\Interfaces\\Event\\', $iface);
133 $iface = strtolower($iface);
135 if (!isset($this->eventsMapping[$iface])) {
136 throw new \Erebot\NotFoundException(
'No such declared interface');
142 $args[0] = $this->connection;
143 $cls = new \ReflectionClass($this->eventsMapping[$iface]);
144 $instance = $cls->newInstanceArgs($args);
169 $msg = strtr($msg, $quoting);
176 "\020\020" =>
"\020",
180 $msg = strtr($msg, $quoting);
199 $iface = str_replace(
'!',
'\\Erebot\\Interfaces\\Event\\', $iface);
200 $iface = strtolower($iface);
202 return isset($this->eventsMapping[$iface])
203 ? $this->eventsMapping[$iface]
217 return $this->eventsMapping;
230 foreach ($events as $iface => $cls) {
231 $this->setEventClass($iface, $cls);
250 $iface = str_replace(
'!',
'\\Erebot\\Interfaces\\Event\\', $iface);
251 if (!interface_exists($iface)) {
252 throw new \Erebot\InvalidValueException(
253 'The given interface ('.$iface.
') does not exist'
257 $iface = strtolower($iface);
258 $reflector = new \ReflectionClass($cls);
259 if (!$reflector->implementsInterface($iface)) {
260 throw new \Erebot\InvalidValueException(
261 'The given class does not implement that interface'
264 $this->eventsMapping[$iface] = $cls;
278 if (!strncmp($msg,
':', 1)) {
279 $pos = strcspn($msg,
' ');
280 $origin = (string) substr($msg, 1, $pos - 1);
281 $msg = new \Erebot\IrcTextWrapper((
string) substr($msg, $pos + 1));
285 $msg = new \Erebot\IrcTextWrapper($msg);
289 $type = strtoupper($type);
292 $method =
'handle'.$type;
293 $exists = method_exists($this, $method);
296 $backup = clone $msg;
299 $res = $this->$method($origin, $msg);
302 if (ctype_digit($type)) {
304 $target = $backup[0];
306 return $this->connection->dispatch(
353 $isChan = (int) $this->connection->isChannel($target);
355 if ($len > 1 && $msg[$len-1] ==
"\x01" && $msg[0] ==
"\x01") {
357 $msg = (string) substr($msg, 1, -1);
359 $msg = self::ctcpUnquote($msg);
361 $pos = strcspn($msg,
" ");
362 $ctcp = substr($msg, 0, $pos);
363 $msg = (string) substr($msg, $pos + 1);
365 if ($ctcp ==
"ACTION") {
367 return $this->connection->dispatch(
368 $this->makeEvent($mapping[
'action'][$isChan], $target, $origin, $msg)
372 return $this->connection->dispatch(
373 $this->makeEvent($mapping[
'action'][$isChan], $origin, $msg)
378 return $this->connection->dispatch(
379 $this->makeEvent($mapping[
'ctcp'][$isChan], $target, $origin, $ctcp, $msg)
383 return $this->connection->dispatch(
384 $this->makeEvent($mapping[
'ctcp'][$isChan], $origin, $ctcp, $msg)
389 return $this->connection->dispatch(
391 $mapping[
'normal'][$isChan],
399 return $this->connection->dispatch(
400 $this->makeEvent($mapping[
'normal'][$isChan], $origin, $msg)
418 return $this->connection->dispatch(
419 $this->makeEvent(
'!Invite', $msg[1], $origin, $msg[0])
437 return $this->connection->dispatch(
438 $this->makeEvent(
'!Join', $msg[0], $origin)
456 return $this->connection->dispatch(
457 $this->makeEvent(
'!Kick', $msg[0], $origin, $msg[1], $msg[2])
478 if (!$this->connection->isChannel($target)) {
479 return $this->connection->dispatch(
480 $this->makeEvent(
'!UserMode', $origin, $target, $msg)
484 $event = $this->makeEvent(
'!RawMode', $target, $origin, $msg);
485 $this->connection->dispatch($event);
486 if ($event->preventDefault(
true)) {
492 $len = strlen($modes);
518 for ($i = 0; $i < $len; $i++) {
519 switch ($modes[$i]) {
535 $cls = $priv[$mode][$modes[$i]];
536 $this->connection->dispatch(
537 $this->makeEvent($cls, $target, $origin, $tnick)
561 return $this->connection->dispatch(
562 $this->makeEvent(
'!Nick', $origin, $msg[0])
582 'action' => array(
'!PrivateCtcpReply',
'!ChanCtcpReply'),
583 'ctcp' => array(
'!PrivateCtcpReply',
'!ChanCtcpReply'),
584 'normal' => array(
'!PrivateNotice',
'!ChanNotice'),
586 return $this->noticeOrPrivmsg($origin, $msg, $mapping);
603 return $this->connection->dispatch(
608 isset($msg[1]) ? $msg[1] :
''
627 return $this->connection->dispatch(
628 $this->makeEvent(
'!Ping', $msg)
646 return $this->connection->dispatch(
647 $this->makeEvent(
'!Pong', $origin, $msg[1])
667 'action' => array(
'!PrivateAction',
'!ChanAction'),
668 'ctcp' => array(
'!PrivateCtcp',
'!ChanCtcp'),
669 'normal' => array(
'!PrivateText',
'!ChanText'),
671 return $this->noticeOrPrivmsg($origin, $msg, $mapping);
688 return $this->connection->dispatch(
689 $this->makeEvent(
'!Quit', $origin, $msg[0])
707 return $this->connection->dispatch(
708 $this->makeEvent(
'!Topic', $msg[0], $origin, $msg[1])
733 if (!$this->connection->isConnected()) {
734 return $this->connection->dispatch($this->makeEvent(
'!Connect'));
755 return $this->watchList(
'!Notify', $msg);
775 return $this->watchList(
'!UnNotify', $msg);
795 return $this->watchList(
'!Notify', $msg);
815 return $this->watchList(
'!UnNotify', $msg);
836 $timestamp = intval($msg[3], 10);
837 $timestamp = new \DateTime(
'@'.$timestamp);
840 return $this->connection->dispatch(
844 ($ident ==
'*' ? null : $ident),
845 ($host ==
'*' ? null : $host),
handleQUIT($origin, $msg)
handleKICK($origin, $msg)
handleMODE($origin, $msg)
handlePART($origin, $msg)
handleNICK($origin, $msg)
handlePING($origin, $msg)
handleNOTICE($origin, $msg)
handleJOIN($origin, $msg)
setEventClass($iface, $cls)
handlePONG($origin, $msg)
A class that can parse IRC messages and produce events to match the commands in those messages...
$connection
IRC connection that will send us some messages to parse.
handleTOPIC($origin, $msg)
static stripCodes($text, $strip=self::STRIP_ALL)
$eventsMapping
Mappings from (lowercase) interface names to actual classes.
__construct(\Erebot\Interfaces\Connection $connection)
handlePRIVMSG($origin, $msg)
handleINVITE($origin, $msg)
noticeOrPrivmsg($origin, $msg, $mapping)