/* * CSB Who Is * Copyright (C) 2026 counter-strike-boost.com * * amx_who dumps every connected player's SteamID, IP, ping, country (GeoIP), * time on server and access flags to the admin's console. A /who menu lets an * admin pick a player and print the same card. Handy for cross-referencing bans * and spotting VPNs. * * Inspired by the info commands in the AMX Mod X Admin Commands plugin. * Independent GPL re-implementation. * * This program is free software: you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. It is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See for details. */ #include #include #include new const PLUGIN[] = "CSB Who Is" new const VERSION[] = "1.0.0" new const AUTHOR[] = "counter-strike-boost.com" new g_iJoin[33] public plugin_init() { register_plugin(PLUGIN, VERSION, AUTHOR) register_concmd("amx_who", "cmdWho", ADMIN_KICK, "- print SteamID/IP/ping/country/flags for everyone") register_clcmd("say /who", "cmdWhoMenu") register_clcmd("say_team /who", "cmdWhoMenu") } public client_putinserver(id) { g_iJoin[id] = get_systime() } public client_disconnected(id) { g_iJoin[id] = 0 } formatCard(id, out[], len) { new name[32], authid[35], ip[32], flagStr[32] new ccode[3], country[46] get_user_name(id, name, charsmax(name)) get_user_authid(id, authid, charsmax(authid)) get_user_ip(id, ip, charsmax(ip), 1) get_flags(get_user_flags(id), flagStr, charsmax(flagStr)) if (!flagStr[0]) copy(flagStr, charsmax(flagStr), "-") if (!geoip_code2(ip, ccode)) copy(ccode, charsmax(ccode), "??") if (!geoip_country(ip, country, charsmax(country))) copy(country, charsmax(country), "Unknown") new ping, loss get_user_ping(id, ping, loss) new mins = g_iJoin[id] ? (get_systime() - g_iJoin[id]) / 60 : 0 formatex(out, len, "#%d %s | %s | %s (%s) %s | ping %d | %d min | flags %s", get_user_userid(id), name, authid, ip, ccode, country, ping, mins, flagStr) } public cmdWho(id, level, cid) { if (!cmd_access(id, level, cid, 1)) return PLUGIN_HANDLED console_print(id, "----- CSB Who Is -----") new players[32], num, pid, card[192] get_players(players, num) for (new i = 0; i < num; i++) { pid = players[i] formatCard(pid, card, charsmax(card)) console_print(id, "%s", card) } console_print(id, "----- %d player(s) -----", num) return PLUGIN_HANDLED } public cmdWhoMenu(id) { if (!(get_user_flags(id) & ADMIN_KICK)) { client_print(id, print_chat, "[CSB] You do not have access to /who.") return PLUGIN_HANDLED } new menu = menu_create("\yWho Is - pick a player", "whoMenuHandler") new players[32], num, pid, name[32], info[8] get_players(players, num) for (new i = 0; i < num; i++) { pid = players[i] get_user_name(pid, name, charsmax(name)) num_to_str(pid, info, charsmax(info)) menu_additem(menu, name, info, 0) } menu_display(id, menu, 0) return PLUGIN_HANDLED } public whoMenuHandler(id, menu, item) { if (item == MENU_EXIT || item < 0) { menu_destroy(menu) return PLUGIN_HANDLED } new info[8], name[32], access, callback menu_item_getinfo(menu, item, access, info, charsmax(info), name, charsmax(name), callback) menu_destroy(menu) new target = str_to_num(info) if (target < 1 || !is_user_connected(target)) { client_print(id, print_chat, "[CSB] That player left.") return PLUGIN_HANDLED } new card[192] formatCard(target, card, charsmax(card)) console_print(id, "[CSB Who] %s", card) client_print(id, print_chat, "[CSB] Details for %s printed to your console (~ key).", name) return PLUGIN_HANDLED }