9 * This source file is subject to the new BSD license that is bundled
10 * with this package in the file LICENSE.
11 * It is also available through the world-wide-web at this URL:
12 * http://phergie.org/license
15 * @package Phergie_Plugin_UserInfo
16 * @author Phergie Development Team <team@phergie.org>
17 * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
18 * @license http://phergie.org/license New BSD License
19 * @link http://pear.phergie.org/package/Phergie_Plugin_UserInfo
23 * Provides an API for querying information on users.
26 * @package Phergie_Plugin_UserInfo
27 * @author Phergie Development Team <team@phergie.org>
28 * @license http://phergie.org/license New BSD License
29 * @link http://pear.phergie.org/package/Phergie_Plugin_UserInfo
31 class Phergie_Plugin_UserInfo extends Phergie_Plugin_Abstract
41 * An array containing all the user information for a given channel
45 protected $store = array();
52 public function onMode()
54 $args = $this->event->getArguments();
56 if (count($args) != 3) {
60 list($chan, $modes, $nicks) = $args;
62 if (!preg_match('/(?:\+|-)[hovaq+-]+/i', $modes)) {
66 $chan = trim(strtolower($chan));
67 $modes = str_split(trim(strtolower($modes)), 1);
68 $nicks = explode(' ', trim(strtolower($nicks)));
69 $operation = array_shift($modes); // + or -
71 while ($char = array_shift($modes)) {
72 $nick = array_shift($nicks);
94 if ($operation == '+') {
95 $this->store[$chan][$nick] |= $mode;
96 } else if ($operation == '-') {
97 $this->store[$chan][$nick] ^= $mode;
104 * Tracks users joining a channel
108 public function onJoin()
110 $chan = trim(strtolower($this->event->getArgument(0)));
111 $nick = trim(strtolower($this->event->getNick()));
113 $this->store[$chan][$nick] = self::REGULAR;
117 * Tracks users leaving a channel
121 public function onPart()
123 $chan = trim(strtolower($this->event->getArgument(0)));
124 $nick = trim(strtolower($this->event->getNick()));
126 if (isset($this->store[$chan][$nick])) {
127 unset($this->store[$chan][$nick]);
132 * Tracks users quitting a server
136 public function onQuit()
138 $nick = trim(strtolower($this->event->getNick()));
140 foreach ($this->store as $chan => $store) {
141 if (isset($store[$nick])) {
142 unset($this->store[$chan][$nick]);
148 * Tracks users changing nicks
152 public function onNick()
154 $nick = trim(strtolower($this->event->getNick()));
155 $newNick = trim(strtolower($this->event->getArgument(0)));
157 foreach ($this->store as $chan => $store) {
158 if (isset($store[$nick])) {
159 $this->store[$chan][$newNick] = $store[$nick];
160 unset($this->store[$chan][$nick]);
166 * Populates the internal user listing for a channel when the bot joins it.
170 public function onResponse()
172 if ($this->event->getCode() != Phergie_Event_Response::RPL_NAMREPLY) {
176 $desc = preg_split('/[@*=]\s*/', $this->event->getDescription(), 2);
177 list($chan, $users) = array_pad(explode(' :', trim($desc[1])), 2, null);
178 $users = explode(' ', trim($users));
180 $chan = trim(strtolower($chan));
182 foreach ($users as $user) {
187 $user = trim(strtolower($user));
188 $flag = self::REGULAR;
190 if ($user[0] == '~') {
191 $flag |= self::OWNER;
192 } else if ($user[0] == '&') {
193 $flag |= self::ADMIN;
194 } else if ($user[0] == '@') {
196 } else if ($user[0] == '%') {
197 $flag |= self::HALFOP;
198 } else if ($user[0] == '+') {
199 $flag |= self::VOICE;
202 if ($flag != self::REGULAR) {
203 $user = substr($user, 1);
206 $this->store[$chan][$user] = $flag;
215 public function onPrivmsg()
217 if ($this->getConfig('debug', false) == false) {
221 list($target, $msg) = array_pad($this->event->getArguments(), 2, null);
223 if (preg_match('#^ishere (\S+)$#', $msg, $m)) {
224 $this->doPrivmsg($target, $this->isIn($m[1], $target) ? 'true' : 'false');
225 } elseif (preg_match('#^isowner (\S+)$#', $msg, $m)) {
226 $this->doPrivmsg($target, $this->isOwner($m[1], $target) ? 'true' : 'false');
227 } elseif (preg_match('#^isadmin (\S+)$#', $msg, $m)) {
228 $this->doPrivmsg($target, $this->isAdmin($m[1], $target) ? 'true' : 'false');
229 } elseif (preg_match('#^isop (\S+)$#', $msg, $m)) {
230 $this->doPrivmsg($target, $this->isOp($m[1], $target) ? 'true' : 'false');
231 } elseif (preg_match('#^ishop (\S+)$#', $msg, $m)) {
232 $this->doPrivmsg($target, $this->isHalfop($m[1], $target) ? 'true' : 'false');
233 } elseif (preg_match('#^isvoice (\S+)$#', $msg, $m)) {
234 $this->doPrivmsg($target, $this->isVoice($m[1], $target) ? 'true' : 'false');
235 } elseif (preg_match('#^channels (\S+)$#', $msg, $m)) {
236 $channels = $this->getChannels($m[1]);
237 $this->doPrivmsg($target, $channels ? join(', ', $channels) : 'unable to find nick');
238 } elseif (preg_match('#^users (\S+)$#', $msg, $m)) {
239 $nicks = $this->getUsers($m[1]);
240 $this->doPrivmsg($target, $nicks ? join(', ', $nicks) : 'unable to find channel');
241 } elseif (preg_match('#^random (\S+)$#', $msg, $m)) {
242 $nick = $this->getrandomuser($m[1]);
243 $this->doPrivmsg($target, $nick ? $nick : 'unable to find channel');
248 * Checks whether or not a given user has a mode
250 * @param int $mode A numeric mode (identified by the class constants)
251 * @param string $nick The nick to check
252 * @param string $chan The channel to check in
256 public function is($mode, $nick, $chan)
258 $chan = trim(strtolower($chan));
259 $nick = trim(strtolower($nick));
261 if (!isset($this->store[$chan][$nick])) {
265 return ($this->store[$chan][$nick] & $mode) != 0;
269 * Checks whether or not a given user has owner (~) status
271 * @param string $nick The nick to check
272 * @param string $chan The channel to check in
276 public function isOwner($nick, $chan)
278 return $this->is(self::OWNER, $nick, $chan);
282 * Checks whether or not a given user has admin (&) status
284 * @param string $nick The nick to check
285 * @param string $chan The channel to check in
289 public function isAdmin($nick, $chan)
291 return $this->is(self::ADMIN, $nick, $chan);
295 * Checks whether or not a given user has operator (@) status
297 * @param string $nick The nick to check
298 * @param string $chan The channel to check in
302 public function isOp($nick, $chan)
304 return $this->is(self::OP, $nick, $chan);
308 * Checks whether or not a given user has halfop (%) status
310 * @param string $nick The nick to check
311 * @param string $chan The channel to check in
315 public function isHalfop($nick, $chan)
317 return $this->is(self::HALFOP, $nick, $chan);
321 * Checks whether or not a given user has voice (+) status
323 * @param string $nick The nick to check
324 * @param string $chan The channel to check in
328 public function isVoice($nick, $chan)
330 return $this->is(self::VOICE, $nick, $chan);
334 * Checks whether or not a given user is in a channel
336 * @param string $nick The nick to check
337 * @param string $chan The channel to check in
341 public function isIn($nick, $chan)
343 return $this->is(self::REGULAR, $nick, $chan);
347 * Returns the entire user list for a channel or false if the bot is not
350 * @param string $chan The channel name
354 public function getUsers($chan)
356 $chan = trim(strtolower($chan));
357 if (isset($this->store[$chan])) {
358 return array_keys($this->store[$chan]);
364 * Returns the nick of a random user present in a given channel or false
365 * if the bot is not present in the channel.
367 * @param string $chan The channel name
371 public function getRandomUser($chan)
373 $chan = trim(strtolower($chan));
375 if (isset($this->store[$chan])) {
376 $ignore = array('chanserv', 'q', 'l', 's');
379 $nick = array_rand($this->store[$chan], 1);
380 } while (in_array($nick, $ignore));
389 * Returns a list of channels in which a given user is present.
391 * @param string $nick Nick of the user (optional, defaults to the bot's
396 public function getChannels($nick = null)
399 $nick = $this->connection->getNick();
402 $nick = trim(strtolower($nick));
405 foreach ($this->store as $chan => $store) {
406 if (isset($store[$nick])) {