/*
* 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
}