C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using Newtonsoft.Json;
using ConVar;
using Facepunch;
using Newtonsoft.Json.Linq;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using WebSocketSharp;
using Oxide.Game.Rust.Libraries;
using Time = Oxide.Core.Libraries.Time;
using Facepunch.Extend;
namespace Oxide.Plugins {
[Info("Server Armour", "Pho3niX90", "0.6.51")]
[Description("Protect your server! Auto ban known hackers, scripters and griefer accounts, and notify server owners of threats.")]
class ServerArmour : CovalencePlugin {
#region Variables
string api_hostname = "https://io.serverarmour.com";
//
Dictionary<string, ISAPlayer> _playerData = new Dictionary<string, ISAPlayer>();
private Time _time = GetLibrary<Time>();
private double cacheLifetime = 1;
// minutes
private SAConfig config;
string specifier = "G";
bool debug = false;
CultureInfo culture = CultureInfo.CreateSpecificCulture("en-US");
//StringComparison defaultCompare = StringComparison.InvariantCultureIgnoreCase;
const string DATE_FORMAT = "yyyy/MM/dd HH:mm";
const string DATE_FORMAT2 = "yyyy-MM-dd HH:mm:ss";
ulong ServerArmourId = 76561199060671869L;
bool init = false;
private Dictionary<string, string> headers;
string adminIds = "";
private static ServerArmour _instance;
#endregion
#region Libraries
private readonly Game.Rust.Libraries.Player Player = Interface.Oxide.GetLibrary<Game.Rust.Libraries.Player>();
#endregion
#region Permissions
const string PermissionToBan = "serverarmour.ban";
const string PermissionToUnBan = "serverarmour.unban";
const string PermissionAdminWebsite = "serverarmour.website.admin";
const string PermissionWhitelistRecentVacKick = "serverarmour.whitelist.recentvac";
const string PermissionWhitelistBadIPKick = "serverarmour.whitelist.badip";
const string PermissionWhitelistKeywordKick = "serverarmour.whitelist.keyword";
const string PermissionWhitelistVacCeilingKick = "serverarmour.whitelist.vacceiling";
const string PermissionWhitelistServerCeilingKick = "serverarmour.whitelist.banceiling";
const string PermissionWhitelistGameBanCeilingKick = "serverarmour.whitelist.gamebanceiling";
const string PermissionWhitelistTotalBanCeiling = "serverarmour.whitelist.totalbanceiling";
const string PermissionWhitelistSteamProfile = "serverarmour.whitelist.steamprofile";
const string PermissionWhitelistFamilyShare = "serverarmour.whitelist.familyshare";
const string PermissionWhitelistTwitterBan = "serverarmour.whitelist.twitterban";
#endregion
#region Plugins
[PluginReference]
Plugin DiscordApi, DiscordMessages, BetterChat, Ember, Clans;
void DiscordSend(string steamId, string name, EmbedFieldList report, int color = 39423, bool isBan = false) {
string webHook;
if (isBan) {
if (config.DiscordBanWebhookURL.Length == 0 || config.DiscordBanWebhookURL.Equals("https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks")) {
Puts("Discord webhook not setup.");
return;
}
webHook = config.DiscordBanWebhookURL;
}
else {
if (config.DiscordWebhookURL.Length == 0 || config.DiscordWebhookURL.Equals("https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks")) {
Puts("Discord webhook not setup.");
return;
}
webHook = config.DiscordWebhookURL;
}
List<EmbedFieldList> fields = new List<EmbedFieldList>();
if (config.DiscordQuickConnect) {
fields.Add(new EmbedFieldList() {
name = server.Name, value = $"[steam://connect/{config.ServerIp}:{server.Port}](steam://connect/{config.ServerIp}:{server.Port})", inline = true
}
);
}
fields.Add(new EmbedFieldList() {
name = "Steam Profile", value = $"[{name}\n{steamId}](https://steamcommunity.com/profiles/{steamId})", inline = !config.DiscordQuickConnect
}
);
fields.Add(new EmbedFieldList() {
name = "Server Armour Profile ", value = $"[{name}\n{steamId}](https://io.serverarmour.com/profile/{steamId})", inline = !config.DiscordQuickConnect
}
);
fields.Add(report);
var fieldsObject = fields.Cast<object>().ToArray();
string json = JsonConvert.SerializeObject(fieldsObject);
if (DiscordApi != null && DiscordApi.IsLoaded) {
DiscordApi?.Call("API_SendEmbeddedMessage", webHook, "Server Armour Report: ", color, json);
}
else if (DiscordMessages != null && DiscordMessages.IsLoaded) {
DiscordMessages?.Call("API_SendFancyMessage", webHook, "Server Armour Report: ", color, json);
}
else {
LogWarning("No discord API plugin loaded, will not publish to hook!");
}
}
#endregion
#region Hooks
void OnServerInitialized(bool first) {
_instance = this;
LoadData();
// CheckOnlineUsers();
// CheckLocalBans();
Puts("Server Armour is being initialized.");
if (string.IsNullOrEmpty(config.ServerGPort)) {
config.ServerGPort = server.Port.ToString();
}
SaveConfig();
Puts($"Server IP is {config.ServerIp} / {server.Address}");
Puts($"Server Port is {server.Port}");
RegPerm(PermissionToBan);
RegPerm(PermissionToUnBan);
RegPerm(PermissionAdminWebsite);
RegPerm(PermissionWhitelistBadIPKick);
RegPerm(PermissionWhitelistKeywordKick);
RegPerm(PermissionWhitelistRecentVacKick);
RegPerm(PermissionWhitelistServerCeilingKick);
RegPerm(PermissionWhitelistVacCeilingKick);
RegPerm(PermissionWhitelistGameBanCeilingKick);
RegPerm(PermissionWhitelistTotalBanCeiling);
RegPerm(PermissionWhitelistSteamProfile);
RegPerm(PermissionWhitelistFamilyShare);
RegPerm(PermissionWhitelistTwitterBan);
RegisterTag();
headers = new Dictionary<string, string> {
{
"server_key", config.ServerApiKey
}
, {
"Accept", "application/json"
}
}
;
string[] _admins = permission.GetUsersInGroup("admin");
if (config.OwnerSteamId != null && config.OwnerSteamId.Length > 0 && !_admins.Contains(config.OwnerSteamId)) {
var adminsList = new List<string>();
adminsList.AddRange(_admins);
adminsList.AddRange(config.OwnerSteamId.Split(','));
var extraAdmins = permission.GetPermissionUsers(PermissionAdminWebsite);
if (extraAdmins != null && extraAdmins.Length > 0) {
adminsList.AddRange(extraAdmins);
}
int e = 0;
foreach (string extraAdminsGroups in permission.GetPermissionGroups(PermissionAdminWebsite)) {
foreach (string extraAdmin in permission.GetUsersInGroup(extraAdminsGroups)) {
if (!adminsList.Contains(extraAdmin)) {
adminsList.Add(extraAdmin);
e++;
}
}
}
_admins = adminsList.Distinct().ToArray();
}
for (int i = 0, n = _admins.Length; i < n; i++) {
adminIds += $"{_admins[i].Substring(0, 17)}" + (i < _admins.Length - 1 ? "," : "");
}
CheckServerConnection();
}
void CheckServerConnection() {
string body = ServerGetString();
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/check_server", body, (code, response) => {
if (code > 204 || response.IsNullOrEmpty()) {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
timer.Once(3, CheckServerConnection);
return;
}
JObject obj = null;
try {
obj = JObject.Parse(response);
}
catch (Exception) {
timer.Once(5, CheckServerConnection);
return;
}
if (obj != null) {
var msg = obj["message"].ToString();
var key = obj["key"]?.ToString();
if (msg.Equals("connected")) {
init = true;
Puts("connected to SA API");
}
else if (msg.Equals("key assigned to server") || msg.Equals("key assigned to new server")) {
config.SetConfig(ref key, "io.serverarmour.com", "Server Key");
headers = new Dictionary<string, string> {
{
"server_key", key
}
, {
"Accept", "application/json"
}
}
;
SaveConfig();
Puts("Server key has been updated");
init = true;
}
else {
LogError("Server Armour has not initialized.Is your apikey correct? Get it from https://io.serverarmour.com/my-servers or join discord for support https://discord.gg/jxvRaPR");
Interface.Oxide.UnloadPlugin(Name);
return;
}
Puts("Server Armour has initialized.");
}
}
, this, RequestMethod.POST, headers);
}
void Unload() {
SaveData();
_playerData.Clear();
_playerData = null;
}
//[Command("tc")]
void OnUserConnected(IPlayer player) {
if (!init) {
LogError("User not checked.Server armour is not loaded.");
}
else {
//lets check the userid first.if (config.AutoKick_KickWeirdSteam64 && !player.Id.IsSteamId())
{
KickPlayer(player.Id, GetMsg("Strange Steam64ID"), "C");
return;
}
GetPlayerBans(player);
if (config.ShowProtectedMsg) SendReplyWithIcon(player, GetMsg("Protected MSG"));
}
}
void OnUserDisconnected(IPlayer player) {
if (init) {
_playerData = _playerData.Where(pair => minutesAgo((uint)pair.Value.cacheTimestamp) < cacheLifetime).ToDictionary(pair => pair.Key, pair => pair.Value);
}
}
void OnPluginLoaded(Plugin plugin) {
if (plugin.Title == "BetterChat") RegisterTag();
}
void OnUserUnbanned(string name, string id, string ipAddress) {
SaUnban(id);
}
/// <summary>
/// Processes commands on an interval basis, this is only needed for servers that do not have RCON enabled (not yet implemented)./// </summary>
/// <param name="playerId"></param>
void APIActions(string playerId) {
// do webcall
//process instructions.}
void OnUserBanned(string name, string id, string ipAddress, string reason) {
//this is to make sure that if an app like battlemetrics for example, bans a player, we catch it.timer.Once(3f, () =>
{
//lets make sure first it wasn't us.if (!IsPlayerCached(id) && (IsPlayerCached(id) && !ContainsMyBan(id)))
{
Puts($"Player wasn't banned via Server Armour, now adding to DB with a default lengh ban of 100yrs {name} ({id}) at {ipAddress} was banned: {reason}");
IPlayer bPlayer = players.FindPlayerById(id);
if (bPlayer != null) {
if ((bPlayer.IsAdmin && config.IgnoreAdmins)) return;
AddBan(bPlayer, new ISABan {
serverName = server.Name, serverIp = config.ServerIp, reason = reason, created = DateTime.Now.ToString(DATE_FORMAT), banUntil = DateTime.Now.AddYears(100).ToString(DATE_FORMAT)
}
, false);
}
}
}
);
}
void OnPlayerReported(BasePlayer reporter, string targetName, string targetId, string subject, string message, string type) {
string messageClean = Uri.EscapeDataString(message);
string subjectClean = Uri.EscapeDataString(subject);
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/player/{reporter.UserIDString}/addf7", $"target={targetId}&subject={subjectClean}&message={messageClean}", (code, response) => {
if (code > 204 || response == null) {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
return;
}
}
, this, RequestMethod.POST, headers);
}
#endregion
#region API_Hooks
#endregion
#region WebRequests
void GetPlayerBans(IPlayer player) {
KickIfBanned(GetPlayerCache(player?.Id));
_webCheckPlayer(player.Name, player.Id, player.Address, player.IsConnected);
}
void GetPlayerBans(string playerId, string playerName) {
KickIfBanned(GetPlayerCache(playerId));
_webCheckPlayer(playerName, playerId, "0.0.0.0", true);
}
void _webCheckPlayer(string name, string id, string address, bool connected) {
string playerName = Uri.EscapeDataString(name);
try {
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/player/{id}?bans=true", $"ipAddress={address}", (code, response) => {
if (code > 204 || response.IsNullOrEmpty()) {
if (code == 500) {
timer.Once(5, () => _webCheckPlayer(playerName, id, address, connected));
}
else {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
}
return;
}
LogDebug("Getting player from API");
ISAPlayer isaPlayer = null;
try {
isaPlayer = JsonConvert.DeserializeObject<ISAPlayer>(response);
}
catch (Exception) {
timer.Once(5, () => _webCheckPlayer(playerName, id, address, connected));
return;
}
isaPlayer.cacheTimestamp = _time.GetUnixTimestamp();
isaPlayer.lastConnected = _time.GetUnixTimestamp();
// add cache for player
LogDebug("Checking cache");
if (!IsPlayerCached(isaPlayer.steamid)) {
AddPlayerCached(isaPlayer);
}
else {
UpdatePlayerData(isaPlayer);
}
// lets check bans first
try {
KickIfBanned(isaPlayer);
}
catch (Exception ane) {
Puts("An ArgumentNullException occured.Please notify the developer along with the below information: ");
Puts(response);
Puts(ane.StackTrace);
}
//script vars
string pSteamId = isaPlayer.steamid;
//string lSteamId = GetFamilyShare(isaPlayer.steamid);
//
LogDebug("Check for a twitter game ban");
if (config.AutoKick_KickTwitterGameBanned && !HasPerm(pSteamId, PermissionWhitelistTwitterBan)) {
if (isaPlayer.twitterBanId > 0) {
KickPlayer(isaPlayer?.steamid, $"https://twitter.com/rusthackreport/status/{isaPlayer.twitterBanId}", "C");
}
}
LogDebug("Check for a recent vac");
bool pRecentVac = (isaPlayer.steamNumberOfVACBans > 0 || isaPlayer.steamDaysSinceLastBan > 0) && isaPlayer.steamDaysSinceLastBan < config.DissallowVacBanDays;
//check main player
bool lRecentVac = (isaPlayer.lender?.steamNumberOfVACBans > 0 || isaPlayer.lender?.steamDaysSinceLastBan > 0) && isaPlayer.lender?.steamDaysSinceLastBan < config.DissallowVacBanDays;
//check the lender player
if (config.AutoKickOn && !HasPerm(pSteamId, PermissionWhitelistRecentVacKick) && (pRecentVac || lRecentVac)) {
int vacLast = pRecentVac ? isaPlayer.steamDaysSinceLastBan : isaPlayer.lender.steamDaysSinceLastBan;
int until = config.DissallowVacBanDays - vacLast;
Interface.CallHook("OnSARecentVacKick", vacLast, until);
string msg = GetMsg(pRecentVac ? "Reason: VAC Ban Too Fresh" : "Reason: VAC Ban Too Fresh - Lender", new Dictionary<string, string> {
["daysago"]
= vacLast.ToString(), ["daysto"] = until.ToString()
}
);
KickPlayer(isaPlayer?.steamid, msg, "C");
}
LogDebug("Check for a family share account");
if (!HasPerm(pSteamId, PermissionWhitelistFamilyShare) && config.AutoKickFamilyShare && IsFamilyShare(pSteamId)) {
Interface.CallHook("OnSAFamilyShareKick", pSteamId);
KickPlayer(isaPlayer?.steamid, GetMsg("Family Share Kick"), "C");
}
LogDebug("Check for too many vac bans");
if (!HasPerm(pSteamId, PermissionWhitelistVacCeilingKick) && HasReachedVacCeiling(isaPlayer)) {
Interface.CallHook("OnSATooManyVacKick", pSteamId, isaPlayer?.steamNumberOfVACBans);
KickPlayer(isaPlayer?.steamid, GetMsg("VAC Ceiling Kick"), "C");
}
LogDebug("Check for too many game bans");
if (!HasPerm(pSteamId, PermissionWhitelistGameBanCeilingKick) && HasReachedGameBanCeiling(isaPlayer)) {
Interface.CallHook("OnSATooManyGameBansKick", pSteamId, isaPlayer.steamNumberOfGameBans);
KickPlayer(isaPlayer?.steamid, GetMsg("Too Many Previous Game Bans"), "C");
}
/*LogDebug("Check for bloody/a4tech owner");
if (!HasPerm(pSteamId, PermissionWhitelistHardwareOwnsBloody) && (OwnsBloody(isaPlayer) || HasGroup(pSteamId, GroupBloody))) {
Interface.CallHook("OnSABloodyKick", pSteamId);
KickPlayer(isaPlayer?.steamid, GetMsg("Kick Bloody"), "C");
}*/
LogDebug("Check for players with too many server bans");
if (!HasPerm(pSteamId, PermissionWhitelistServerCeilingKick) && HasReachedServerCeiling(isaPlayer)) {
Interface.CallHook("OnSATooManyServerBans", pSteamId, config.AutoKickCeiling, ServerBanCount(isaPlayer) + ServerBanCount(isaPlayer.lender));
KickPlayer(isaPlayer?.steamid, GetMsg("Too Many Previous Bans"), "C");
}
if (!HasPerm(PermissionWhitelistTotalBanCeiling, pSteamId) && HasReachedTotalBanCeiling(isaPlayer)) {
Interface.CallHook("OnSATooManyBans", pSteamId, config.AutoKickCeiling, TotalBans(isaPlayer.lender));
KickPlayer(isaPlayer?.steamid, GetMsg("Too Many Previous Bans"), "C");
}
LogDebug("Check for players with a private profile");
if (!HasPerm(pSteamId, PermissionWhitelistSteamProfile) && config.AutoKick_KickPrivateProfile && isaPlayer.communityvisibilitystate == 1) {
Interface.CallHook("OnSAProfilePrivate", pSteamId, isaPlayer.communityvisibilitystate);
KickPlayer(isaPlayer?.steamid, GetMsg("Profile Private"), "C");
}
LogDebug("Check for a hidden steam level");
if (!HasPerm(pSteamId, PermissionWhitelistSteamProfile) && isaPlayer.steamlevel == -1 && config.AutoKick_KickHiddenLevel) {
Interface.CallHook("OnSASteamLevelHidden", pSteamId);
KickPlayer(isaPlayer?.steamid, GetMsg("Steam Level Hidden"), "C");
}
LogDebug("Check for low level steam account");
Puts($"Player {isaPlayer.steamid} is at steam level {isaPlayer.steamlevel}");
if (!HasPerm(pSteamId, PermissionWhitelistSteamProfile) && isaPlayer.steamlevel < config.AutoKick_MinSteamProfileLevel && isaPlayer.steamlevel >= 0) {
Interface.CallHook("OnSAProfileLevelLow", pSteamId, config.AutoKick_MinSteamProfileLevel, isaPlayer.steamlevel);
KickPlayer(isaPlayer?.steamid, GetMsg("Profile Low Level", new Dictionary<string, string> {
["level"]
= config.AutoKick_MinSteamProfileLevel.ToString()
}
), "C");
}
LogDebug("Check for VPN");
Puts($"IP/CACHE| ID:{id} ADD:{address} RATING:{isaPlayer.ipRating} AGE: {isaPlayer.ipLastCheck}");
if (config.AutoKickOn && config.AutoKick_BadIp && !HasPerm(id, PermissionWhitelistBadIPKick) && config.AutoKick_BadIp) {
if (IsBadIp(isaPlayer)) {
if (isaPlayer.ipInfo.proxy == "yes") KickPlayer(id, GetMsg("Reason: Proxy IP"), "C");
else KickPlayer(id, GetMsg("Reason: Bad IP"), "C");
Interface.CallHook("OnSAVPNKick", id, isaPlayer.ipRating);
}
}
GetPlayerReport(isaPlayer, connected);
}
, this, RequestMethod.POST, headers);
}
catch (ArgumentNullException ice) {
Puts("An ArgumentNullException occured.Please notify the developer along with the below information: ");
Puts(ice.Message);
return;
}
}
void KickIfBanned(ISAPlayer isaPlayer) {
if (isaPlayer == null) return;
IPlayer iPlayer = covalence.Players.FindPlayer(isaPlayer.steamid);
if (iPlayer != null && iPlayer.IsAdmin && config.IgnoreAdmins) return;
LogDebug("KIB 1");
ISABan ban = IsBanned(isaPlayer?.steamid);
LogDebug("KIB 2");
ISABan lban = IsBanned(isaPlayer?.lender?.steamid);
LogDebug("KIB 3");
if (ban != null) {
KickPlayer(isaPlayer?.steamid, ban.reason, "U");
}
if (lban != null) KickPlayer(isaPlayer?.steamid, GetMsg("Lender Banned"), "U");
}
void AddBan(IPlayer player, ISABan thisBan, bool doNative = true) {
if (config.IgnoreAdmins && player.IsAdmin) return;
if (thisBan == null) return;
string reason = Uri.EscapeDataString(thisBan.reason);
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/player/{player.Id}/addban", $"ip={player?.Address}&reason={reason}&dateTime={thisBan.created}&dateUntil={thisBan.banUntil}", (code, response) => {
if (code > 204) {
if (code == 500) {
timer.Once(5, () => AddBan(player, thisBan, doNative = true));
}
else {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
}
return;
}
// ISABan thisBan = new ISABan { serverName = server.Name, date = dateTime, reason = banreason, serverIp = thisServerIp, banUntil = dateBanUntil };
if (IsPlayerCached(player.Id)) {
LogDebug($"{player.Id} has ban cached, now updating.");
AddPlayerData(player.Id, thisBan);
}
else {
LogDebug($"{player.Id} had no ban data cached, now creating.");
ISAPlayer newPlayer = new ISAPlayer(player);
newPlayer.bans.Add(thisBan);
AddPlayerCached(player, newPlayer);
}
}
, this, RequestMethod.POST, headers);
}
void AddBan(string playerId, ISABan thisBan) {
if (thisBan == null) {
Puts($"This ban is null");
return;
}
string reason = Uri.EscapeDataString(thisBan.reason);
try {
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/player/{playerId}/addban", $"reason={reason}&dateTime={thisBan.created}&dateUntil={thisBan.banUntil}", (code, response) => {
if (code > 204) {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
return;
}
// ISABan thisBan = new ISABan { serverName = server.Name, date = dateTime, reason = banreason, serverIp = thisServerIp, banUntil = dateBanUntil };
if (IsPlayerCached(playerId)) {
LogDebug($"{playerId} has ban cached, now updating.");
AddPlayerData(playerId, thisBan);
}
else {
LogDebug($"{playerId} had no ban data cached, now creating.");
ISAPlayer newPlayer = new ISAPlayer(playerId);
newPlayer.bans.Add(thisBan);
AddPlayerCached(newPlayer);
}
SaveData();
}
, this, RequestMethod.POST, headers);
}
catch (Exception ice) {
Puts("An ArgumentNullException occured.Please notify the developer along with the below information: ");
Puts(ice.Message);
return;
}
}
#endregion
#region Commands
[Command("sa.clb", "getreport")]
void SCmdCheckLocalBans(IPlayer player, string command, string[] args) {
CheckLocalBans();
}
[Command("unban", "playerunban", "sa.unban"), Permission(PermissionToUnBan)]
void SCmdUnban(IPlayer player, string command, string[] args) {
if (args == null || (args.Length > 2 || args.Length < 1)) {
SendReplyWithIcon(player, GetMsg("UnBan Syntax"));
return;
}
var reason = args.Length > 1 ? args[1] : null;
SaUnban(args[0], player, reason);
}
void SilentBan(ulong steamId, TimeSpan timeSpan, string reason, IPlayer enforcer = null) {
Unsubscribe(nameof(OnUserBanned));
var username = covalence.Players.FindPlayerById(steamId.ToString())?.Name ?? "";
NativeBan(steamId, reason, Convert.ToInt64(timeSpan.TotalSeconds), username, enforcer);
Subscribe(nameof(OnUserBanned));
}
void SilentUnban(string playerId, IPlayer player) {
Unsubscribe(nameof(OnUserUnbanned));
NativeUnban(playerId, player);
Subscribe(nameof(OnUserUnbanned));
}
void NativeBan(ulong playerId, string reason, long duration = 0, string playerUsername = "unnamed", IPlayer player = null) {
if (!playerId.IsSteamId()) {
player?.Reply(string.Concat("This doesn't appear to be a 64bit steamid: ", playerId));
return;
}
ServerUsers.User user = ServerUsers.Get(playerId);
if (user != null && user.@group == ServerUsers.UserGroup.Banned) {
player?.Reply(string.Concat("User ", playerId, " is already banned"));
return;
}
string str3 = "";
BasePlayer basePlayer = BasePlayer.FindByID(playerId);
string durationSuffix = (duration > (long)0 ? string.Concat(" for ", duration.FormatSecondsLong()) : "");
if (basePlayer != null && basePlayer.IsConnected) {
playerUsername = basePlayer.displayName;
if (basePlayer.IsConnected && basePlayer.net.connection.ownerid != 0 && basePlayer.net.connection.ownerid != basePlayer.net.connection.userid) {
str3 = string.Concat(str3, string.Format(" and also banned ownerid {0}", basePlayer.net.connection.ownerid));
ServerUsers.Set(basePlayer.net.connection.ownerid, ServerUsers.UserGroup.Banned, basePlayer.displayName, reason, duration);
}
Chat.Broadcast(string.Concat(new string[] {
"Kickbanning ", basePlayer.displayName, durationSuffix, " (", reason, ")"
}
), "SERVER", "#eee", (ulong)0);
//Net.sv.Kick(basePlayer.net.connection, string.Concat("Banned", str, ": ", str2), false);
}
ServerUsers.Set(playerId, ServerUsers.UserGroup.Banned, playerUsername, reason, (long)(DateTime.Now.AddSeconds(duration) - Epoch).TotalSeconds);
player?.Reply(string.Format("Banned User{0}: {1} - \"{2}\" for \"{3}\"{4}", new object[] {
durationSuffix, playerId, playerUsername, reason, str3
}
));
}
/*
private static bool TryGetBanExpiry(ConsoleSystem.Arg arg, int n, out long expiry, out string durationSuffix)
{
expiry = arg.GetTimestamp(n, (long)-1);
durationSuffix = null;
int current = Epoch.Current;
if (expiry > (long)0 && expiry <= (long)current)
{
arg.ReplyWith("Expiry time is in the past");
return false;
}
durationSuffix = (expiry > (long)0 ? string.Concat(" for ", (expiry - (long)current).FormatSecondsLong()) : "");
return true;
}
public static void banid(ConsoleSystem.Arg arg)
{
long num;
string str;
ulong num1 = arg.GetUInt64(0, (ulong)0);
string str1 = arg.GetString(1, "unnamed");
string str2 = arg.GetString(2, "no reason");
if (num1 < 70000000000000000L)
{
arg.ReplyWith(string.Concat("This doesn't appear to be a 64bit steamid: ", num1));
return;
}
ServerUsers.User user = ServerUsers.Get(num1);
if (user != null && user.@group == ServerUsers.UserGroup.Banned)
{
arg.ReplyWith(string.Concat("User ", num1, " is already banned"));
return;
}
if (!Admin.TryGetBanExpiry(arg, 3, out num, out str))
{
return;
}
string str3 = "";
BasePlayer basePlayer = BasePlayer.FindByID(num1);
if (basePlayer != null && basePlayer.IsConnected)
{
str1 = basePlayer.displayName;
if (basePlayer.IsConnected && basePlayer.net.connection.ownerid != 0 && basePlayer.net.connection.ownerid != basePlayer.net.connection.userid)
{
str3 = string.Concat(str3, string.Format(" and also banned ownerid {0}", basePlayer.net.connection.ownerid));
ServerUsers.Set(basePlayer.net.connection.ownerid, ServerUsers.UserGroup.Banned, basePlayer.displayName, arg.GetString(1, string.Format("Family share owner of {0}", basePlayer.net.connection.userid)), num);
}
Chat.Broadcast(string.Concat(new string[] { "Kickbanning ", basePlayer.displayName, str, " (", str2, ")" }), "SERVER", "#eee", (ulong)0);
Net.sv.Kick(basePlayer.net.connection, string.Concat("Banned", str, ": ", str2), false);
}
ServerUsers.Set(num1, ServerUsers.UserGroup.Banned, str1, str2, num);
arg.ReplyWith(string.Format("Banned User{0}: {1} - \"{2}\" for \"{3}\"{4}", new object[] { str, num1, str1, str2, str3 }));
}
*/
bool NativeUnban(string playerId, IPlayer player = null) {
ulong playerIdLong = 0;
if (!ulong.TryParse(playerId, out playerIdLong)) {
var msg = string.Format("This doesn't appear to be a 64bit steamid: {0}", playerId);
if (player == null) {
Puts(msg);
}
else {
player.Reply(msg);
}
return false;
}
ServerUsers.User user = ServerUsers.Get(playerIdLong);
if (user == null || user.@group != ServerUsers.UserGroup.Banned) {
player?.Reply(string.Format("User {0} isn't banned", playerId));
return false;
}
ServerUsers.Remove(playerIdLong);
player?.Reply($"Unbanned User: {playerId}");
return true;
}
void SaUnban(string playerId, IPlayer player = null, string reason = null) {
IPlayer iPlayer = players.FindPlayer(playerId);
SilentUnban(playerId, player);
if (iPlayer == null) {
GetMsg("Player Not Found", new Dictionary<string, string> {
["player"]
= playerId
}
);
return;
}
RemoveBans(iPlayer.Id);
LogDebug($"Player {iPlayer?.Name} ({iPlayer.Id}) was unbanned by {player?.Name} ({player?.Id})");
// Add ember support.if (Ember != null)
{
Ember?.Call("Unban", playerId, Player.FindById(player?.Id));
}
//
webrequest.Enqueue($"{api_hostname}/api/v1/plugin/player/ban/pardon/{iPlayer.Id}", $"", (code, response) => {
if (code > 204 || response == null) {
Puts(GetMsg("No Response From API", new Dictionary<string, string> {
["code"]
= code.ToString(), ["response"] = response
}
));
return;
}
if (code <= 204) {
if (config.RconBroadcast) RCon.Broadcast(RCon.LogType.Chat, new Chat.ChatEntry {
Message = $"Player was unbanned by {player?.Name} ({player?.Id})", UserId = iPlayer.Id, Username = iPlayer?.Name ?? "", Time = Facepunch.Math.Epoch.Current
}
);
if (player != null && config.RconBroadcast) {
RCon.Broadcast(RCon.LogType.Chat, new Chat.ChatEntry {
Message = $"Player { iPlayer?.Name } ({ iPlayer.Id }) was unbanned", UserId = player?.Id, Username = player?.Name ?? "", Time = Facepunch.Math.Epoch.Current
}
);
}
if (player != null && !player.IsServer) {
SendReplyWithIcon(player, $"Player { iPlayer?.Name } ({ iPlayer.Id }) was unbanned");
}
}
}
, this, RequestMethod.POST, headers);
string msgClean = "";
if (reason.IsNullOrEmpty()) {
msgClean = GetMsg("Player Now Unbanned Clean - NoReason", new Dictionary<string, string> {
["player"]
= iPlayer.Name
}
);
}
else {
msgClean = GetMsg("Player Now Unbanned Clean - Reason", new Dictionary<string, string> {
["player"]
= iPlayer.Name, ["reason"] = reason
}
);
}
if (config.DiscordBanReport) {
DiscordSend(playerId, iPlayer.Name, new EmbedFieldList() {
name = "Player Unbanned", value = msgClean, inline = true
}
, 3066993, true);
}
}
//banid 76561198007433923 "Pho3niX90" "Some reason" 1953394942
[Command("banid"), Permission(PermissionToBan)]
void SCmdBanId(IPlayer player, string command, string[] args) {
/*foreach(var ar in args) {
Puts(ar.ToString());
}*/
/*
[0] steam64id
[1] username
[2] reason
[3] length
*/
if (args.Length > 0) {
var playerId = args[0];
var reason = "No reason provided.";
var length = "100y";
//RustAdminSupport
if (args.Length >= 3) {
reason = args[2];
if (args.Length > 3) {
length = args[3];
}
}
API_BanPlayer(player, playerId, reason, length, true);
}
}
[Command("ban", "playerban", "sa.ban"), Permission(PermissionToBan)]
void SCmdBan(IPlayer player, string command, string[] args) {
int argsLength = args == null ? 0 : args.Length;
if (argsLength > 0 && argsLength < 2 && !args[0].IsSteamId()) {
SendReplyWithIcon(player, GetMsg("Ban Syntax"));
return;
}
/***
* Length 2: player, reason
* Length 3: player, reason, time
* Length 4: playerSteamId, reason, time, ignoreSearch
***/
if (args == null || (argsLength > 4)) {
SendReplyWithIcon(player, GetMsg("Ban Syntax"));
return;
}
var playerId = args[0];
var reason = argsLength < 2 ? "No reason provided." : args[1];
var length = args.Length > 2 ? args[2].ToUpper() : "100Y";
var ignoreSearch = false;
if (args.Length > 3) bool.TryParse(args[3], out ignoreSearch);
try {
API_BanPlayer(player, playerId, reason, length, ignoreSearch);
}
catch (Exception) {
SendReplyWithIcon(player, GetMsg("Ban Syntax"));
}
}
[Command("clanban"), Permission(PermissionToBan)]
void SCmdClanBan(IPlayer player, string command, string[] args) {
int argsLength = args == null ? 0 : args.Length;
/***
* Length 2: player, reason
* Length 3: player, reason, time
* Length 4: playerSteamId, reason, time, ignoreSearch
***/
if (args == null || (argsLength < 2 || argsLength > 4)) {
SendReplyWithIcon(player, GetMsg("Ban Syntax"));
return;
}
var playerId = args[0];
var reason = args[1];
var length = args.Length > 2 ? args[2] : "100y";
var ignoreSearch = false;
var errMsg = "";
IPlayer iPlayer = null;
IEnumerable<IPlayer> playersFound = players.FindPlayers(playerId);
int playersFoundCount = playersFound.Count();
switch (playersFoundCount) {
case 0 : errMsg = GetMsg("Player Not Found", new Dictionary<string, string> {
["player"]
= playerId
}
);
break;
case 1 : iPlayer = players.FindPlayer(playerId);
break;
default : List<string> playersFoundNames = new List<string>();
for (int i = 0; i < playersFoundCount; i++) playersFoundNames.Add(playersFound.ElementAt(i).Name);
string playersFoundNamesString = String.Join(", ", playersFoundNames.ToArray());
errMsg = GetMsg("Multiple Players Found", new Dictionary<string, string> {
["players"]
= playersFoundNamesString
}
);
break;
}
if ((!ignoreSearch && iPlayer == null) || !errMsg.Equals("")) {
SendReplyWithIcon(player, errMsg);
return;
}
ulong playerIdU = ulong.Parse(iPlayer.Id);
List<ulong> teamMembers = new List<ulong>();
if (config.ClanBanTeams) {
teamMembers = GetTeamMembers(playerIdU);
}
if (Clans != null && Clans.IsLoaded) {
var clanMembers = GetClan(playerId);
if (clanMembers != null && clanMembers.Count() > 0) {
teamMembers.AddRange(clanMembers);
}
}
teamMembers = teamMembers.Distinct().ToList();
teamMembers?.Remove(ulong.Parse(playerId));
try {
ignoreSearch = bool.Parse(args[3]);
}
catch (Exception) {
}
API_BanPlayer(player, playerId, reason, length, ignoreSearch);
if (teamMembers.Count() > 0) {
var clanBanReason = config.ClanBanPrefix.Replace("{reason}", reason).Replace("{playerId}", playerId);
foreach (var member in teamMembers) {
API_BanPlayer(player, member.ToString(), clanBanReason, length, ignoreSearch);
}
}
}
[Command("sa.cp")]
void SCmdCheckPlayer(IPlayer player, string command, string[] args) {
string playerArg = (args.Length == 0) ? player.Id : args[0];
IPlayer playerToCheck = players.FindPlayer(playerArg.Trim());
if (playerToCheck == null) {
SendReplyWithIcon(player, GetMsg("Player Not Found", new Dictionary<string, string> {
["player"]
= playerArg
}
));
return;
}
GetPlayerReport(playerToCheck, player);
}
#endregion
#region VPN/Proxy
#endregion
#region Ban System
string BanMinutes(DateTime ban) {
return ((int)Math.Round((ban - DateTime.UtcNow).TotalMinutes)).ToString();
}
DateTime _BanUntil(string banLength) {
int digit = int.Parse(new string(banLength.Where(char.IsDigit).ToArray()));
string del = new string(banLength.Where(char.IsLetter).ToArray());
if (digit <= 0) {
// ... [Code preview truncated due to length. Full source in attached file] ...