Hoa central
Client.php
Go to the documentation of this file.
1 <?php
2 
37 namespace Hoa\Irc;
38 
39 use Hoa\Core;
40 use Hoa\Socket;
41 
50 class Client
52  implements Core\Event\Listenable
53 {
59  protected $_on = null;
60 
61 
62 
70  public function __construct(Socket\Client $client)
71  {
72  parent::__construct($client);
73  $this->getConnection()->setNodeName('\Hoa\Irc\Node');
74  $this->_on = new Core\Event\Listener(
75  $this,
76  [
77  'open',
78  'join',
79  'message',
80  'private-message',
81  'mention',
82  'other-message',
83  'ping',
84  'kick',
85  'invite',
86  'error'
87  ]
88  );
89 
90  return;
91  }
92 
101  public function on($listenerId, $callable)
102  {
103  $this->_on->attach($listenerId, $callable);
104 
105  return $this;
106  }
107 
114  protected function _run(Socket\Node $node)
115  {
116  if (false === $node->hasJoined()) {
117  $node->setJoined(true);
118  $this->_on->fire('open', new Core\Event\Bucket());
119 
120  return;
121  }
122 
123  try {
124  $line = $node->getConnection()->readLine();
125 
126  preg_match(
127  '#^(?::(?<prefix>[^\s]+)\s+)?(?<command>[^\s]+)\s+(?<middle>[^:]+)?(:\s*(?<trailing>.+))?$#',
128  $line,
129  $matches
130  );
131 
132  if (!isset($matches['command'])) {
133  $matches['command'] = null;
134  }
135 
136  switch ($matches['command']) {
137  case 366: // RPL_ENDOFNAMES
138  list($nickname, $channel) = explode(' ', $matches['middle'], 2);
139  $node->setChannel($channel);
140 
141  $listener = 'join';
142  $bucket = [
143  'nickname' => $nickname,
144  'channel' => trim($channel)
145  ];
146 
147  break;
148 
149  case 'PRIVMSG':
150  $middle = trim($matches['middle']);
151  $message = $matches['trailing'];
152  $username = $node->getUsername();
153 
154  if ($username === $middle) {
155  $listener = 'private-message';
156  } elseif (false !== strpos($message, $username)) {
157  $node->setChannel($middle);
158  $listener = 'mention';
159  } else {
160  $node->setChannel($middle);
161  $listener = 'message';
162  }
163 
164  $bucket = [
165  'from' => $this->parseNick($matches['prefix']),
166  'message' => $message
167  ];
168 
169  break;
170 
171  case 'PING':
172  $daemons = explode(' ', $matches['trailing']);
173  $listener = 'ping';
174  $bucket = [
175  'daemons' => $daemons
176  ];
177 
178  if (isset($daemons[1])) {
179  $this->pong($daemons[0], $daemons[1]);
180  } else {
181  $this->pong($daemons[0]);
182  }
183 
184  break;
185 
186  case 'KICK':
187  list($channel, ) = explode(' ', $matches['middle'], 2);
188  $node->setChannel($channel);
189 
190  $listener = 'kick';
191  $bucket = [
192  'from' => $this->parseNick($matches['prefix']),
193  'channel' => trim($channel)
194  ];
195 
196  break;
197 
198  case 'INVITE':
199  list($channel, ) = explode(' ', $matches['middle'], 2);
200  $node->setChannel($channel);
201 
202  $listener = 'invite';
203  $bucket = [
204  'from' => $this->parseNick($matches['prefix']),
205  'channel' => trim($channel),
206  'invitation_channel' => trim($matches['trailing'])
207  ];
208 
209  break;
210 
211  default:
212  $listener = 'other-message';
213  $bucket = [
214  'line' => $line,
215  'parsed_line' => $matches
216  ];
217  }
218 
219  $this->_on->fire($listener, new Core\Event\Bucket($bucket));
220  } catch (Core\Exception\Idle $e) {
221  $this->_on->fire(
222  'error',
223  new Core\Event\Bucket([
224  'exception' => $e
225  ])
226  );
227  }
228 
229  return;
230  }
231 
239  protected function _send($message, Socket\Node $node)
240  {
241  return $node->getConnection()->writeAll($message . CRLF);
242  }
243 
252  public function join($username, $channel, $password = null)
253  {
254  if (null !== $password) {
255  $this->send('PASS ' . $password);
256  }
257 
258  $this->send('USER ' . $username . ' 0 * :' . $username);
259 
260  $node = $this->getConnection()->getCurrentNode();
261  $node->setUsername($username);
262  $node->setChannel($channel);
263  $this->setNickname($username);
264 
265  return $this->send('JOIN ' . $channel);
266  }
267 
275  public function say($message, $to = null)
276  {
277  if (null === $to) {
278  $to = $this->getConnection()->getCurrentNode()->getChannel();
279  }
280 
281  foreach (explode("\n", $message) as $line) {
282  $this->send('PRIVMSG ' . $to . ' :' . $line);
283  }
284 
285  return;
286  }
287 
294  public function quit($message = null)
295  {
296  if (null !== $message) {
297  $message = ' ' . $message;
298  }
299 
300  return $this->send('QUIT' . $message);
301  }
302 
309  public function setNickname($nickname)
310  {
311  return $this->send('NICK ' . $nickname);
312  }
313 
321  public function setTopic($topic, $channel = null)
322  {
323  if (null === $channel) {
324  $channel = $this->getConnection()->getCurrentNode()->getChannel();
325  }
326 
327  return $this->send('TOPIC ' . $channel . ' ' . $topic);
328  }
329 
337  public function invite($nickname, $channel = null)
338  {
339  if (null === $channel) {
340  $channel = $this->getConnection()->getCurrentNode()->getChannel();
341  }
342 
343  return $this->send('INVITE ' . $nickname . ' ' . $channel);
344  }
345 
353  public function pong($daemon, $daemon2 = null)
354  {
355  $this->send('PONG ' . $daemon);
356 
357  if (null !== $daemon2) {
358  $this->send('PONG ' . $daemon2);
359  }
360 
361  return;
362  }
363 
370  public function parseNick($nick)
371  {
372  preg_match(
373  '#^(?<nick>[^!]+)!(?<user>[^@]+)@(?<host>.+)$#',
374  $nick,
375  $matches
376  );
377 
378  return $matches;
379  }
380 }
join($username, $channel, $password=null)
Definition: Client.php:252
say($message, $to=null)
Definition: Client.php:275
parseNick($nick)
Definition: Client.php:370
on($listenerId, $callable)
Definition: Client.php:101
setNickname($nickname)
Definition: Client.php:309
_send($message, Socket\Node $node)
Definition: Client.php:239
_run(Socket\Node $node)
Definition: Client.php:114
invite($nickname, $channel=null)
Definition: Client.php:337
send($message, Socket\Node $node=null)
Definition: Handler.php:240
__construct(Socket\Client $client)
Definition: Client.php:70
setTopic($topic, $channel=null)
Definition: Client.php:321
pong($daemon, $daemon2=null)
Definition: Client.php:353
quit($message=null)
Definition: Client.php:294