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;
|
|
}
|
|
}
|