diff --git a/lib/Destiny/Chat/ChatRedisService.php b/lib/Destiny/Chat/ChatRedisService.php index ae3734a86..25a7f3543 100644 --- a/lib/Destiny/Chat/ChatRedisService.php +++ b/lib/Destiny/Chat/ChatRedisService.php @@ -36,11 +36,7 @@ function afterConstruct() { $this->redis = Application::instance()->getRedis(); } - /** - * @throws Exception - */ - public function findUserIdsByUsersIp(int $userid): array { - $keys = RedisUtils::callScript('check-sameip-users', [$userid]); + private function stripRedisUserIpPrefixes(array $keys) { return array_filter(array_map(function($n) { return intval(substr($n, strlen('CHAT:userips-'))); }, $keys), function($n){ @@ -49,15 +45,30 @@ public function findUserIdsByUsersIp(int $userid): array { } /** + * Finds all users who share the same IP + * @throws Exception + */ + public function findUserIdsByUsersIp(int $userid): array { + $keys = RedisUtils::callScript('check-sameip-users', [$userid]); + return $this->stripRedisUserIpPrefixes($keys); + } + + /** + * Find all users by ip * @throws Exception */ public function findUserIdsByIP(string $ipaddress): array { $keys = RedisUtils::callScript('check-ip', [$ipaddress]); - return array_filter(array_map(function($n) { - return intval(substr($n, strlen('CHAT:userips-'))); - }, $keys), function($n){ - return $n != null && $n > 0; - }); + return $this->stripRedisUserIpPrefixes($keys); + } + + /** + * Find all users by ip (wildcard) + * @throws Exception + */ + public function findUserIdsByIPWildcard(string $ipaddress): array { + $keys = RedisUtils::callScript('check-ip-wildcard', [$ipaddress]); + return $this->stripRedisUserIpPrefixes($keys); } /** diff --git a/lib/Destiny/Controllers/ChatAdminController.php b/lib/Destiny/Controllers/ChatAdminController.php index b15cec1aa..a545db7a1 100644 --- a/lib/Destiny/Controllers/ChatAdminController.php +++ b/lib/Destiny/Controllers/ChatAdminController.php @@ -47,8 +47,13 @@ public function adminChatBroadcast(array $params, ViewModel $model): string { */ public function adminChatIp(array $params, ViewModel $model): string { $model->title = 'Chat'; + $max = 100; FilterParams::required($params, 'ip'); - $ids = ChatRedisService::instance()->findUserIdsByIP($params['ip']); + $ids = ChatRedisService::instance()->findUserIdsByIPWildcard($params['ip']); + $ids = array_unique($ids); + if (count($ids) > $max) { + $ids = array_slice($ids, 0, $max); + } $model->usersByIp = UserService::instance()->getUsersByUserIds($ids); $model->searchIp = $params ['ip']; return 'admin/chat'; diff --git a/scripts/redis/check-ip-wildcard.lua b/scripts/redis/check-ip-wildcard.lua new file mode 100644 index 000000000..7d1b67b7d --- /dev/null +++ b/scripts/redis/check-ip-wildcard.lua @@ -0,0 +1,17 @@ +if not ARGV[1] then + return {err = "INVALID ARGUMENTS"} +end + +local ip = ARGV[1] +local foundusers = {} +local keys = redis.call("KEYS", "CHAT:userips-*") +for _, key in ipairs(keys) do + local rawData = redis.call('ZRANGE', key, 0, -1); + for idx = 1, #rawData, 2 do + if string.match(rawData[idx], ip) then + table.insert(foundusers, key) + end + end +end + +return foundusers diff --git a/views/admin/chat.php b/views/admin/chat.php index 1c599eff7..152fb29ac 100644 --- a/views/admin/chat.php +++ b/views/admin/chat.php @@ -39,7 +39,7 @@