C#:
using Newtonsoft.Json;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using System.Collections.Generic;
using System.Net;
using System.Text.RegularExpressions;
using System.Text;
using System;
using UnityEngine;
using System.Linq;
namespace Oxide.Plugins
{
[Info("Discord Logger", "MON@H", "2.0.11")]
[Description("Logs events to Discord channels using webhooks")]
class DiscordLogger : RustPlugin
{
#region Variables
[PluginReference] private Plugin AntiSpam, BetterChatMute, CallHeli, PersonalHeli, UFilter;
private readonly Hash<uint, CargoShip> _cargoShips = new Hash<uint, CargoShip>();
private readonly List<uint> _listBadCargoShips = new List<uint>();
private readonly List<uint> _listSupplyDrops = new List<uint>();
private readonly Queue<QueuedMessage> _queue = new Queue<QueuedMessage>();
private readonly StringBuilder _sb = new StringBuilder();
private EventSettings _eventSettings;
private int _retryCount = 0;
private object _resultCall;
private QueuedMessage _nextMessage;
private QueuedMessage _queuedMessage;
private string _langKey;
private string[] _profanities;
private Timer _timerQueue;
private Timer _timerQueueCooldown;
private uint _entityID;
private Vector3 _locationLargeOilRig;
private Vector3 _locationOilRig;
private readonly List<Regex> _regexTags = new List<Regex>
{
new Regex("<color=.+?>", RegexOptions.Compiled),
new Regex("<size=.+?>", RegexOptions.Compiled)
};
private readonly List<string> _tags = new List<string>
{
"</color>",
"</size>",
"<i>",
"</i>",
"<b>",
"</b>"
};
private class QueuedMessage
{
public string WebhookUrl { set; get; }
public string Message { set; get; }
}
private enum TeamEventType
{
Created,
Disbanded,
Updated,
}
private class Response
{
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("countryCode")]
public string CountryCode { get; set; }
}
#endregion Variables
#region Initialization
private void Init()
{
UnsubscribeHooks();
}
private void Unload()
{
Application.logMessageReceivedThreaded -= HandleLog;
}
private void OnServerInitialized(bool isStartup)
{
if (isStartup && _configData.ServerStateSettings.Enabled)
{
LogToConsole("Server is online again!");
DiscordSendMessage(Lang(LangKeys.Event.Initialized), _configData.ServerStateSettings.WebhookURL);
}
CacheOilRigsLocation();
SubscribeHooks();
}
private void OnServerShutdown()
{
if (_configData.ServerStateSettings.Enabled)
{
LogToConsole("Server is shutting down!");
string url = GetWebhookURL(_configData.ServerStateSettings.WebhookURL);
if (!string.IsNullOrEmpty(url))
{
webrequest.Enqueue(url, new DiscordMessage(Lang(LangKeys.Event.Shutdown)).ToJson(), DiscordSendMessageCallback, null, RequestMethod.POST, _headers);
}
}
}
#endregion Initialization
#region Configuration
private ConfigData _configData;
private class ConfigData
{
[JsonProperty(PropertyName = "Global settings")]
public GlobalSettings GlobalSettings = new GlobalSettings();
[JsonProperty(PropertyName = "Admin Hammer settings")]
public EventSettings AdminHammerSettings = new EventSettings();
[JsonProperty(PropertyName = "Admin Radar settings")]
public EventSettings AdminRadarSettings = new EventSettings();
[JsonProperty(PropertyName = "Bradley settings")]
public EventSettings BradleySettings = new EventSettings();
[JsonProperty(PropertyName = "Cargo Ship settings")]
public EventSettings CargoShipSettings = new EventSettings();
[JsonProperty(PropertyName = "Cargo Plane settings")]
public EventSettings CargoPlaneSettings = new EventSettings();
[JsonProperty(PropertyName = "Chat settings")]
public EventSettings ChatSettings = new EventSettings();
[JsonProperty(PropertyName = "Chat (Team) settings")]
public EventSettings ChatTeamSettings = new EventSettings();
[JsonProperty(PropertyName = "CH47 Helicopter settings")]
public EventSettings ChinookSettings = new EventSettings();
[JsonProperty(PropertyName = "Christmas settings")]
public EventSettings ChristmasSettings = new EventSettings();
[JsonProperty(PropertyName = "Clan settings")]
public EventSettings ClanSettings = new EventSettings();
[JsonProperty(PropertyName = "Dangerous Treasures settings")]
public EventSettings DangerousTreasuresSettings = new EventSettings();
[JsonProperty(PropertyName = "Duel settings")]
public EventSettings DuelSettings = new EventSettings();
[JsonProperty(PropertyName = "Godmode settings")]
public EventSettings GodmodeSettings = new EventSettings();
[JsonProperty(PropertyName = "Easter settings")]
public EventSettings EasterSettings = new EventSettings();
[JsonProperty(PropertyName = "Error settings")]
public EventSettings ErrorSettings = new EventSettings();
[JsonProperty(PropertyName = "Hackable Locked Crate settings")]
public EventSettings LockedCrateSettings = new EventSettings();
[JsonProperty(PropertyName = "Halloween settings")]
public EventSettings HalloweenSettings = new EventSettings();
[JsonProperty(PropertyName = "Helicopter settings")]
public EventSettings HelicopterSettings = new EventSettings();
[JsonProperty(PropertyName = "NTeleportation settings")]
public EventSettings NTeleportationSettings = new EventSettings();
[JsonProperty(PropertyName = "Permissions settings")]
public EventSettings PermissionsSettings = new EventSettings();
[JsonProperty(PropertyName = "Player death settings")]
public EventSettings PlayerDeathSettings = new EventSettings();
[JsonProperty(PropertyName = "Player DeathNotes settings")]
public EventSettings PlayerDeathNotesSettings = new EventSettings();
[JsonProperty(PropertyName = "Player connect advanced info settings")]
public EventSettings PlayerConnectedInfoSettings = new EventSettings();
[JsonProperty(PropertyName = "Player connect settings")]
public EventSettings PlayerConnectedSettings = new EventSettings();
[JsonProperty(PropertyName = "Player disconnect settings")]
public EventSettings PlayerDisconnectedSettings = new EventSettings();
[JsonProperty(PropertyName = "Player Respawned settings")]
public EventSettings PlayerRespawnedSettings = new EventSettings();
[JsonProperty(PropertyName = "Private Messages settings")]
public EventSettings PrivateMessagesSettings = new EventSettings();
[JsonProperty(PropertyName = "Raidable Bases settings")]
public EventSettings RaidableBasesSettings = new EventSettings();
[JsonProperty(PropertyName = "Rcon command settings")]
public EventSettings RconCommandSettings = new EventSettings();
[JsonProperty(PropertyName = "Rcon connection settings")]
public EventSettings RconConnectionSettings = new EventSettings();
[JsonProperty(PropertyName = "Rust Kits settings")]
public EventSettings RustKitsSettings = new EventSettings();
[JsonProperty(PropertyName = "SantaSleigh settings")]
public EventSettings SantaSleighSettings = new EventSettings();
[JsonProperty(PropertyName = "Server messages settings")]
public EventSettings ServerMessagesSettings = new EventSettings();
[JsonProperty(PropertyName = "Server state settings")]
public EventSettings ServerStateSettings = new EventSettings();
[JsonProperty(PropertyName = "Supply Drop settings")]
public EventSettings SupplyDropSettings = new EventSettings();
[JsonProperty(PropertyName = "Teams settings")]
public EventSettings TeamsSettings = new EventSettings();
[JsonProperty(PropertyName = "User Banned settings")]
public EventSettings UserBannedSettings = new EventSettings();
[JsonProperty(PropertyName = "User Kicked settings")]
public EventSettings UserKickedSettings = new EventSettings();
[JsonProperty(PropertyName = "User Muted settings")]
public EventSettings UserMutedSettings = new EventSettings();
[JsonProperty(PropertyName = "User Name Updated settings")]
public EventSettings UserNameUpdateSettings = new EventSettings();
[JsonProperty(PropertyName = "Vanish settings")]
public EventSettings VanishSettings = new EventSettings();
}
private class GlobalSettings
{
[JsonProperty(PropertyName = "Log to console?")]
public bool LoggingEnabled = false;
[JsonProperty(PropertyName = "Use AntiSpam plugin on chat messages")]
public bool UseAntiSpam = false;
[JsonProperty(PropertyName = "Use UFilter plugin on chat messages")]
public bool UseUFilter = false;
[JsonProperty(PropertyName = "Hide admin connect/disconnect messages")]
public bool HideAdmin = false;
[JsonProperty(PropertyName = "Hide NPC death messages")]
public bool HideNPC = false;
[JsonProperty(PropertyName = "Replacement string for tags")]
public string TagsReplacement = "`";
[JsonProperty(PropertyName = "Queue interval (1 message per ? seconds)")]
public float QueueInterval = 1f;
[JsonProperty(PropertyName = "Queue cooldown if connection error (seconds)")]
public float QueueCooldown = 60f;
[JsonProperty(PropertyName = "Default WebhookURL")]
public string DefaultWebhookURL = string.Empty;
[JsonProperty(PropertyName = "RCON command blacklist", ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<string> RCONCommandBlacklist = new List<string>()
{
"playerlist",
"status"
};
}
private class EventSettings
{
[JsonProperty(PropertyName = "WebhookURL")]
public string WebhookURL = "";
[JsonProperty(PropertyName = "Enabled?")]
public bool Enabled = false;
}
protected override void LoadConfig()
{
base.LoadConfig();
try
{
_configData = Config.ReadObject<ConfigData>();
if (_configData == null)
{
LoadDefaultConfig();
SaveConfig();
}
}
catch
{
PrintError("The configuration file is corrupted");
LoadDefaultConfig();
SaveConfig();
}
}
protected override void LoadDefaultConfig()
{
PrintWarning("Creating a new configuration file");
_configData = new ConfigData();
}
protected override void SaveConfig() => Config.WriteObject(_configData);
#endregion Configuration
#region Localization
private string Lang(string key, string userIDString = null, params object[] args)
{
try
{
return string.Format(lang.GetMessage(key, this, userIDString).Replace("{time}", DateTime.Now.ToShortTimeString()), args);
}
catch (Exception ex)
{
PrintError($"Lang Key '{key}' threw exception:\n{ex}");
throw;
}
}
private static class LangKeys
{
public static class Event
{
private const string Base = nameof(Event) + ".";
public const string Bradley = Base + nameof(Bradley);
public const string CargoPlane = Base + nameof(CargoPlane);
public const string CargoShip = Base + nameof(CargoShip);
public const string Chat = Base + nameof(Chat);
public const string ChatTeam = Base + nameof(ChatTeam);
public const string Chinook = Base + nameof(Chinook);
public const string Christmas = Base + nameof(Christmas);
public const string Death = Base + nameof(Death);
public const string Easter = Base + nameof(Easter);
public const string EasterWinner = Base + nameof(EasterWinner);
public const string Error = Base + nameof(Error);
public const string Halloween = Base + nameof(Halloween);
public const string HalloweenWinner = Base + nameof(HalloweenWinner);
public const string Helicopter = Base + nameof(Helicopter);
public const string Initialized = Base + nameof(Initialized);
public const string LockedCrate = Base + nameof(LockedCrate);
public const string PlayerConnected = Base + nameof(PlayerConnected);
public const string PlayerConnectedInfo = Base + nameof(PlayerConnectedInfo);
public const string PlayerDisconnected = Base + nameof(PlayerDisconnected);
public const string PlayerRespawned = Base + nameof(PlayerRespawned);
public const string RconCommand = Base + nameof(RconCommand);
public const string RconConnection = Base + nameof(RconConnection);
public const string SantaSleigh = Base + nameof(SantaSleigh);
public const string ServerMessage = Base + nameof(ServerMessage);
public const string Shutdown = Base + nameof(Shutdown);
public const string SupplyDrop = Base + nameof(SupplyDrop);
public const string SupplyDropLanded = Base + nameof(SupplyDropLanded);
public const string SupplySignal = Base + nameof(SupplySignal);
public const string Team = Base + nameof(Team);
public const string UserBanned = Base + nameof(UserBanned);
public const string UserKicked = Base + nameof(UserKicked);
public const string UserMuted = Base + nameof(UserMuted);
public const string UserNameUpdated = Base + nameof(UserNameUpdated);
public const string UserUnbanned = Base + nameof(UserUnbanned);
public const string UserUnmuted = Base + nameof(UserUnmuted);
}
public static class Permission
{
private const string Base = nameof(Permission) + ".";
public const string GroupCreated = Base + nameof(GroupCreated);
public const string GroupDeleted = Base + nameof(GroupDeleted);
public const string UserGroupAdded = Base + nameof(UserGroupAdded);
public const string UserGroupRemoved = Base + nameof(UserGroupRemoved);
public const string UserPermissionGranted = Base + nameof(UserPermissionGranted);
public const string UserPermissionRevoked = Base + nameof(UserPermissionRevoked);
}
public static class Plugin
{
private const string Base = nameof(Plugin) + ".";
public const string AdminHammerOff = Base + nameof(AdminHammerOff);
public const string AdminHammerOn = Base + nameof(AdminHammerOn);
public const string AdminRadarOff = Base + nameof(AdminRadarOff);
public const string AdminRadarOn = Base + nameof(AdminRadarOn);
public const string ClanCreated = Base + nameof(ClanCreated);
public const string ClanDisbanded = Base + nameof(ClanDisbanded);
public const string DangerousTreasuresEnded = Base + nameof(DangerousTreasuresEnded);
public const string DangerousTreasuresStarted = Base + nameof(DangerousTreasuresStarted);
public const string DeathNotes = Base + nameof(DeathNotes);
public const string Duel = Base + nameof(Duel);
public const string GodmodeOff = Base + nameof(GodmodeOff);
public const string GodmodeOn = Base + nameof(GodmodeOn);
public const string NTeleportation = Base + nameof(NTeleportation);
public const string PersonalHelicopter = Base + nameof(PersonalHelicopter);
public const string PrivateMessage = Base + nameof(PrivateMessage);
public const string RaidableBaseCompleted = Base + nameof(RaidableBaseCompleted);
public const string RaidableBaseEnded = Base + nameof(RaidableBaseEnded);
public const string RaidableBaseStarted = Base + nameof(RaidableBaseStarted);
public const string RustKits = Base + nameof(RustKits);
public const string TimedGroupAdded = Base + nameof(TimedGroupAdded);
public const string TimedGroupExtended = Base + nameof(TimedGroupExtended);
public const string TimedPermissionExtended = Base + nameof(TimedPermissionExtended);
public const string TimedPermissionGranted = Base + nameof(TimedPermissionGranted);
public const string VanishOff = Base + nameof(VanishOff);
public const string VanishOn = Base + nameof(VanishOn);
}
public static class Format
{
private const string Base = nameof(Format) + ".";
public const string CargoShip = Base + nameof(CargoShip);
public const string Created = Base + nameof(Created);
public const string Day = Base + nameof(Day);
public const string Days = Base + nameof(Days);
public const string Disbanded = Base + nameof(Disbanded);
public const string Easy = Base + nameof(Easy);
public const string Expert = Base + nameof(Expert);
public const string Hard = Base + nameof(Hard);
public const string Hour = Base + nameof(Hour);
public const string Hours = Base + nameof(Hours);
public const string LargeOilRig = Base + nameof(LargeOilRig);
public const string Medium = Base + nameof(Medium);
public const string Minute = Base + nameof(Minute);
public const string Minutes = Base + nameof(Minutes);
public const string Nightmare = Base + nameof(Nightmare);
public const string OilRig = Base + nameof(OilRig);
public const string Second = Base + nameof(Second);
public const string Seconds = Base + nameof(Seconds);
public const string Updated = Base + nameof(Updated);
}
}
protected override void LoadDefaultMessages()
{
lang.RegisterMessages(new Dictionary<string, string>
{
[LangKeys.Event.Bradley] = ":dagger: {time} Bradley spawned `{0}`",
[LangKeys.Event.CargoPlane] = ":airplane: {time} Cargo Plane incoming `{0}`",
[LangKeys.Event.CargoShip] = ":ship: {time} Cargo Ship incoming `{0}`",
[LangKeys.Event.Chat] = ":speech_left: {time} **{0}**: {1}",
[LangKeys.Event.ChatTeam] = ":busts_in_silhouette: {time} **{0}**: {1}",
[LangKeys.Event.Chinook] = ":helicopter: {time} Chinook 47 incoming `{0}`",
[LangKeys.Event.Christmas] = ":christmas_tree: {time} Christmas event started",
[LangKeys.Event.Death] = ":skull: {time} `{0}` died",
[LangKeys.Event.Easter] = ":egg: {time} Easter event started",
[LangKeys.Event.EasterWinner] = ":egg: {time} Easter event ended. The winner is `{0}`",
[LangKeys.Event.Error] = ":octagonal_sign: {time}\n{0}",
[LangKeys.Event.Halloween] = ":jack_o_lantern: {time} Halloween event started",
[LangKeys.Event.HalloweenWinner] = ":jack_o_lantern: {time} Halloween event ended. The winner is `{0}`",
[LangKeys.Event.Helicopter] = ":dagger: {time} Helicopter incoming `{0}`",
[LangKeys.Event.Initialized] = ":ballot_box_with_check: {time} Server is online again!",
[LangKeys.Event.LockedCrate] = ":package: {time} Codelocked crate is here `{0}`",
[LangKeys.Event.PlayerConnected] = ":white_check_mark: {time} {0} connected",
[LangKeys.Event.PlayerConnectedInfo] = ":detective: {time} {0} connected. SteamID: `{1}` IP: `{2}`",
[LangKeys.Event.PlayerDisconnected] = ":x: {time} {0} disconnected ({1})",
[LangKeys.Event.PlayerRespawned] = ":baby_symbol: {time} `{0}` has been spawned at `{1}`",
[LangKeys.Event.RconCommand] = ":satellite: {time} RCON command `{0}` is run from `{1}`",
[LangKeys.Event.RconConnection] = ":satellite: {time} RCON connection is opened from `{0}`",
[LangKeys.Event.Team] = ":family_man_girl_boy: {time} Team was `{0}`\n{1}",
[LangKeys.Event.SantaSleigh] = ":santa: {time} SantaSleigh Event started",
[LangKeys.Event.ServerMessage] = ":desktop: {time} `{0}`",
[LangKeys.Event.Shutdown] = ":stop_sign: {time} Server is shutting down!",
[LangKeys.Event.SupplyDrop] = ":parachute: {time} SupplyDrop incoming at `{0}`",
[LangKeys.Event.SupplyDropLanded] = ":gift: {time} SupplyDrop landed at `{0}`",
[LangKeys.Event.SupplySignal] = ":firecracker: {time} SupplySignal was thrown by `{0}` at `{1}`",
[LangKeys.Event.UserBanned] = ":no_entry: {time} Player `{0}` SteamID: `{1}` IP: `{2}` was banned: `{3}`",
[LangKeys.Event.UserKicked] = ":hiking_boot: {time} Player `{0}` SteamID: `{1}` was kicked: `{2}`",
[LangKeys.Event.UserMuted] = ":mute: {time} `{0}` was muted by `{1}` for `{2}` (`{3}`)",
[LangKeys.Event.UserNameUpdated] = ":label: {time} `{0}` changed name to `{1}` SteamID: `{2}`",
[LangKeys.Event.UserUnbanned] = ":ok: {time} Player `{0}` SteamID: `{1}` IP: `{2}` was unbanned",
[LangKeys.Event.UserUnmuted] = ":speaker: {time} `{0}` was unmuted `{1}`",
[LangKeys.Format.CargoShip] = "Cargo Ship",
[LangKeys.Format.Created] = "created",
[LangKeys.Format.Day] = "day",
[LangKeys.Format.Days] = "days",
[LangKeys.Format.Disbanded] = "disbanded",
[LangKeys.Format.Easy] = "Easy",
[LangKeys.Format.Expert] = "Expert",
[LangKeys.Format.Hard] = "Hard",
[LangKeys.Format.Hour] = "hour",
[LangKeys.Format.Hours] = "hours",
[LangKeys.Format.LargeOilRig] = "Large Oil Rig",
[LangKeys.Format.Medium] = "Medium",
[LangKeys.Format.Minute] = "minute",
[LangKeys.Format.Minutes] = "minutes",
[LangKeys.Format.Nightmare] = "Nightmare",
[LangKeys.Format.OilRig] = "Oil Rig",
[LangKeys.Format.Second] = "second",
[LangKeys.Format.Seconds] = "seconds",
[LangKeys.Format.Updated] = "updated",
[LangKeys.Permission.GroupCreated] = ":family: {time} Group `{0}` has been created",
[LangKeys.Permission.GroupDeleted] = ":family: {time} Group `{0}` has been deleted",
[LangKeys.Permission.UserGroupAdded] = ":family: {time} `{0}` `{1}` is added to group `{2}`",
[LangKeys.Permission.UserGroupRemoved] = ":family: {time} `{0}` `{1}` is removed from group `{2}`",
[LangKeys.Permission.UserPermissionGranted] = ":key: {time} `{0}` `{1}` is granted `{2}`",
[LangKeys.Permission.UserPermissionRevoked] = ":key: {time} `{0}` `{1}` is revoked `{2}`",
[LangKeys.Plugin.AdminHammerOff] = ":hammer: {time} AdminHammer enabled by `{0}`",
[LangKeys.Plugin.AdminHammerOn] = ":hammer: {time} AdminHammer disabled by `{0}`",
[LangKeys.Plugin.AdminRadarOff] = ":compass: {time} Admin Radar enabled by `{0}`",
[LangKeys.Plugin.AdminRadarOn] = ":compass: {time} Admin Radar disabled by `{0}`",
[LangKeys.Plugin.ClanCreated] = ":family_mwgb: {time} **{0}** clan was created",
[LangKeys.Plugin.ClanDisbanded] = ":family_mwgb: {time} **{0}** clan was disbanded",
[LangKeys.Plugin.DangerousTreasuresEnded] = ":pirate_flag: {time} Dangerous Treasures event at `{0}` is ended",
[LangKeys.Plugin.DangerousTreasuresStarted] = ":pirate_flag: {time} Dangerous Treasures started at `{0}`",
[LangKeys.Plugin.DeathNotes] = ":skull_crossbones: {time} {0}",
[LangKeys.Plugin.Duel] = ":crossed_swords: {time} `{0}` has defeated `{1}` in a duel",
[LangKeys.Plugin.GodmodeOff] = ":angel: {time} Godmode disabled for `{0}`",
[LangKeys.Plugin.GodmodeOn] = ":angel: {time} Godmode enabled for `{0}`",
[LangKeys.Plugin.NTeleportation] = ":cyclone: {time} `{0}` teleported from `{1}` `{2}` to `{3}` `{4}`",
[LangKeys.Plugin.PersonalHelicopter] = ":dagger: {time} Personal Helicopter incoming `{0}`",
[LangKeys.Plugin.PrivateMessage] = ":envelope: {time} PM from `{0}` to `{1}`: {2}",
[LangKeys.Plugin.RaidableBaseCompleted] = ":homes: {time} {1} Raidable Base owned by {2} at `{0}` has been raided by **{3}**",
[LangKeys.Plugin.RaidableBaseEnded] = ":homes: {time} {1} Raidable Base at `{0}` has ended",
[LangKeys.Plugin.RaidableBaseStarted] = ":homes: {time} {1} Raidable Base spawned at `{0}`",
[LangKeys.Plugin.RustKits] = ":shopping_bags: {time} `{0}` redeemed a kit `{1}`",
[LangKeys.Plugin.TimedGroupAdded] = ":timer: {time} `{0}` `{1}` is added to `{2}` for {3}",
[LangKeys.Plugin.TimedGroupExtended] = ":timer: {time} `{0}` `{1}` timed group `{2}` is extended to {3}",
[LangKeys.Plugin.TimedPermissionExtended] = ":timer: {time} `{0}` `{1}` timed permission `{2}` is extended to {3}",
[LangKeys.Plugin.TimedPermissionGranted] = ":timer: {time} `{0}` `{1}` is granted `{2}` for {3}",
[LangKeys.Plugin.VanishOff] = ":ghost: {time} Vanish: Disabled for `{0}`",
[LangKeys.Plugin.VanishOn] = ":ghost: {time} Vanish: Enabled for `{0}`",
}, this);
}
#endregion Localization
#region Events Hooks
private void OnAdminHammerEnabled(BasePlayer player)
{
LogToConsole($"AdminHammer enabled by {player.UserIDString} {player.displayName}");
DiscordSendMessage(Lang(LangKeys.Plugin.AdminHammerOff, null, ReplaceChars(player.displayName)), _configData.AdminHammerSettings.WebhookURL);
}
private void OnAdminHammerDisabled(BasePlayer player)
{
LogToConsole($"AdminHammer disabled by {player.UserIDString} {player.displayName}");
DiscordSendMessage(Lang(LangKeys.Plugin.AdminHammerOn, null, ReplaceChars(player.displayName)), _configData.AdminHammerSettings.WebhookURL);
}
private void OnBetterChatMuted(IPlayer target, IPlayer initiator, string reason)
{
LogToConsole($"{target.Name} was muted by {initiator.Name} for ever ({reason})");
DiscordSendMessage(Lang(LangKeys.Event.UserMuted, null, ReplaceChars(target.Name), ReplaceChars(initiator.Name), "ever", ReplaceChars(reason)), _configData.UserMutedSettings.WebhookURL);
}
private void OnBetterChatMuteExpired(IPlayer player)
{
LogToConsole($"{player.Name} was unmuted by SERVER");
DiscordSendMessage(Lang(LangKeys.Event.UserUnmuted, null, ReplaceChars(player.Name), "SERVER"), _configData.UserMutedSettings.WebhookURL);
}
private void OnBetterChatTimeMuted(IPlayer target, IPlayer initiator, TimeSpan time, string reason)
{
LogToConsole($"{target.Name} was muted by {initiator.Name} for {time.ToShortString()} ({reason})");
DiscordSendMessage(Lang(LangKeys.Event.UserMuted, null, ReplaceChars(target.Name), ReplaceChars(initiator.Name), time.ToShortString(), ReplaceChars(reason)), _configData.UserMutedSettings.WebhookURL);
}
private void OnBetterChatUnmuted(IPlayer target, IPlayer initiator)
{
LogToConsole($"{target.Name} was unmuted by {initiator.Name}");
DiscordSendMessage(Lang(LangKeys.Event.UserUnmuted, null, ReplaceChars(target.Name), ReplaceChars(initiator.Name)), _configData.UserMutedSettings.WebhookURL);
}
private void OnClanCreate(string tag)
{
LogToConsole($"{tag} clan was created");
DiscordSendMessage(Lang(LangKeys.Plugin.ClanCreated, null, ReplaceChars(tag)), _configData.ClanSettings.WebhookURL);
}
private void OnClanDisbanded(string tag)
{
LogToConsole($"{tag} clan was disbanded");
DiscordSendMessage(Lang(LangKeys.Plugin.ClanDisbanded, null, ReplaceChars(tag)), _configData.ClanSettings.WebhookURL);
}
private void OnDangerousEventStarted(Vector3 containerPos)
{
HandleDangerousTreasures(containerPos, LangKeys.Plugin.DangerousTreasuresStarted);
}
private void OnDangerousEventEnded(Vector3 containerPos)
{
HandleDangerousTreasures(containerPos, LangKeys.Plugin.DangerousTreasuresEnded);
}
private void OnDeathNotice(Dictionary<string, object> data, string message)
{
DiscordSendMessage(Lang(LangKeys.Plugin.DeathNotes, null, StripRustTags(Formatter.ToPlaintext(message))), _configData.PlayerDeathNotesSettings.WebhookURL);
}
private void OnDuelistDefeated(BasePlayer attacker, BasePlayer victim)
{
if (!attacker.IsValid() || !victim.IsValid())
{
return;
}
LogToConsole($"{attacker.displayName} has defeated {victim.displayName} in a duel");
DiscordSendMessage(Lang(LangKeys.Plugin.Duel, null, ReplaceChars(attacker.displayName), ReplaceChars(victim.displayName)), _configData.DuelSettings.WebhookURL);
}
private void OnEntitySpawned(BaseHelicopter entity)
{
NextTick(() => HandleEntity(entity));
}
private void OnEntitySpawned(BradleyAPC entity) => HandleEntity(entity);
private void OnEntitySpawned(CargoPlane entity) => HandleEntity(entity);
private void OnEntitySpawned(CargoShip entity) => HandleEntity(entity);
private void OnEntitySpawned(CH47HelicopterAIController entity) => HandleEntity(entity);
private void OnEntitySpawned(EggHuntEvent entity) => HandleEntity(entity);
private void OnEntitySpawned(HackableLockedCrate entity) => HandleEntity(entity);
private void OnEntitySpawned(SantaSleigh entity) => HandleEntity(entity);
private void OnEntitySpawned(SupplyDrop entity) => HandleEntity(entity);
private void OnEntitySpawned(XMasRefill entity) => HandleEntity(entity);
private void OnEntityDeath(BasePlayer player, HitInfo info)
{
if (!player.IsValid() || info == null)
{
return;
}
if (_configData.GlobalSettings.HideNPC && (player.IsNpc || !player.userID.IsSteamId()))
{
return;
}
LogToConsole($"{player.displayName} died.");
DiscordSendMessage(Lang(LangKeys.Event.Death, null, ReplaceChars(player.displayName)), _configData.PlayerDeathSettings.WebhookURL);
}
private void OnEntityKill(EggHuntEvent entity)
{
if (!entity.IsValid())
{
return;
}
List<EggHuntEvent.EggHunter> winners = entity.GetTopHunters();
string winner;
if (winners.Count > 0)
{
winner = ReplaceChars(winners[0].displayName);
}
else
{
winner = "No winner";
}
bool isHalloween = entity is HalloweenHunt;
if (isHalloween)
{
if (_configData.HalloweenSettings.Enabled)
{
LogToConsole("Halloween Hunt Event has ended. The winner is " + winner);
DiscordSendMessage(Lang(LangKeys.Event.HalloweenWinner, null, winner), _configData.HalloweenSettings.WebhookURL);
}
}
else
{
if (_configData.EasterSettings.Enabled)
{
LogToConsole("Egg Hunt Event has ended. The winner is " + winner);
DiscordSendMessage(Lang(LangKeys.Event.EasterWinner, null, winner), _configData.EasterSettings.WebhookURL);
}
}
}
private void OnEntityKill(CargoShip cargoShip)
{
if (cargoShip.IsValid())
{
_cargoShips.Remove((uint)cargoShip.net.ID.Value);
}
}
private void OnExplosiveThrown(BasePlayer player, SupplySignal entity) => HandleSupplySignal(player, entity);
private void OnExplosiveDropped(BasePlayer player, SupplySignal entity) => HandleSupplySignal(player, entity);
private void OnGodmodeToggled(string playerID, bool enabled)
{
IPlayer player = covalence.Players.FindPlayerById(playerID);
if (player == null)
{
return;
}
if (enabled)
{
LogToConsole($"Godmode disabled for {player.Id} {player.Name}");
DiscordSendMessage(Lang(LangKeys.Plugin.GodmodeOn, null, ReplaceChars(player.Name)), _configData.GodmodeSettings.WebhookURL);
return;
}
LogToConsole($"Godmode enabled for {player.Id} {player.Name}");
DiscordSendMessage(Lang(LangKeys.Plugin.GodmodeOff, null, ReplaceChars(player.Name)), _configData.GodmodeSettings.WebhookURL);
}
private void OnPlayerConnected(BasePlayer player)
{
if (_configData.PlayerConnectedSettings.Enabled)
{
LogToConsole($"Player {player.displayName} connected.");
if (!_configData.GlobalSettings.HideAdmin || !player.IsAdmin)
{
StringBuilder sb = new StringBuilder();
sb.Append(Lang(LangKeys.Event.PlayerConnected, null, ReplaceChars(player.displayName)));
if (player.net.connection.ipaddress.StartsWith("127.")
|| player.net.connection.ipaddress.StartsWith("10.")
|| player.net.connection.ipaddress.StartsWith("172.16.")
|| player.net.connection.ipaddress.StartsWith("192.168."))
{
sb.Append(" :signal_strength:");
DiscordSendMessage(sb.ToString(), _configData.PlayerConnectedSettings.WebhookURL);
}
else
{
webrequest.Enqueue($"http://ip-api.com/json/{player.net.connection.ipaddress.Split(':')[0]}", null, (code, response) => {
if (code == 200 && response != null)
{
sb.Append(" :flag_");
sb.Append(JsonConvert.DeserializeObject<Response>(response).CountryCode.ToLower());
sb.Append(":");
}
DiscordSendMessage(sb.ToString(), _configData.PlayerConnectedSettings.WebhookURL);
}, this, RequestMethod.GET);
}
}
}
if (_configData.PlayerConnectedInfoSettings.Enabled)
{
DiscordSendMessage(Lang(LangKeys.Event.PlayerConnectedInfo, null, ReplaceChars(player.displayName), player.UserIDString, player.net.connection.ipaddress.Split(':')[0]), _configData.PlayerConnectedInfoSettings.WebhookURL);
}
}
private void OnPlayerDisconnected(BasePlayer player, string reason)
{
if (!player.IsValid())
{
return;
}
LogToConsole($"Player {player.displayName} disconnected ({reason}).");
if (!_configData.GlobalSettings.HideAdmin || !player.IsAdmin)
{
DiscordSendMessage(Lang(LangKeys.Event.PlayerDisconnected, null, ReplaceChars(player.displayName), ReplaceChars(reason)), _configData.PlayerDisconnectedSettings.WebhookURL);
}
}
private void OnPlayerChat(BasePlayer player, string message, ConVar.Chat.ChatChannel channel)
{
if (!player.IsValid() || string.IsNullOrWhiteSpace(message))
{
return;
}
if (IsPluginLoaded(BetterChatMute))
{
_resultCall = BetterChatMute.Call("API_IsMuted", player.IPlayer);
if (_resultCall is bool && (bool)_resultCall)
{
return;
}
}
if (_configData.GlobalSettings.UseAntiSpam && IsPluginLoaded(AntiSpam))
{
_resultCall = AntiSpam.Call("GetSpamFreeText", message);
message = (_resultCall as string);
if (string.IsNullOrWhiteSpace(message))
{
return;
}
}
if (_configData.GlobalSettings.UseUFilter && IsPluginLoaded(UFilter))
{
_sb.Clear();
_sb.Append(message);
_resultCall = UFilter.Call("Profanities", message);
if (_resultCall is string[])
{
_profanities = _resultCall as string[];
}
foreach (string profanity in _profanities)
{
_sb.Replace(profanity, new string('*', profanity.Length));
}
message = _sb.ToString();
if (string.IsNullOrWhiteSpace(message))
{
return;
}
}
message = ReplaceChars(message);
switch (channel)
{
case ConVar.Chat.ChatChannel.Global:
case ConVar.Chat.ChatChannel.Local:
if (_configData.ChatSettings.Enabled)
{
DiscordSendMessage(Lang(LangKeys.Event.Chat, null, ReplaceChars(player.displayName), message), _configData.ChatSettings.WebhookURL);
}
break;
case ConVar.Chat.ChatChannel.Team:
if (_configData.ChatTeamSettings.Enabled)
{
DiscordSendMessage(Lang(LangKeys.Event.ChatTeam, null, ReplaceChars(player.displayName), message), _configData.ChatTeamSettings.WebhookURL);
}
break;
}
}
private void OnPlayerTeleported(BasePlayer player, Vector3 oldPosition, Vector3 newPosition)
{
LogToConsole($"NTeleportation {player.UserIDString} {player.displayName} from {oldPosition} to {newPosition}");
DiscordSendMessage(Lang(LangKeys.Plugin.NTeleportation, null, ReplaceChars(player.displayName), GetGridPosition(oldPosition), oldPosition, GetGridPosition(newPosition), newPosition), _configData.NTeleportationSettings.WebhookURL);
}
private void OnPMProcessed(IPlayer sender, IPlayer target, string message)
{
LogToConsole($"PM from `{sender.Name}` to `{target.Name}`: {message}");
DiscordSendMessage(Lang(LangKeys.Plugin.PrivateMessage, null, ReplaceChars(sender.Name), ReplaceChars(target.Name), ReplaceChars(message)), _configData.PrivateMessagesSettings.WebhookURL);
}
private void OnPlayerRespawned(BasePlayer player)
{
if (string.IsNullOrWhiteSpace(player?.displayName))
{
return;
}
LogToConsole($"{player.displayName} has been spawned at {GetGridPosition(player.transform.position)}");
DiscordSendMessage(Lang(LangKeys.Event.PlayerRespawned, null, ReplaceChars(player.displayName), GetGridPosition(player.transform.position)), _configData.PlayerRespawnedSettings.WebhookURL);
}
private void OnRadarActivated(BasePlayer player)
{
LogToConsole($"Admin Radar enabled by {player.UserIDString} {player.displayName}");
DiscordSendMessage(Lang(LangKeys.Plugin.AdminRadarOn, null, ReplaceChars(player.displayName)), _configData.AdminRadarSettings.WebhookURL);
}
private void OnRadarDeactivated(BasePlayer player)
{
LogToConsole($"Admin Radar disabled by {player.UserIDString} {player.displayName}");
DiscordSendMessage(Lang(LangKeys.Plugin.AdminRadarOff, null, ReplaceChars(player.displayName)), _configData.AdminRadarSettings.WebhookURL);
}
private void OnRaidableBaseStarted(Vector3 raidPos, int difficulty)
{
HandleRaidableBase(raidPos, difficulty, LangKeys.Plugin.RaidableBaseStarted);
}
private void OnRaidableBaseEnded(Vector3 raidPos, int difficulty)
{
HandleRaidableBase(raidPos, difficulty, LangKeys.Plugin.RaidableBaseEnded);
}
private void OnRaidableBaseCompleted(Vector3 raidPos, int difficulty, bool allowPVP, string id, float spawnTime, float despawnTime, float loadTime, ulong ownerId, BasePlayer owner, List<BasePlayer> raiders)
{
HandleRaidableBase(raidPos, difficulty, LangKeys.Plugin.RaidableBaseCompleted, owner, raiders);
}
private void OnRconConnection(IPAddress ip)
{
LogToConsole($"RCON connection is opened from {ip}");
DiscordSendMessage(Lang(LangKeys.Event.RconConnection, null, ip.ToString()), _configData.RconConnectionSettings.WebhookURL);
}
private void OnRconCommand(IPAddress ip, string command, string[] args)
{
foreach (string rconCommand in _configData.GlobalSettings.RCONCommandBlacklist)
{
if (command.ToLower().Equals(rconCommand.ToLower()))
{
return;
}
}
for (int i = 0; i < args.Length; i++)
{
command += $" {args[i]}";
}
LogToConsole($"RCON command {command} is run from {ip}");
DiscordSendMessage(Lang(LangKeys.Event.RconCommand, null, command, ip), _configData.RconCommandSettings.WebhookURL);
}
private void OnSupplyDropLanded(SupplyDrop entity)
{
if (!entity.IsValid() || _listSupplyDrops.Contains(((uint)entity.net.ID.Value)))
{
return;
}
LogToConsole($"SupplyDrop landed at {GetGridPosition(entity.transform.position)}");
DiscordSendMessage(Lang(LangKeys.Event.SupplyDropLanded, null, GetGridPosition(entity.transform.position)), _configData.SupplyDropSettings.WebhookURL);
_entityID = (uint)entity.net.ID.Value;
_listSupplyDrops.Add(_entityID);
timer.Once(60f, () => _listSupplyDrops.Remove(_entityID));
}
private void OnUserBanned(string name, string id, string ipAddress, string reason)
{
LogToConsole($"Player {name} ({id}) at {ipAddress} was banned: {reason}");
DiscordSendMessage(Lang(LangKeys.Event.UserBanned, null, ReplaceChars(name), id, ipAddress, ReplaceChars(reason)), _configData.UserBannedSettings.WebhookURL);
}
private void OnUserKicked(IPlayer player, string reason)
{
LogToConsole($"Player {player.Name} ({player.Id}) was kicked ({reason})");
DiscordSendMessage(Lang(LangKeys.Event.UserKicked, null, ReplaceChars(player.Name), player.Id, ReplaceChars(reason)), _configData.UserKickedSettings.WebhookURL);
}
private void OnUserUnbanned(string name, string id, string ipAddress)
{
LogToConsole($"Player {name} ({id}) at {ipAddress} was unbanned");
DiscordSendMessage(Lang(LangKeys.Event.UserUnbanned, null, ReplaceChars(name), id, ipAddress), _configData.UserBannedSettings.WebhookURL);
}
private void OnUserNameUpdated(string id, string oldName, string newName)
{
if (oldName.Equals(newName) || oldName.Equals("Unnamed"))
{
return;
}
LogToConsole($"Player name changed from {oldName} to {newName} for ID {id}");
DiscordSendMessage(Lang(LangKeys.Event.UserNameUpdated, null, ReplaceChars(oldName), ReplaceChars(newName), id), _configData.UserNameUpdateSettings.WebhookURL);
}
private void OnServerMessage(string message, string name, string color, ulong id)
{
LogToConsole($"ServerMessage: {message}");
DiscordSendMessage(Lang(LangKeys.Event.ServerMessage, nu
// ... [Code preview truncated due to length. Full source in attached file] ...