diff --git a/file/js/be.bastelstu.Chat.litcoffee b/file/js/be.bastelstu.Chat.litcoffee index 188a125..02daedd 100644 --- a/file/js/be.bastelstu.Chat.litcoffee +++ b/file/js/be.bastelstu.Chat.litcoffee @@ -37,7 +37,7 @@ be.bastelstu.Chat Attributes ---------- -When `shields` reaches zero `@pe.getMessages` is stopped, to prevent annoying the server with requests that don't go through. Decreased every time `@getMessages()` fails. +When `shields` reaches zero `@pe.getMessages` is stopped, to prevent annoying the server with requests that don't go through. Decreased every time `@getMessages()` fails. shields: 3 @@ -407,15 +407,15 @@ Handle reply. success: (data, textStatus, jqXHR) => WCF.DOMNodeInsertedHandler.enable() - @handleMessages(data.messages) - @handleUsers(data.users) + @handleMessages data.messages + @handleUsers data.users WCF.DOMNodeInsertedHandler.disable() Decrease `@shields` on error and disable PeriodicalExecuters once `@shields` reaches zero. error: => console.error 'Battle Station hit - shields at ' + (--@shields / 3 * 104) + ' percent' - if @shields is 0 + if @shields <= 0 @pe.refreshRoomList.stop() @pe.getMessages.stop() @freeTheFish() @@ -638,6 +638,7 @@ Updates the room list. actionName: 'getRoomList' className: 'chat\\data\\room\\RoomAction' showLoadingOverlay: false + suppressErrors: true success: (data) => $('#timsChatRoomList li').remove() $('#toggleRooms .ajaxLoad').hide() @@ -656,7 +657,7 @@ Bind click event for inline room change if we have the history API available. event.preventDefault() @changeRoom $ event.target - console.log "Found #{data.length} rooms" + console.log "Found #{data.returnValues.length} rooms" **submit(target)** Submits the message. @@ -717,7 +718,12 @@ Switches the active sidebar tab to the one belonging to `target`. Sends leave notification to the server. unload: -> - $.ajax @config.unloadURL, - type: 'POST' + proxy = new WCF.Action.Proxy + autoSend: true + data: + actionName: 'leave' + className: 'chat\\data\\room\\RoomAction' + showLoadingOverlay: false async: false + suppressErrors: true )(jQuery, @) diff --git a/file/lib/action/LeaveAction.class.php b/file/lib/action/LeaveAction.class.php deleted file mode 100644 index cedb813..0000000 --- a/file/lib/action/LeaveAction.class.php +++ /dev/null @@ -1,85 +0,0 @@ - - * @package be.bastelstu.chat - * @subpackage action - */ -class LeaveAction extends \wcf\action\AbstractAction { - /** - * @see wcf\action\AbstractAction::$loginRequired - */ - public $loginRequired = true; - - /** - * @see \wcf\action\AbstractAction::$neededModules - */ - public $neededModules = array('CHAT_ACTIVE'); - - /** - * @see \wcf\page\AbstractPage::$neededPermissions - */ - public $neededPermissions = array(); - - /** - * The current room. - * - * @var \chat\data\room\Room - */ - public $room = null; - - /** - * Values read from the UserStorage of the current user. - * - * @var array - */ - public $userData = array(); - - /** - * @see \wcf\action\IAction::execute() - */ - public function execute() { - parent::execute(); - - $this->userData['roomID'] = \chat\util\ChatUtil::readUserData('roomID'); - - $cache = data\room\Room::getCache(); - if (!isset($cache[$this->userData['roomID']])) throw new IllegalLinkException(); - $this->room = $cache[$this->userData['roomID']]; - if (!$this->room->canEnter()) throw new \wcf\system\exception\PermissionDeniedException(); - - if (CHAT_DISPLAY_JOIN_LEAVE) { - $this->userData['color'] = \chat\util\ChatUtil::readUserData('color'); - - // leave message - $messageAction = new data\message\MessageAction(array(), 'create', array( - 'data' => array( - 'roomID' => $this->room->roomID, - 'sender' => WCF::getUser()->userID, - 'username' => WCF::getUser()->username, - 'time' => TIME_NOW, - 'type' => data\message\Message::TYPE_LEAVE, - 'message' => '', - 'color1' => $this->userData['color'][1], - 'color2' => $this->userData['color'][2] - ) - )); - $messageAction->executeAction(); - } - - // set current room to null - \chat\util\ChatUtil::writeUserData(array('roomID' => null)); - - $this->executed(); - header("HTTP/1.0 204 No Content"); - exit; - } -} diff --git a/file/lib/data/room/Room.class.php b/file/lib/data/room/Room.class.php index 90c926f..f187b41 100644 --- a/file/lib/data/room/Room.class.php +++ b/file/lib/data/room/Room.class.php @@ -137,7 +137,7 @@ public function countUsers() { /** * Returns the users that are currently active in this room. * - * @return \wcf\data\user\UserList + * @return \wcf\data\user\UserProfileList */ public function getUsers() { $sql = "SELECT @@ -160,4 +160,46 @@ public function getUsers() { return $userList; } + + /** + * Returns the users that "timed out". + * + * @return \wcf\data\user\UserList + */ + public static function getDeadUsers() { + if (\chat\util\ChatUtil::nodePushRunning()) { + $time = TIME_NOW - 120; + } + else { + $time = TIME_NOW; + } + + $sql = "SELECT + r.userID + FROM + wcf".WCF_N."_user_storage r + LEFT JOIN + wcf".WCF_N."_user_storage a + ON a.userID = r.userID + AND a.field = ? + WHERE + r.field = ? + AND r.fieldValue IS NOT NULL + AND ( + a.fieldValue < ? + OR a.fieldValue IS NULL + )"; + $stmt = WCF::getDB()->prepareStatement($sql); + $stmt->execute(array('lastActivity', 'roomID', $time - 30)); + $userIDs = array(); + while ($userID = $stmt->fetchColumn()) $userIDs[] = $userID; + + $userList = new \wcf\data\user\UserList(); + if (!empty($userIDs)) $userList->getConditionBuilder()->add('user_table.userID IN (?)', array($userIDs)); + else $userList->getConditionBuilder()->add('1 = 0', array()); + + $userList->readObjects(); + + return $userList; + } } diff --git a/file/lib/data/room/RoomAction.class.php b/file/lib/data/room/RoomAction.class.php index 4df07d6..e7f3b81 100644 --- a/file/lib/data/room/RoomAction.class.php +++ b/file/lib/data/room/RoomAction.class.php @@ -1,5 +1,6 @@ parameters['room'] = $rooms[$roomID]; } /** @@ -132,10 +140,6 @@ public function validateGetRoomList() { public function getRoomList() { $rooms = Room::getCache(); - $roomID = \chat\util\ChatUtil::readUserData('roomID'); - if (!isset($rooms[$roomID])) throw new \wcf\system\exception\IllegalLinkException(); - $activeRoom = $rooms[$roomID]; - $result = array(); foreach ($rooms as $room) { if (!$room->canEnter()) continue; @@ -146,10 +150,61 @@ public function getRoomList() { 'application' => 'chat', 'object' => $room )), - 'active' => $room->roomID == $activeRoom->roomID + 'active' => $room->roomID == $this->parameters['room']->roomID ); } return $result; } + + /** + * Validates parameters and permissions. + */ + public function validateLeave() { + if (!CHAT_ACTIVE) throw new \wcf\system\exception\IllegalLinkException(); + + unset($this->parameters['user']); + + $rooms = Room::getCache(); + $roomID = ChatUtil::readUserData('roomID'); + if (!isset($rooms[$roomID])) throw new \wcf\system\exception\IllegalLinkException(); + } + + /** + * Leaves the room. + */ + public function leave() { + // user cannot be set during an AJAX request may be set by the chat itself + if (!isset($this->parameters['user'])) { + $this->parameters['user'] = WCF::getUser(); + } + + $rooms = Room::getCache(); + + $roomID = ChatUtil::readUserData('roomID', $this->parameters['user']); + if (!isset($rooms[$roomID])) throw new \wcf\system\exception\UserInputException(); + $activeRoom = $rooms[$roomID]; + + if (CHAT_DISPLAY_JOIN_LEAVE) { + $userData['color'] = ChatUtil::readUserData('color', $this->parameters['user']); + + // leave message + $messageAction = new \chat\data\message\MessageAction(array(), 'create', array( + 'data' => array( + 'roomID' => $activeRoom->roomID, + 'sender' => $this->parameters['user']->userID, + 'username' => $this->parameters['user']->username, + 'time' => TIME_NOW, + 'type' => \chat\data\message\Message::TYPE_LEAVE, + 'message' => '', + 'color1' => $userData['color'][1], + 'color2' => $userData['color'][2] + ) + )); + $messageAction->executeAction(); + } + + // set current room to null + ChatUtil::writeUserData(array('roomID' => null), $this->parameters['user']); + } } diff --git a/file/lib/page/NewMessagesPage.class.php b/file/lib/page/NewMessagesPage.class.php index f685aad..e59a78b 100644 --- a/file/lib/page/NewMessagesPage.class.php +++ b/file/lib/page/NewMessagesPage.class.php @@ -65,29 +65,12 @@ public function readData() { $this->readMessages(); $this->users = $this->room->getUsers(); - $deadUsers = \chat\util\ChatUtil::getDiedUsers(); + $deadUsers = data\room\Room::getDeadUsers(); foreach ($deadUsers as $deadUser) { - if (!$deadUser) continue; - - $user = new \wcf\data\user\User($deadUser['userID']); - if (CHAT_DISPLAY_JOIN_LEAVE) { - $userData['color'] = \chat\util\ChatUtil::readUserData('color', $user); - - $messageAction = new data\message\MessageAction(array(), 'create', array( - 'data' => array( - 'roomID' => $deadUser['roomID'], - 'sender' => $user->userID, - 'username' => $user->username, - 'time' => TIME_NOW, - 'type' => data\message\Message::TYPE_LEAVE, - 'message' => '', - 'color1' => $userData['color'][1], - 'color2' => $userData['color'][2] - ) - )); - $messageAction->executeAction(); - } - \chat\util\ChatUtil::writeUserData(array('roomID' => null), $user); + $roomAction = new data\room\RoomAction(array(), 'leave', array( + 'user' => $deadUser + )); + $roomAction->executeAction(); } } diff --git a/file/lib/util/ChatUtil.class.php b/file/lib/util/ChatUtil.class.php index c552c1c..03d6dfa 100644 --- a/file/lib/util/ChatUtil.class.php +++ b/file/lib/util/ChatUtil.class.php @@ -44,41 +44,6 @@ final class ChatUtil { */ private static $packageID = null; - /** - * Fetches the userIDs of died users. - * - * @return array - */ - public static function getDiedUsers() { - if (self::nodePushRunning()) { - $time = TIME_NOW - 120; - } - else { - $time = TIME_NOW; - } - - $sql = "SELECT - r.userID, r.fieldValue AS roomID - FROM - wcf".WCF_N."_user_storage r - LEFT JOIN - wcf".WCF_N."_user_storage a - ON a.userID = r.userID - AND a.field = ? - WHERE - r.field = ? - AND r.fieldValue IS NOT NULL - AND ( - a.fieldValue < ? - OR a.fieldValue IS NULL - )"; - $stmt = WCF::getDB()->prepareStatement($sql); - $stmt->execute(array('lastActivity', 'roomID', $time - 30)); - $users = array(); - while ($user = $stmt->fetchArray()) $users[] = $user; - - return $users; - } /** * Returns the packageID of Tims Chat. */ @@ -173,6 +138,20 @@ public static function readUserData($field, \wcf\data\user\User $user = null) { else return $data[$user->userID]; } + /** + * Writes user data + * @param array $data + * @param \wcf\data\user\User $user + */ + public static function writeUserData(array $data, \wcf\data\user\User $user = null) { + if ($user === null) $user = WCF::getUser(); + $ush = UserStorageHandler::getInstance(); + + foreach ($data as $key => $value) { + $ush->update($user->userID, $key, (isset(static::$serialize[$key])) ? serialize($value) : $value); + } + } + /** * Splits a string into smaller chunks. * UTF-8 safe version of str_split(). @@ -246,20 +225,6 @@ public static function timeModifier($time) { return (int) round($result, 0); } - /** - * Writes user data - * @param array $data - * @param \wcf\data\user\User $user - */ - public static function writeUserData(array $data, \wcf\data\user\User $user = null) { - if ($user === null) $user = WCF::getUser(); - $ush = UserStorageHandler::getInstance(); - - foreach ($data as $key => $value) { - $ush->update($user->userID, $key, (isset(static::$serialize[$key])) ? serialize($value) : $value); - } - } - /** * Disables the constructor. */