id = Utils::$chat["AUTOID"] ? null : $id; $this->ip = $ip; $this->username = $username; $this->expire = $expire; } public function Check($id, $ip, $username) { if($GLOBALS["chat"]["AUTOID"]) $id = null; return (($this->id == null ? false : $id == $this->id) || ($this->ip == null ? false : Utils::CheckIPAddresses($ip, $this->ip)) || ($this->username == null ? false : $username == $this->username)) && ($this->expire > time() || $this->expire == -1); } } class Context { public static $onlineUsers = []; public static $channelList = []; public static $bannedUsers = []; public static $invisibleUsers = []; public static function ForceChannelSwitch($user, $to) { if(Context::ChannelExists($to)) { $oldchan = $user->channel; if(!Modules::ExecuteRoutine("OnChannelDelete", [$user, Context::GetChannel($to), Context::GetChannel($oldchan)])) return; Message::HandleChannelSwitch($user, $to, $user->channel); unset(Context::GetChannel($user->channel)->users[$user->id]); Context::GetChannel($to)->users[$user->id] = Context::$onlineUsers[$user->id]; Context::$onlineUsers[$user->id]->channel = $to; if(Context::GetChannel($oldchan)->channelType == CHANNEL_TEMP && Context::GetChannel($oldchan)->GetOwner()->id == $user->id) Context::DeleteChannel($oldchan); Modules::ExecuteRoutine("AfterChannelSwitch", [$user, Context::GetChannel($to), Context::GetChannel($oldchan)]); } } public static function SwitchChannel($user, $to, $pwd = "") { if($user->channel != $to) { if(Context::ChannelExists($to)) { if($pwd == Context::GetChannel($to)->password || $user->canModerate() || Context::GetChannel($to)->GetOwner()->id == $user->id) { if(Context::GetChannel($to)->permissionLevel <= $user->getRank()) { Context::ForceChannelSwitch($user, $to); return; } else Message::PrivateBotMessage(MSG_ERROR, "ipchan", array($to), $user); } else Message::PrivateBotMessage(MSG_ERROR, "ipwchan", array($to), $user); } else Message::PrivateBotMessage(MSG_ERROR, "nochan", array($to), $user); } // else Message::PrivateBotMessage(MSG_ERROR, "samechan", array($to), $user); // kind of extraneous $user->sock->send(Utils::PackMessage(5, ["2", $user->channel])); } public static function IsLobby($channel) { if(is_string($channel)) $channel = Context::GetChannel($channel); return $channel->name == Context::GetChannel(Utils::$chat["DEFAULT_CHANNEL"])->name; } public static function AddInvisibleUser($name, $color) { for($id = -2;;$id--) { if(!array_key_exists($id, Context::$onlineUsers) && !array_key_exists($id, Context::$invisibleUsers)) break; } Context::$invisibleUsers[$id] = new User($id, "", $name, $color, "6770\f1\f1\f1\f1\f1", null, false); foreach(Context::$onlineUsers as $user) { $user->sock->send(Utils::PackMessage(7, ["1", $id, $name, $color, "6770\f1\f1\f1\f1\f1", ])); } return Context::$invisibleUsers[$id]; } public static function GetUserByID($id) { if(array_key_exists($id, Context::$onlineUsers)) return Context::$onlineUsers[$id]; //return Context::$onlineUsers[array_rand(Context::$onlineUsers)]; else return null; } public static function GetUserByName($name) { foreach(Context::$onlineUsers as $user) { if ($user->username == $name) return $user; } //return GetUserByID(0); return null; } public static function GetUserBySock($sock) { foreach(Context::$onlineUsers as $user) { if($user->sock == $sock) return $user; } return null; } public static function GetAllChannels() { return join(Utils::$separator, Context::$channelList); } public static function GetChannel($name) { if(array_key_exists($name, Context::$channelList)) return Context::$channelList[$name]; else if($name == "@default") return Context::$channelList[Utils::$chat["DEFAULT_CHANNEL"]]; else return null; } public static function ChannelExists($name) { return array_key_exists($name, Context::$channelList); } public static function CreateChannel($channel) { if(is_string($channel)) $channel = new Channel($channel); if(!Context::ChannelExists($channel->name)) { if($channel->name[0] != "@" && $channel->name[0] != "*") { if(!Modules::ExecuteRoutine("OnChannelCreate", [$channel])) return Utils::FormatBotMessage(MSG_ERROR, "generr", []); Context::$channelList[$channel->name] = $channel; Message::HandleChannelCreation($channel); Database::CreateChannel($channel->name, $channel->password, $channel->permissionLevel); Modules::ExecuteRoutine("AfterChannelCreate", [$channel]); return "OK"; } else return Utils::FormatBotMessage(MSG_ERROR, "inchan", []); } else return Utils::FormatBotMessage(MSG_ERROR, "nischan", [$channel->name]); } public static function RenameChannel($oldname, $newname) { if(Context::ChannelExists($oldname) && !Context::ChannelExists($newname)) { Context::$channelList[$newname] = clone Context::GetChannel($oldname); Context::$channelList[$newname]->name = $newname; if(!Modules::ExecuteRoutine("OnChannelModify", [Context::$channelList[$oldname], Context::$channelList[$newname]])) { unset(Context::$channelList[$newname]); return false; } Message::HandleChannelModification($newname, $oldname); Modules::ExecuteRoutine("AfterChannelModify", [Context::$channelList[$oldname], Context::$channelList[$newname]]); unset(Context::$channelList[$oldname]); return true; } else return false; } public static function ChangeChannelPassword($channel, $pwd) { if(is_string($channel)) $channel = Context::GetChannel($channel); $tmp = [clone $channel, clone $channel]; $tmp[0]->password = trim($pwd) == "" ? "" : Utils::Hash(trim($pwd)); if(!Modules::ExecuteRoutine("OnChannelModify", [$channel, $tmp[0]])) return; Context::$channelList[$channel->name] = $tmp[0]; Message::HandleChannelModification(Context::$channelList[$channel->name]); Modules::ExecuteRoutine("AfterChannelModify", [$tmp[1], $channel]); } public static function ChangeChannelPermission($channel, $perm) { if(is_string($channel)) $channel = Context::GetChannel($channel); $tmp = [clone $channel, clone $channel]; $tmp[0]->permissionLevel = $perm; if(!Modules::ExecuteRoutine("OnChannelModify", [$channel, $tmp[0]])) return; Context::$channelList[$channel->name] = $tmp[0]; Message::HandleChannelModification(Context::$channelList[$channel->name]); Modules::ExecuteRoutine("AfterChannelModify", [$tmp[1], $channel]); } public static function DeleteChannel($channel) { if(is_string($channel)) $channel = Context::GetChannel($channel); if(!Modules::ExecuteRoutine("OnChannelDelete", [$channel])); foreach($channel->users as $user) Context::SwitchChannel($user, Utils::$chat["DEFAULT_CHANNEL"]); Message::HandleChannelDeletion($channel); Database::RemoveChannel($channel->name); unset(Context::$channelList[$channel->name]); Modules::ExecuteRoutine("AfterChannelDelete", [$channel]); } public static function Join($user) { if(!Modules::ExecuteRoutine("OnUserJoin", [$user])) return; Message::HandleJoin($user); Context::$onlineUsers[$user->id] = $user; Context::$channelList[Utils::$chat["DEFAULT_CHANNEL"]]->users[$user->id] = Context::$onlineUsers[$user->id]; Database::Login($user); Modules::ExecuteRoutine("AfterUserJoin", [$user]); } public static function AllowUser($username, $sock) { foreach(Context::$onlineUsers as $user) { if($user->GetOriginalUsername() != $username) { if($sock == $user->sock) { return "sockfail"; } } else return "userfail"; } return 0; } public static function CheckBan($id, $ip, $name) { foreach(Context::$bannedUsers as $ban) { if($ban->Check($id, $ip, $name)) return $ban->expire; } return false; } public static function Unban($id, $ip, $name, $by = null) { if($by == null) $by = Message::$bot; if(!Modules::ExecuteRoutine("OnUnban", [&$id, &$ip, &$name, $by])) return false; $banned = false; foreach(Context::$bannedUsers as $bid => $ban) { if($ban->Check($id, $ip, $name)) { unset(Context::$bannedUsers[$bid]); $banned = true; } } if($ip != null) $ip = str_replace("*", "%", $ip); Database::Unban($ip, $id, $name); Modules::ExecuteRoutine("AfterUnban", [$id, $ip, $name, $by]); return $banned; } public static function ModifyUser($newuser) { $u = Context::GetUserByID($newuser->id); $u->Copy($newuser); if(!Modules::ExecuteRoutine("OnUserModify", [$u])) return; Message::HandleUserModification($u); } public static function KickUser($user, $by = null, $time = 0, $banip = false, $type = LEAVE_KICK) { if(!Modules::ExecuteRoutine("OnUserKick", [$user, $by == null ? Message::$bot : $by, &$time, &$banip])) return; Message::HandleKick($user, $time); if($time != 0) { $exp = $time < 0 ? -1 : (int)gmdate("U") + $time; Database::Ban($banip ? $user->sock->remoteAddress : null , $user->id, $user->GetOriginalUsername(), $exp); array_push(Context::$bannedUsers, new Ban($banip ? $user->sock->remoteAddress : null , $user->id, $user->GetOriginalUsername(), $exp)); } $ip = $user->sock->remoteAddress; $user->sock->close(); Context::Leave($user, $type); if($banip) Context::BanIP($ip, $time, $by, true); Modules::ExecuteRoutine("AfterUserKick", [$user, $by == null ? Message::$bot : $by, $time, $banip]); } public static function BanIP($ip, $time = -1, $by = null, $alreadybanned = false) { if(!$alreadybanned) { if(!Modules::ExecuteRoutine("OnBanIP", [&$ip, &$time, $by == null ? Message::$bot : $by])) return; $exp = $time < 0 ? -1 : (int)gmdate("U") + $time; array_push(Context::$bannedUsers, new Ban($ip, null, null, $exp)); Database::Ban($ip, null, null, $exp); } foreach(Context::$onlineUsers as $user) { if(Utils::CheckIPAddresses($user->sock->remoteAddress, $ip)) { Message::HandleKick($user, $time); $user->sock->close(); Context::Leave($user, LEAVE_KICK); } } if(!$alreadybanned) Modules::ExecuteRoutine("AfterBanIP", [$ip, $time, $by == null ? Message::$bot : $by]); } public static function CheckPings() { foreach(Context::$onlineUsers as $user) { if(gmdate("U") - $user->ping > Utils::$chat["MAX_IDLE_TIME"]) { $user->sock->close(); Context::Leave($user); } } } public static function DoesSockExist($sock) { foreach(Context::$onlineUsers as $u) { if($u->sock == $sock) return true; } return false; } public static function Leave($user, $type = LEAVE_NORMAL) { if(Context::GetChannel($user->channel)->channelType == CHANNEL_TEMP && Context::GetChannel($user->channel)->GetOwner()->id == $user->id) Context::DeleteChannel($user->channel); Database::Logout($user); Message::HandleLeave($user, $type); unset(Context::GetChannel($user->channel)->users[$user->id]); unset(Context::$onlineUsers[$user->id]); } }