Иконка ресурса

FREE ClanRenameLogs : 1.0.2 1.0.2

Нет прав для скачивания
C#:
// Requires: Clans Reborn
// https://chaoscode.io/resources/clans-reborn.14/

using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;

namespace Oxide.Plugins
{
    [Info("Clan Rename Logs", "SeesAll", "1.0.2")]
    [Description("Logs and audits clan rename actions for Clans Reborn, with reasons, per-wipe cleanup, and optional Discord logging.")]
    public class ClanRenameLogs : RustPlugin
    {
        private const string PermUse = "clanrenamelogs.use";
        private const string DataFileName = "ClanRenameLogs";

        [PluginReference]
        private Plugin Clans; 

        private List<RenameEntry> _log = new List<RenameEntry>();
        private Configuration _config;

        #region Config

        private class DiscordSettings
        {
            public bool Enabled = false;
            public string WebhookUrl = "";
            public string Username = "ClanRenamer";
            public string AvatarUrl = "";
            public bool MentionHere = false;
            public string MentionRoleId = "";
        }

        private class Configuration
        {
            public bool WipeLogsOnServerWipe = true;
            public DiscordSettings Discord = new DiscordSettings();
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            try
            {
                _config = Config.ReadObject<Configuration>();
                if (_config == null)
                {
                    throw new Exception("Config is null");
                }
            }
            catch
            {
                PrintWarning("Configuration file is invalid or missing, creating a new one with default values.");
                LoadDefaultConfig();
            }
        }

        protected override void LoadDefaultConfig()
        {
            _config = new Configuration();
            SaveConfig();
        }

        protected override void SaveConfig()
        {
            Config.WriteObject(_config, true);
        }

        #endregion

        #region Lang

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                ["Error.NoPermission"] = "You do not have permission to use this command.",
                ["Error.NoClansPlugin"] = "Clans/ClansReborn plugin not found. Cannot rename clans.",
                ["Usage.Chat"] = "Usage: /renameclan OLD_TAG NEW_TAG REASON",
                ["Usage.ChatExample"] = "Example: /renameclan BAD GOOD Offensive name",
                ["Usage.Console"] = "Usage: renameclan OLD_TAG NEW_TAG REASON",
                ["Error.EmptyTags"] = "Old and new clan tags cannot be empty.",
                ["Error.ClanNotFound"] = "No clan with tag '{0}' was found. Rename aborted.",
                ["Warn.CantVerifyClan"] = "Warning: Could not verify if the clan exists via Clans API.",
                ["Warn.NewTagExists"] = "Warning: A clan with tag '{0}' already exists.",
                ["Warn.RenameFailed"] = "Rename may have failed or been rejected by Clans Reborn. Please verify manually.",
                ["Info.LoggedRename"] = "Clan tag '{0}' has been renamed to '{1}' with reason: {2}.",
                ["Info.LoggedRenameConsole"] = "Clan tag '{0}' has been renamed to '{1}' with reason: {2}.",
            }, this);
        }

        private string Msg(string key, string userId = null)
        {
            return lang.GetMessage(key, this, userId);
        }

        #endregion

        #region Data Model

        private class RenameEntry
        {
            public string TimeUtc { get; set; }
            public string ExecutorName { get; set; }
            public string ExecutorId { get; set; }
            public string OldTag { get; set; }
            public string NewTag { get; set; }
            public string Reason { get; set; }
        }

        #endregion

        #region Hooks

        private void Init()
        {
            permission.RegisterPermission(PermUse, this);
            LoadConfig();
            LoadData();
        }

        private void OnServerSave()
        {
            SaveData();
        }

        private void Unload()
        {
            SaveData();
        }

        private void OnNewSave(string filename)
        {
            if (_config == null)
            {
                LoadConfig();
            }

            if (_config.WipeLogsOnServerWipe)
            {
                _log.Clear();
                Interface.Oxide.DataFileSystem.WriteObject(DataFileName, _log);
                Puts($"[ClanRenameLogs] Detected new save '{filename}'. Log cleared because WipeLogsOnServerWipe = true.");
            }
            else
            {
                Puts("[ClanRenameLogs] Detected new save, but WipeLogsOnServerWipe = false. Log has been preserved.");
            }
        }

        #endregion

        #region Commands

        [ChatCommand("renameclan")]
        private void CmdRenameClan(BasePlayer player, string command, string[] args)
        {
            if (player == null)
                return;

            if (!HasPermission(player))
            {
                SendMessage(player, Msg("Error.NoPermission", player.UserIDString));
                return;
            }

            if (Clans == null)
            {
                SendMessage(player, Msg("Error.NoClansPlugin", player.UserIDString));
                return;
            }

            if (args.Length < 3)
            {
                SendMessage(player, Msg("Usage.Chat", player.UserIDString));
                SendMessage(player, Msg("Usage.ChatExample", player.UserIDString));
                return;
            }

            string oldTag = args[0];
            string newTag = args[1];
            string reason = string.Join(" ", args.Skip(2));

            if (string.IsNullOrEmpty(oldTag) || string.IsNullOrEmpty(newTag))
            {
                SendMessage(player, Msg("Error.EmptyTags", player.UserIDString));
                return;
            }

            bool apiSupported = TryCheckClanExists(oldTag, out bool oldExists);
            if (apiSupported)
            {
                if (!oldExists)
                {
                    SendMessage(player, string.Format(Msg("Error.ClanNotFound", player.UserIDString), oldTag));
                    return;
                }

                if (TryCheckClanExists(newTag, out bool newExists) && newExists)
                {
                    SendMessage(player, string.Format(Msg("Warn.NewTagExists", player.UserIDString), newTag));
                }
            }
            else
            {
                SendMessage(player, Msg("Warn.CantVerifyClan", player.UserIDString));
            }

            string cmd = $"clans rename {oldTag} {newTag}";
            rust.RunServerCommand(cmd);

            bool verified = false;
            if (apiSupported)
            {
                bool oldStillExists;
                bool newExists;
                bool oldCheck = TryCheckClanExists(oldTag, out oldStillExists);
                bool newCheck = TryCheckClanExists(newTag, out newExists);
                if (oldCheck && newCheck)
                {
                    verified = !oldStillExists && newExists;
                }
            }

            if (!verified && apiSupported)
            {
                SendMessage(player, Msg("Warn.RenameFailed", player.UserIDString));
                Puts($"[ClanRenameLogs] Verification failed for rename '{{oldTag}}' -> '{{newTag}}' initiated by {player.displayName} ({player.UserIDString}).");
                return;
            }

            LogRename(player.displayName, player.UserIDString, oldTag, newTag, reason);
            SendDiscordLog(player.displayName, player.UserIDString, oldTag, newTag, reason);

            SendMessage(player, string.Format(Msg("Info.LoggedRename", player.UserIDString), oldTag, newTag, reason));
        }

        [ConsoleCommand("renameclan")]
        private void CmdRenameClanConsole(ConsoleSystem.Arg arg)
        {
            if (!arg.IsAdmin)
            {
                arg.ReplyWith(Msg("Error.NoPermission"));
                return;
            }

            if (Clans == null)
            {
                arg.ReplyWith(Msg("Error.NoClansPlugin"));
                return;
            }

            if (arg.Args == null || arg.Args.Length < 3)
            {
                arg.ReplyWith(Msg("Usage.Console"));
                return;
            }

            string oldTag = arg.Args[0].ToString().Trim();
            string newTag = arg.Args[1].ToString().Trim();
            string reason = string.Join(" ", arg.Args.Skip(2).Select(value => value.ToString()));

            string executorName = "SERVER CONSOLE";
            string executorId = "0";

            bool apiSupported = TryCheckClanExists(oldTag, out bool oldExists);
            if (apiSupported)
            {
                if (!oldExists)
                {
                    arg.ReplyWith(string.Format(Msg("Error.ClanNotFound"), oldTag));
                    return;
                }

                if (TryCheckClanExists(newTag, out bool newExists) && newExists)
                {
                    arg.ReplyWith(string.Format(Msg("Warn.NewTagExists"), newTag));
                }
            }
            else
            {
                arg.ReplyWith(Msg("Warn.CantVerifyClan"));
            }

            string cmd = $"clans rename {oldTag} {newTag}";
            rust.RunServerCommand(cmd);

            bool verified = false;
            if (apiSupported)
            {
                bool oldStillExists;
                bool newExists;
                bool oldCheck = TryCheckClanExists(oldTag, out oldStillExists);
                bool newCheck = TryCheckClanExists(newTag, out newExists);
                if (oldCheck && newCheck)
                {
                    verified = !oldStillExists && newExists;
                }
            }

            if (!verified && apiSupported)
            {
                arg.ReplyWith(Msg("Warn.RenameFailed"));
                Puts($"[ClanRenameLogs] Verification failed for rename '{{oldTag}}' -> '{{newTag}}' initiated by {executorName} ({executorId}).");
                return;
            }

            LogRename(executorName, executorId, oldTag, newTag, reason);
            SendDiscordLog(executorName, executorId, oldTag, newTag, reason);

            arg.ReplyWith(string.Format(Msg("Info.LoggedRenameConsole"), oldTag, newTag, reason));
        }

        #endregion

        #region Helpers - Clan Checks

        private bool TryCheckClanExists(string tag, out bool exists)
        {
            exists = false;

            if (Clans == null || string.IsNullOrEmpty(tag))
                return false;

            try
            {
                var result = Clans.Call("GetClan", tag);
                exists = result != null;
            }
            catch (Exception e)
            {
                PrintWarning($"[ClanRenameLogs] Failed to query Clans plugin for tag '{tag}': {e.Message}");
                return false;
            }

            return true;
        }

        #endregion

        #region Helpers - General

        private bool HasPermission(BasePlayer player)
        {
            return permission.UserHasPermission(player.UserIDString, PermUse);
        }

        private void SendMessage(BasePlayer player, string message)
        {
            player.ChatMessage($"<color=#ffa500>[ClanRenameLogs]</color> {message}");
        }

        private void LogRename(string executorName, string executorId, string oldTag, string newTag, string reason)
        {
            var entry = new RenameEntry
            {
                TimeUtc = DateTime.UtcNow.ToString("o"), // ISO 8601
                ExecutorName = executorName,
                ExecutorId = executorId,
                OldTag = oldTag,
                NewTag = newTag,
                Reason = reason
            };

            _log.Add(entry);
            SaveData();
        }

        private void LoadData()
        {
            try
            {
                _log = Interface.Oxide.DataFileSystem.ReadObject<List<RenameEntry>>(DataFileName) ?? new List<RenameEntry>();
            }
            catch
            {
                _log = new List<RenameEntry>();
            }
        }

        private void SaveData()
        {
            Interface.Oxide.DataFileSystem.WriteObject(DataFileName, _log);
        }

        #endregion

        #region Helpers - Discord

        private void SendDiscordLog(string executorName, string executorId, string oldTag, string newTag, string reason)
        {
            var d = _config?.Discord;
            if (d == null || !d.Enabled || string.IsNullOrEmpty(d.WebhookUrl))
                return;

            string mention = "";
            if (d.MentionHere)
            {
                mention = "@here ";
            }
            else if (!string.IsNullOrEmpty(d.MentionRoleId))
            {
                mention = $"<@&{d.MentionRoleId}> ";
            }

            var payload = new
            {
                content = string.IsNullOrEmpty(mention) ? null : mention,
                username = string.IsNullOrEmpty(d.Username) ? "ClanRenamer" : d.Username,
                avatar_url = string.IsNullOrEmpty(d.AvatarUrl) ? null : d.AvatarUrl,
                embeds = new[]
                {
                    new
                    {
                        title = "Clan Rename Logged",
                        description = $"`{oldTag}` → `{newTag}`",
                        color = 15158332, // light red/orange
                        fields = new[]
                        {
                            new { name = "Executor", value = $"{executorName} ({executorId})", inline = false },
                            new { name = "Reason", value = string.IsNullOrEmpty(reason) ? "No reason provided." : reason, inline = false },
                            new { name = "Time (UTC)", value = DateTime.UtcNow.ToString("u"), inline = false }
                        }
                    }
                }
            };

            string json;
            try
            {
                json = JsonConvert.SerializeObject(payload);
            }
            catch (Exception e)
            {
                PrintWarning($"[ClanRenameLogs] Failed to serialize Discord payload: {e.Message}");
                return;
            }

            webrequest.Enqueue(d.WebhookUrl, json, (code, response) =>
            {
                if (code != 204 && code != 200)
                {
                    PrintWarning($"[ClanRenameLogs] Discord webhook returned code {code}. Response: {response}");
                }
            }, this, Core.Libraries.RequestMethod.POST, new Dictionary<string, string>
            {
                ["Content-Type"] = "application/json"
            });
        }

        #endregion
    }
}

Автор
15FPS
Скачиваний
0
Просмотры
1
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок
Сверху