forked from GNUsocial/gnu-social
		
	
		
			
				
	
	
		
			414 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			414 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| /**
 | |
|  * Phergie
 | |
|  *
 | |
|  * PHP version 5
 | |
|  *
 | |
|  * LICENSE
 | |
|  *
 | |
|  * This source file is subject to the new BSD license that is bundled
 | |
|  * with this package in the file LICENSE.
 | |
|  * It is also available through the world-wide-web at this URL:
 | |
|  * http://phergie.org/license
 | |
|  *
 | |
|  * @category  Phergie
 | |
|  * @package   Phergie_Plugin_UserInfo
 | |
|  * @author    Phergie Development Team <team@phergie.org>
 | |
|  * @copyright 2008-2010 Phergie Development Team (http://phergie.org)
 | |
|  * @license   http://phergie.org/license New BSD License
 | |
|  * @link      http://pear.phergie.org/package/Phergie_Plugin_UserInfo
 | |
|  */
 | |
| 
 | |
| /**
 | |
|  * Provides an API for querying information on users.
 | |
|  *
 | |
|  * @category Phergie
 | |
|  * @package  Phergie_Plugin_UserInfo
 | |
|  * @author   Phergie Development Team <team@phergie.org>
 | |
|  * @license  http://phergie.org/license New BSD License
 | |
|  * @link     http://pear.phergie.org/package/Phergie_Plugin_UserInfo
 | |
|  */
 | |
| class Phergie_Plugin_UserInfo extends Phergie_Plugin_Abstract
 | |
| {
 | |
|     const REGULAR = 1;
 | |
|     const VOICE   = 2;
 | |
|     const HALFOP  = 4;
 | |
|     const OP      = 8;
 | |
|     const ADMIN   = 16;
 | |
|     const OWNER   = 32;
 | |
| 
 | |
|     /**
 | |
|      * An array containing all the user information for a given channel
 | |
|      *
 | |
|      * @var array
 | |
|      */
 | |
|     protected $store = array();
 | |
| 
 | |
|     /**
 | |
|      * Tracks mode changes
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onMode()
 | |
|     {
 | |
|         $args = $this->event->getArguments();
 | |
| 
 | |
|         if (count($args) != 3) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         list($chan, $modes, $nicks) = $args;
 | |
| 
 | |
|         if (!preg_match('/(?:\+|-)[hovaq+-]+/i', $modes)) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $chan = trim(strtolower($chan));
 | |
|         $modes = str_split(trim(strtolower($modes)), 1);
 | |
|         $nicks = explode(' ', trim(strtolower($nicks)));
 | |
|         $operation = array_shift($modes); // + or -
 | |
| 
 | |
|         while ($char = array_shift($modes)) {
 | |
|             $nick = array_shift($nicks);
 | |
|             $mode = null;
 | |
| 
 | |
|             switch ($char) {
 | |
|             case 'q':
 | |
|                 $mode = self::OWNER;
 | |
|                 break;
 | |
|             case 'a':
 | |
|                 $mode = self::ADMIN;
 | |
|                 break;
 | |
|             case 'o':
 | |
|                 $mode = self::OP;
 | |
|                 break;
 | |
|             case 'h':
 | |
|                 $mode = self::HALFOP;
 | |
|                 break;
 | |
|             case 'v':
 | |
|                 $mode = self::VOICE;
 | |
|                 break;
 | |
|             }
 | |
| 
 | |
|             if (!empty($mode)) {
 | |
|                 if ($operation == '+') {
 | |
|                     $this->store[$chan][$nick] |= $mode;
 | |
|                 } else if ($operation == '-') {
 | |
|                     $this->store[$chan][$nick] ^= $mode;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tracks users joining a channel
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onJoin()
 | |
|     {
 | |
|         $chan = trim(strtolower($this->event->getArgument(0)));
 | |
|         $nick = trim(strtolower($this->event->getNick()));
 | |
| 
 | |
|         $this->store[$chan][$nick] = self::REGULAR;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tracks users leaving a channel
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onPart()
 | |
|     {
 | |
|         $chan = trim(strtolower($this->event->getArgument(0)));
 | |
|         $nick = trim(strtolower($this->event->getNick()));
 | |
| 
 | |
|         if (isset($this->store[$chan][$nick])) {
 | |
|             unset($this->store[$chan][$nick]);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tracks users quitting a server
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onQuit()
 | |
|     {
 | |
|         $nick = trim(strtolower($this->event->getNick()));
 | |
| 
 | |
|         foreach ($this->store as $chan => $store) {
 | |
|             if (isset($store[$nick])) {
 | |
|                 unset($this->store[$chan][$nick]);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Tracks users changing nicks
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onNick()
 | |
|     {
 | |
|         $nick = trim(strtolower($this->event->getNick()));
 | |
|         $newNick = trim(strtolower($this->event->getArgument(0)));
 | |
| 
 | |
|         foreach ($this->store as $chan => $store) {
 | |
|             if (isset($store[$nick])) {
 | |
|                 $this->store[$chan][$newNick] = $store[$nick];
 | |
|                 unset($this->store[$chan][$nick]);
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Populates the internal user listing for a channel when the bot joins it.
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onResponse()
 | |
|     {
 | |
|         if ($this->event->getCode() != Phergie_Event_Response::RPL_NAMREPLY) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         $desc = preg_split('/[@*=]\s*/', $this->event->getDescription(), 2);
 | |
|         list($chan, $users) = array_pad(explode(' :', trim($desc[1])), 2, null);
 | |
|         $users = explode(' ', trim($users));
 | |
| 
 | |
|         $chan = trim(strtolower($chan));
 | |
| 
 | |
|         foreach ($users as $user) {
 | |
|             if (empty($user)) {
 | |
|                 continue;
 | |
|             }
 | |
| 
 | |
|             $user = trim(strtolower($user));
 | |
|             $flag = self::REGULAR;
 | |
| 
 | |
|             if ($user[0] == '~') {
 | |
|                 $flag |= self::OWNER;
 | |
|             } else if ($user[0] == '&') {
 | |
|                 $flag |= self::ADMIN;
 | |
|             } else if ($user[0] == '@') {
 | |
|                 $flag |= self::OP;
 | |
|             } else if ($user[0] == '%') {
 | |
|                 $flag |= self::HALFOP;
 | |
|             } else if ($user[0] == '+') {
 | |
|                 $flag |= self::VOICE;
 | |
|             }
 | |
| 
 | |
|             if ($flag != self::REGULAR) {
 | |
|                 $user = substr($user, 1);
 | |
|             }
 | |
| 
 | |
|             $this->store[$chan][$user] = $flag;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Debugging function
 | |
|      *
 | |
|      * @return void
 | |
|      */
 | |
|     public function onPrivmsg()
 | |
|     {
 | |
|         if ($this->getConfig('debug', false) == false) {
 | |
|             return;
 | |
|         }
 | |
| 
 | |
|         list($target, $msg) = array_pad($this->event->getArguments(), 2, null);
 | |
| 
 | |
|         if (preg_match('#^ishere (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isIn($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^isowner (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isOwner($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^isadmin (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isAdmin($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^isop (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isOp($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^ishop (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isHalfop($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^isvoice (\S+)$#', $msg, $m)) {
 | |
|             $this->doPrivmsg($target, $this->isVoice($m[1], $target) ? 'true' : 'false');
 | |
|         } elseif (preg_match('#^channels (\S+)$#', $msg, $m)) {
 | |
|             $channels = $this->getChannels($m[1]);
 | |
|             $this->doPrivmsg($target, $channels ? join(', ', $channels) : 'unable to find nick');
 | |
|         } elseif (preg_match('#^users (\S+)$#', $msg, $m)) {
 | |
|             $nicks = $this->getUsers($m[1]);
 | |
|             $this->doPrivmsg($target, $nicks ? join(', ', $nicks) : 'unable to find channel');
 | |
|         } elseif (preg_match('#^random (\S+)$#', $msg, $m)) {
 | |
|             $nick = $this->getrandomuser($m[1]);
 | |
|             $this->doPrivmsg($target, $nick ? $nick : 'unable to  find channel');
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has a mode
 | |
|      *
 | |
|      * @param int    $mode A numeric mode (identified by the class constants)
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function is($mode, $nick, $chan)
 | |
|     {
 | |
|         $chan = trim(strtolower($chan));
 | |
|         $nick = trim(strtolower($nick));
 | |
| 
 | |
|         if (!isset($this->store[$chan][$nick])) {
 | |
|             return false;
 | |
|         }
 | |
| 
 | |
|         return ($this->store[$chan][$nick] & $mode) != 0;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has owner (~) status
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isOwner($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::OWNER, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has admin (&) status
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isAdmin($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::ADMIN, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has operator (@) status
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isOp($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::OP, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has halfop (%) status
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isHalfop($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::HALFOP, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user has voice (+) status
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isVoice($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::VOICE, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Checks whether or not a given user is in a channel
 | |
|      *
 | |
|      * @param string $nick The nick to check
 | |
|      * @param string $chan The channel to check in
 | |
|      *
 | |
|      * @return bool
 | |
|      */
 | |
|     public function isIn($nick, $chan)
 | |
|     {
 | |
|         return $this->is(self::REGULAR, $nick, $chan);
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the entire user list for a channel or false if the bot is not
 | |
|      * in the channel.
 | |
|      *
 | |
|      * @param string $chan The channel name
 | |
|      *
 | |
|      * @return array|bool
 | |
|      */
 | |
|     public function getUsers($chan)
 | |
|     {
 | |
|         $chan = trim(strtolower($chan));
 | |
|         if (isset($this->store[$chan])) {
 | |
|             return array_keys($this->store[$chan]);
 | |
|         }
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns the nick of a random user present in a given channel or false
 | |
|      * if the bot is not present in the channel.
 | |
|      *
 | |
|      * @param string $chan The channel name
 | |
|      *
 | |
|      * @return array|bool
 | |
|      */
 | |
|     public function getRandomUser($chan)
 | |
|     {
 | |
|         $chan = trim(strtolower($chan));
 | |
| 
 | |
|         if (isset($this->store[$chan])) {
 | |
|             $ignore = array('chanserv', 'q', 'l', 's');
 | |
| 
 | |
|             do {
 | |
|                 $nick = array_rand($this->store[$chan], 1);
 | |
|             } while (in_array($nick, $ignore));
 | |
| 
 | |
|             return $nick;
 | |
|         }
 | |
| 
 | |
|         return false;
 | |
|     }
 | |
| 
 | |
|     /**
 | |
|      * Returns a list of channels in which a given user is present.
 | |
|      *
 | |
|      * @param string $nick Nick of the user (optional, defaults to the bot's
 | |
|      *               nick)
 | |
|      *
 | |
|      * @return array|bool
 | |
|      */
 | |
|     public function getChannels($nick = null)
 | |
|     {
 | |
|         if (empty($nick)) {
 | |
|             $nick = $this->connection->getNick();
 | |
|         }
 | |
| 
 | |
|         $nick = trim(strtolower($nick));
 | |
|         $channels = array();
 | |
| 
 | |
|         foreach ($this->store as $chan => $store) {
 | |
|             if (isset($store[$nick])) {
 | |
|                 $channels[] = $chan;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         return $channels;
 | |
|     }
 | |
| }
 |