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

FREE ChatPlus : 1.4.0 1.4.0

Нет прав для скачивания
C#:
//#define RUST
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Oxide.Core;
using Oxide.Core.Configuration;
using Oxide.Core.Libraries;
using Oxide.Core.Plugins;
using System.Text.RegularExpressions;
using ConVar;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
namespace Oxide.Plugins {
    [Info("ChatPlus", "RustPlugin.ru - Developed by Vlad-00003", "1.4.0", ResourceId = 82)]
    public class ChatPlus : CovalencePlugin {
        /*  covalence.FormatText(msg);
         *  Formatter.ToPlaintext(msg);
         *  Original autor: Unknown
         *  Editor: Vlad-00003
         *  Editor info:
         *    E-mail: Vlad-00003@mail.ru
         *    Vk: vk.com/vlad_00003
         * v1.1.0
         *   Добавлены команды:
         *     chatplus.message {steamid/ник} привилегия
         *     chatplus.name {steamid/ник} привилегия
         *     chatplus.prefix {steamid/ник} привилегия
         *       Данные команды лишь УСТАНАВЛИВАЮТ префикс\цвета игроку.Для использования необходимо выдать игроку 
         *       привилегии.Без привилегий команды работать НЕ будут.*       Для использования из консоли игрока требуется привилегия на присваивание префикса и цветов (chatplus.assign)
         *   Добавлена возможноть выдавать мут\использовать команды присваивания цветов\префика игрокам, не находящимся на сервере.*   Добавлена комманда mutelist - выводит список текущик игроков, у которых заблокирован чат.*   При отключении чата игроку сохраняется не только время, а так же то, кто заблокировал игроку чат и причина,
         *   что полностью отражается как в чате и заблокированного, так и при команде mutelist
         *   Отныне при использовании команды mute причина и время опциональны - можно заблокировать человека навсегда, но с причиной.*   Примеры:
         *     "mute vlad" - блокировать игроку чат на всегда.Причина - Not specified
         *     "mute vlad 1d" - блокировать чат игроку на 1 день.Причина - Not specified
         *     "mute vlad Просто потому что я так решил." - блокировать чат игроку навсегда.Причина - "Просто потому что я так решил."
         *     "mute vlad 1d Это весомоя причина" - блокировать чат игроку на 1 день.Причина - "Это весомоя причина"
         *   Разделены привилегии на использование команд mute/unmute на две разные привилегии - chatplus.mute и chatplus.unmute соответственно.*   Небольшая чистка и оптимизация кода.* V1.1.1
         *   Стандартная причина мута (если не указана) выведена в файл конфигурации
         * v1.1.2
         *   Добавлен API - private void API_RegisterThirdPartyTitle(Plugin plugin, Func<IPlayer, string> titleGetter)
         * V1.1.3
         *   Удалена ненужная проверка
         * V1.2.0
         *   Плагин переведён на тип Covalence - Теперь он может работать не только в Rust-е.Требуется проверка на других играх.*     Так же теперь плагин поддерживает стандартизированное форматирование ([#HEXCOLOR][/#] [+SIZE][/+])
         *   Исправлена ошибка при удалении игрока из чёрного списка - теперь сообщение о том, что игрока удалили появляется в нужное время.*   Если игрок указал неверный параметр в команде /chat, то ему будет выведена справка.Раньше не выводилось ничего.*   Если у вас возникнут ошибки при обновлении до данной версии вы можете сделать следующие - очистить BlackList у каждого игрока 
         *     в файле данных.Или просто удалите ChatPlus_Players.json из папки oxide/data.*   Для полной совместимости с Clans Reborn вам нужно поправить функцию OnPluginLoaded в плагине Clans:
         *   void OnPluginLoaded(Plugin plugin)
         *   {
         *       if (plugin.Title != "Better Chat" || plugin.Title != "ChatPlus") return;
         *       if (enableClanTagging) Interface.CallHook("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(getFormattedClanTag));
         *   }
         * V1.2.1
         *   Добавлено лоигрование режимов администратора и модератора чата.* V1.2.2
         *   Исправлена ошибка во флаге, Rust заменено на RUST.Из-за этого даже в игре Rust использовались мультиобразные вызовы,
         *   что приводило к отсутствию звуков личных сообщений и отсутствию иконок игроков в чате
         *   Так же исправлена возможность отправлять ЛС самому себе если отображаемое имя на сервере игры RUST отличается от 
         *   фактического имени в базе
         *   Добавлен ResourceId
         * V1.3.0
         *   Добавлена возможность использовать PM через консоль и отвечать через r.*     Теперь вы можете отправлять личные сообщения игрокам из консоли, а они могут вам отвечать!
         *   Исправлена ошибка в языковых файлах.Команд присваивания префикса\цветов имён\сообщений в чате
         *   Полностью переписаны языковые файл (Изменён принцип форматирования на стандартизированное представление):
         *     <color=#HEX></color> заменено на [#HEX][/#] и <size=N></size> заменено на [+N][/+]
         *   Удалите ваши старые языковые файлы и перезапустите плагин.*   Данное действие ОБЯЗАТЕЛЬНО!
         *   Добавлены новые строки файла конфигурации(пересоздавать ничего не нужно - 
         *     они автоматически будут добавлены в конфиг при первом запуске обновлённой версии):
         *      M.Имя консоли при отправке личных сообщений и отключении чата из консоли
         *      N.Формат отправки сообщений из консоли командой say
         *  Имя консоли это то имя, которые будет выводиться при блокировке чата из консоли сервера.*  Так же теперь изменению подверглась команда global.say, которую, помимо консоли, могут вызывать администраторы из консоли игры:
         *    Теперь вы можете настроить формат вывода сообщений в чат при использовании данной команды!
         *    {0} - Это имя консоли, из пераметра выше.{1} - само сообщение.* V1.3.1
         *   Добавлена возможность отображение аватарок игрока при отправке личного сообщения(ТОЛЬКО Rust!)
         * V1.3.2
         *   Переделана система логгирования, теперь так же ведётся лог личных сообщений(что крайне мешает когда ты переписываешься через консоль
         *     я подумаю как это сделать красивее).*   Оптимизация функций, отвечающих за отображение иконок в личных переписках.*   Проверка на консоль сервера вынесена отдельно
         * V1.3.3
         *   Теперь в списках имён\префиксов\цветов сообщений отображается default, дабы игрок мог вернуть цвет к стандарту без команды /chat reset
         * v1.3.4
         *   Исправление v1.3.3 - теперь default видят только те, у кого на данный момент выбран не стандартный цвет\префикс
         * v1.3.5
         *   Добавлено верное форматирование в функцию BroadcastChat - вывод сообщений в чат о мутах.Теперь она так же поддерживает стандартизированное форматирование.* v1.3.6
         *   Теперь верно получается языковой файл справки о команде /chat
		 * v1.3.7
		 *   Попытка исправить NRE в SendChat при вызове SendConsoleCommand
         * v1.3.71
         *   Убрана устаревшая функция Reply, принимающая как аргумент BasePlayer, упрощён доступ к данным пользователя в команде /chat
         * v1.3.8
         *   Добавлена возможность скрывать имя администратора, который заблокировал доступ к чату.* v1.3.9
         *   Добавлен API IsPlayerMuted(object ID) - вернёт true если игроку недоступен чат
         *   Добавлен хук OnChatPlusMessage(Dictionary<string,object> dict), доступные параметры:
         *     ["Player"] - Iplayer - игрок, написавший в чат
         *     ["Message"] - string - его сообщение в чат
         *     ["CensoredMessage"] - string - версия его сообщения с цензурой
         *     ["Prefixes"] - string - все префиксы игрока, разделённые одним пробелом.* v1.3.10
         *   Исправил ошибку в хуке
         * v1.3.11
         *   Добавлена новая строка в языковой файл - сообщение о том, что игрока нет в чёрном списке при использовании /chat ignore remove <name>
         *   Исправлена ошибка, по которой сообщение в чат могло отправляться игроку, которого нет на сервере, что приводило к сбоям в работе плагина.*   Проверка IsServerConsole по ID игрока заменена на поле IsServer класса IPlayer.* v1.4.0
         *   Убрана возможность форматирования текста игроками(перед форматированием сообщение очищается от тэегов)
         *   Поправлена цензура чата.Теперь если исключение находиться на нулевой позиции оно так же будет учтено.*   Исправлена ошибка из-за которой время блокировки чата не сохранялось при перезагрузках.*      Всем администраторам - пересмотрите список тех, кому блокировали чат.Возможно часть из этих блокировок уже давно должна была закончится =)
         */
#region Global vars
        private ChatConfig config;
        private static ChatPlus m_Instance;
        private static Dictionary<string, MuteData> mutes = new Dictionary<string, MuteData>();
        private Dictionary<string, PlayerData> PlayersData = new Dictionary<string, PlayerData>();
        private PlayerData defaultData = new PlayerData();
        private bool GlobalMute = false;
        private bool HasExpired;
        private IPlayer ConsoleIPly;
        DynamicConfigFile mutes_File = Interface.Oxide.DataFileSystem.GetFile("ChatPlus_Mutes");
        DynamicConfigFile players_File = Interface.Oxide.DataFileSystem.GetFile("ChatPlus_Players");
        public static Dictionary<Plugin, Func<IPlayer, string>> ThirdPartyTitles = new Dictionary<Plugin, Func<IPlayer, string>>();
#endregion
#region Initialization and quiting
        void OnServerInitialized() {
            m_Instance = this;
            LoadMessages();
            LoadConfig();
            LoadData();
            config.RegisterPerms();
            timer.Repeat(10, 0, () => {
                List<string> expired = mutes.Where(m => m.Value.Expired).Select(m => m.Key).ToList();
                foreach (string userID in expired) {
                    IPlayer player = players.FindPlayerById(userID.ToString());
                    if (player == null) continue;
                    mutes.Remove(userID);
                    BroadcastChat("MUTE.EXPIRED", player.Name);
                    Log(LogType.Mute, string.Format(GetMsg("MUTE.EXPIRED"), player.Name));
                    if (!HasExpired) HasExpired = true;
                }
                if (HasExpired) {
                    SaveMutes();
                    HasExpired = false;
                }
            }
            );
        }
        void Unload() {
            OnServerSave();
        }
        void OnServerSave() {
            SaveMutes();
            players_File.WriteObject(PlayersData.Where(p => !p.Value.Equals(defaultData)).ToDictionary(p => p.Key, p => p.Value));
        }
        private void SaveMutes() {
            mutes_File.WriteObject(mutes);
        }
        void LoadData() {
            mutes = mutes_File.ReadObject<Dictionary<string, MuteData>>();
            PlayersData = players_File.ReadObject<Dictionary<string, PlayerData>>();
        }
#endregion
#region Chat handling
        object OnPlayerChat(BasePlayer player, string message, Chat.ChatChannel channel) {
            IPlayer sender = player.IPlayer;
            if (GlobalMute) {
                if (!CanMuteAll(sender)) {
                    Reply(sender, "MUTE.ALL.DISABLED");
                    return false;
                }
            }
            Puts($"[{channel}] {player.displayName}[{player.userID}]: {message}");
            var pData = GetPlayerData(sender);
            if (pData.IsAdmin == true) {
                Log(LogType.Chat, $"[ADMIN MODE] {sender.Name}({sender.Id}): {message}");
                bool outer;
                var cens = CensorBadWords(message, out outer);
                cens = string.Format(config.adminPrivilages.AdminFormat, cens);
                message = string.Format(config.adminPrivilages.AdminFormat, message);
                SendChat(player, "", channel, message, cens);
                return false;
            }
            if (pData.IsModer == true) {
                Log(LogType.Chat, $"[MODERATOR MODE] {sender.Name}({sender.Id}): {message}");
                bool outer;
                var cens = CensorBadWords(message, out outer);
                cens = string.Format(config.adminPrivilages.ModerFormat, cens);
                message = string.Format(config.adminPrivilages.ModerFormat, message);
                SendChat(player, "", channel, message, cens);
                return false;
            }
            if (SpamCheck(sender, message) != null) return true;
            if (MuteCheck(sender) != null) return true;
            if (config.CapsBlock) {
                message = RemoveCaps(message);
            }
            message = RemoveTags(message);
            bool mute;
            var censorMessage = CensorBadWords(message, out mute);
            if (config.BadWordsBlock & mute) {
                Mute(sender.Id, sender.Name, new TimeSpan(0, 0, config.MuteBadWordsDefault), config.MuteReasonAutoMute, "ChatPlus");
            }
            var prefix = config.Get(config.prefixes, pData.Prefix).Format;
            var nameColor = config.Get(config.names, pData.NameColor).Format;
            var messageColor = config.Get(config.messages, pData.MessageColor).Format;
            var name = string.Format(nameColor, sender.Name);
            message = string.Format(messageColor, message);
            censorMessage = string.Format(messageColor, censorMessage);
            foreach (var thirdPartyTitle in ThirdPartyTitles) {
                try {
                    string title = thirdPartyTitle.Value(sender);
                    if (!string.IsNullOrEmpty(title)) {
                        prefix = title + " " + prefix;
                    }
                }
                catch (Exception ex) {
                    PrintError($"Error when trying to get third-party title from plugin '{thirdPartyTitle.Key.Title}'{Environment.NewLine}{ex}");
                }
            }
            Dictionary<string, object> hookDictionary = new Dictionary<string, object>() {
                ["Player"]
                = sender, ["Message"] = message, ["CensoredMessage"] = censorMessage, ["Prefixes"] = prefix
            }
            ;
            foreach (var plugin in plugins.GetAll()) {
                object result = plugin.CallHook("OnChatPlusMessage", hookDictionary);
                if (result is Dictionary<string, object>) {
                    try {
                        var dict = (Dictionary<string, object>)result;
                        sender = dict["Player"] as IPlayer;
                        message = dict["Message"] as string;
                        censorMessage = dict["CensoredMessage"] as string;
                        prefix = dict["Prefixes"] as string;
                    }
                    catch (Exception ex) {
                        PrintWarning($"Plugin '{plugin.Title}({plugin.Version})' failed to modify the ChatPlus message data.Error:\n{ex.Message}");
                    }
                }
                else if(result != null) return null;
            }
            if (prefix.Length > 0) name = $"{prefix} {name}";
            SendChat(player, name, channel, message, censorMessage, sender.Id);
            Log(LogType.Chat, $"{name}[{sender.Id}]: {message}");
            return false;
        }
        private string RemoveTags(string message) {
            List<string> forbiddenTags = new List<string> {
                "</color>", "</size>", "<b>", "</b>", "<i>", "</i>"
            }
            ;
            message = Regex.Replace(message, "(<color=.+?>)", string.Empty, RegexOptions.IgnoreCase);
            message = Regex.Replace(message, "(<size=.+?>)", string.Empty, RegexOptions.IgnoreCase);
            foreach (string tag in forbiddenTags) message = Regex.Replace(message, tag, string.Empty, RegexOptions.IgnoreCase);
            return Formatter.ToPlaintext(message);
        }
        string RemoveCaps(string message) {
            var ss = message.Split(' ');
            for (int j = 0; j < ss.Length; j++) for (int i = 1; i < ss[j].Length; i++) {
                var sym = ss[j][i];
                if (char.IsLower(sym)) continue;
                ss[j] = ss[j].Remove(i, 1);
                ss[j] = ss[j].Insert(i, char.ToLower(sym).ToString());
            }
            return string.Join(" ", ss);
        }
        bool? MuteCheck(IPlayer sender) {
            if (MuteData.IsMuted(sender.Id)) {
                MuteData md = mutes[sender.Id];
                Reply(sender, "YOU.MUTED", md.Initiator, md.Reason, md.Remain);
                return true;
            }
            return null;
        }
        bool? SpamCheck(IPlayer sender, string message) {
            if (message.Length > 500) {
                sender.Kick(GetMsg("CHAT.TOOMUCH", sender));
                return false;
            }
            if (message.Length > 100) {
                Reply(sender, "CHAT.SPAM");
                return false;
            }
            return null;
        }
        public string CensorBadWords(string input, out bool found) {
            found = false;
            string temp = input.ToLower();
            foreach (var swear in config.badWords) {
                var firstIndex = temp.IndexOf(swear.Key);
                if (firstIndex >= 0 && swear.Value.All(exception => temp.IndexOf(exception) <= 0)) while (firstIndex < input.Length && input[firstIndex] != ' ') {
                    input = input.Remove(firstIndex, 1);
                    input = input.Insert(firstIndex, "*");
                    firstIndex++;
                    found = true;
                }
            }
            return input;
        }
#endregion
#region Logging
        enum LogType {
            Chat, Mute, PM, ServerConsole
        }
        private void Log(LogType type, string msg) {
            switch (type) {
                case LogType.Chat : Interface.Oxide.RootLogger.Write(Oxide.Core.Logging.LogType.Info, $"[CHAT] {Formatter.ToPlaintext(msg)}");
                return;
                case LogType.Mute : Interface.Oxide.RootLogger.Write(Oxide.Core.Logging.LogType.Info, $"[MUTE] {Formatter.ToPlaintext(msg)}");
                return;
                case LogType.PM : Interface.Oxide.RootLogger.Write(Oxide.Core.Logging.LogType.Info, $"[PM] {Formatter.ToPlaintext(msg)}");
                return;
                case LogType.ServerConsole : Interface.Oxide.RootLogger.Write(Oxide.Core.Logging.LogType.Info, $"[ServerConsole] {Formatter.ToPlaintext(msg)}");
                return;
            }
        }
#endregion
#region Broadcasting
        void SendChat(BasePlayer players, string name, Chat.ChatChannel channel, string message, string censorMessage = "", string userId = "0") {
            name = covalence.FormatText(name);
            message = covalence.FormatText(message);
            censorMessage = covalence.FormatText(censorMessage);
            if (string.IsNullOrEmpty(censorMessage)) censorMessage = message;
            foreach (var player in BasePlayer.activePlayerList) {
                if (channel == Chat.ChatChannel.Global) {
                    string msg = GetPlayerData(player).Censor ? censorMessage : message;
                    player?.SendConsoleCommand("chat.add", channel, userId, string.IsNullOrEmpty(name) ? $"{msg}" : $"{name}: {msg}");
                }
            }
            if (channel == Chat.ChatChannel.Team) {
                RelationshipManager.PlayerTeam team = BasePlayer.Find(userId).Team;
                if (team == null || team.members.Count == 0) {
                    return;
                }
                foreach (ulong userId2 in team.members) {
                    string msg = GetPlayerData(players).Censor ? censorMessage : message;
                    BasePlayer basePlayer = RelationshipManager.FindByID(userId2);
                    basePlayer.SendConsoleCommand("chat.add", (int) channel, players.userID, string.IsNullOrEmpty(name) ? $"{msg}" : $"{name}: {msg}");
                }
            }
        }
        void BroadcastChat(string langKey, params object[] args) {
            foreach (var player in BasePlayer.activePlayerList) {
                player.ChatMessage(covalence.FormatText(string.Format(GetMsg(langKey, player), args)));
            }
        }
        private void Reply(IPlayer player, string langkey, params object[] args) {
            string message = string.Format(GetMsg(langkey, player.Id), args);
            message = player.IsServer ? Formatter.ToPlaintext(message) : covalence.FormatText(message);
            if(player.IsServer | player.IsConnected) player.Reply(message);
        }
#endregion
#region Sub functions
        void Mute(string userID, string name, TimeSpan? time = null, string reason = null, string sender = null) {
            if (string.IsNullOrEmpty(sender)) sender = "Not specified";
            if (string.IsNullOrEmpty(reason)) reason = config.MuteReason;
            string log;
            if (!time.HasValue) {
                mutes[userID] = new MuteData(sender, reason);
                BroadcastChat("USER.MUTED.REASON", sender, name, reason, "Unlimited");
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, name, "Unlimited", reason);
            }
            else {
                mutes[userID] = new MuteData(sender, reason, time.Value);
                BroadcastChat("USER.MUTED.REASON", sender, name, reason, MuteData.TimeToString(time.Value));
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, name, MuteData.TimeToString(time.Value), reason);
            }
            Log(LogType.Mute, log);
            SaveMutes();
        }
        private Dictionary<string, string> GetPlayers(string NameOrID) {
            var pl = players.FindPlayers(NameOrID).ToList();
            return pl.Select(p => new KeyValuePair<string, string>(p.Id, p.Name)).ToDictionary(x => x.Key, x => x.Value);
        }
        private void SendChatHelp(IPlayer player) {
            string msg = GetMsg("CMD.CHAT.HELP", player.Id);
            if (CanMuteAll(player)) msg += GetMsg("CMD.MUTE.ALL.HELP", player.Id);
            if (IsAdmin(player)) msg += GetMsg("CMD.CHAT.HELP.PERMISSION.ADMIN", player.Id);
            if (IsModerator(player)) msg += GetMsg("CMD.CHAT.HELP.PERMISSION.MODERATOR", player.Id);
            msg = player.IsServer ? Formatter.ToPlaintext(msg) : covalence.FormatText(msg);
            player.Message(msg);
        }
#endregion
#region Flags
        bool IsModerator(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.ModerPermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 1;
        bool IsAdmin(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.AdminPermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 2;
        bool CanMute(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.MutePermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 1;
        bool CanMuteAll(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.MuteAllPermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 2;
        bool CanAssign(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.AssignPermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 2;
        bool CanUnMute(IPlayer player) => PermissionService.HasPermission(player.Id, config.adminPrivilages.UnMutePermiss) || player.IsAdmin;
        //player.net.connection.authLevel >= 1;
#endregion
#region Commands
#if RUST
        object OnServerCommand(ConsoleSystem.Arg arg, Chat.ChatChannel channel) {
            if (arg?.cmd?.FullName != null && arg?.cmd?.FullName == "global.say") {
                if (!arg.HasArgs()) return false;
                string message = string.Join(" ", arg.Args);
                bool outer;
                var cens = CensorBadWords(message, out outer);
                cens = string.Format(config.ConsoleFormat, config.ConsoleName, cens);
                message = string.Format(config.ConsoleFormat, config.ConsoleName, message);
                Log(LogType.ServerConsole, message);
                SendChat(arg.Player(), "", channel, message, cens);
                return true;
            }
            else return null;
        }
#endif
        [Command("chatplus.prefix")]
        private void cmdConsolePrefix(IPlayer player, string cmd, string[] Args) {
            if (!CanAssign(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (Args == null || Args.Length < 2) {
                Reply(player, "CMD.HELP.PREFIX");
                return;
            }
            var recivers = GetPlayers(Args[0]);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", Args[0]);
                return;
            }
            if (recivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Value} ({p.Key})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target.Key);
            if (!PermissionService.HasPermission(target.Key, Args[1])) {
                Reply(player, "NO.PERMISSION.PLAYER");
                return;
            }
            pdata.Prefix = Args[1];
            Reply(player, "PREFIX.CHANGED", Args[1]);
        }
        [Command("chatplus.name")]
        private void cmdConsoleName(IPlayer player, string cmd, string[] Args) {
            if (!CanAssign(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (Args == null || Args.Length < 2) {
                Reply(player, "CMD.HELP.NAME");
                return;
            }
            var recivers = GetPlayers(Args[0]);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", Args[0]);
                return;
            }
            if (recivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Value} ({p.Key})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target.Key);
            if (!PermissionService.HasPermission(target.Key, Args[1])) {
                Reply(player, "NO.PERMISSION.PLAYER");
                return;
            }
            pdata.NameColor = Args[1];
            Reply(player, "NAME.COLOR.CHANGED", Args[1]);
        }
        [Command("chatplus.message")]
        private void cmdConsoleMessage(IPlayer player, string cmd, string[] Args) {
            if (!CanAssign(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (Args == null || Args.Length < 2) {
                Reply(player, "CMD.HELP.MESSAGE");
                return;
            }
            var recivers = GetPlayers(Args[0]);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", Args[0]);
                return;
            }
            if (recivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Value} ({p.Key})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target.Key);
            if (!PermissionService.HasPermission(target.Key, Args[1])) {
                Reply(player, "NO.PERMISSIO.PLAYERN");
                return;
            }
            pdata.MessageColor = Args[1];
            Reply(player, "MESSAGE.COLOR.CHANGED", Args[1]);
        }
        [Command("muteall")]
        private void cmdChatMuteAll(IPlayer player, string cmd, string[] Args) {
            if (!CanMuteAll(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (GlobalMute) {
                BroadcastChat("MUTE.ALL.ENABLED");
                GlobalMute = false;
                return;
            }
            BroadcastChat("MUTE.ALL.DISABLED");
            GlobalMute = true;
            return;
        }
        [Command("mutelist")]
        void cmdChatMuteList(IPlayer player, string cmd, string[] Args) {
            if (!CanMute(player) || !CanUnMute(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            string msg;
            if (mutes.Count == 0) msg = GetMsg("MUTE.LIST.NOONE");
            else {
                msg = GetMsg("MUTE.LIST.HEAD");
                foreach (var mute in mutes) {
                    msg += "\n" + string.Format(GetMsg("MUTE.LIST.BODY", player.Id), mute.Value.Initiator, $"{players.FindPlayerById(mute.Key.ToString()).Name} ({mute.Key})", mute.Value.Reason, mute.Value.Remain);
                }
            }
            player.Reply(msg);
        }
        [Command("mute")]
        void cmdChatMute(IPlayer player, string cmd, string[] args) {
            if (!CanMute(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (args.Length < 1) {
                Reply(player, "CMD.MUTE.HELP");
                return;
            }
            var recivers = GetPlayers(args[0]);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", args[0]);
                return;
            }
            if (recivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Value} ({p.Key})").ToArray()));
                return;
            }
            var mutePlayer = recivers.First();
            if (MuteData.IsMuted(mutePlayer.Key)) {
                Reply(player, "USER.ALREADY.MUTED", mutePlayer.Value, mutes[mutePlayer.Key].Reason, mutes[mutePlayer.Key].Remain);
                return;
            }
            TimeSpan time;
            string sender = player.IsServer ? config.ConsoleName : player.Name;
            if (config.adminPrivilages.HideAdmins.HasValue && config.adminPrivilages.HideAdmins.Value && !player.IsServer) sender = config.adminPrivilages.AdminReplace;
            if (args.Length == 1) {
                Mute(mutePlayer.Key, mutePlayer.Value, null, null, sender);
                return;
            }
            if (MuteData.StringToTime(args[1], out time)) {
                Mute(mutePlayer.Key, mutePlayer.Value, time, string.Join(" ", args.Skip(2).ToArray()), sender);
                return;
            }
            Mute(mutePlayer.Key, mutePlayer.Value, null, string.Join(" ", args.Skip(1).ToArray()), sender);
        }
        [Command("unmute")]
        void cmdChatUnMute(IPlayer player, string cmd, string[] args) {
            if (!CanUnMute(player)) {
                Reply(player, "NO.ACCESS");
                return;
            }
            if (args.Length == 0) {
                Reply(player, "CMD.UNMUTE.HELP");
                return;
            }
            var recivers = GetPlayers(args[0]);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", args[0]);
                return;
            }
            recivers = recivers.Where(p => mutes.ContainsKey(p.Key)).ToDictionary(x => x.Key, x => x.Value);
            if (recivers == null || recivers.Count == 0) {
                Reply(player, "PLAYER.NOT.MUTED");
                return;
            }
            if (recivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Value} ({p.Key})").ToArray()));
                return;
            }
            var mutePlayer = recivers.First();
            mutes.Remove(mutePlayer.Key);
            BroadcastChat("USER.UNMUTED", player.Name, mutePlayer.Value);
            string log = GetMsg("USER.UNMUTED.LOG");
            log = string.Format(log, player.Name, mutePlayer.Value);
            Log(LogType.Mute, log);
            SaveMutes();
        }
        [Command("chat")]
        void cmdChat(IPlayer player, string cmd, string[] args) {
            if (args.Length == 0) {
                SendChatHelp(player);
                return;
            }
            var playerData = GetPlayerData(player);
            switch (args[0]) {
                case "reset" : PlayersData[player.Id] = new PlayerData();
                Reply(player, "RESET.SUCCESSFULL");
                return;
                case "admin" : if (!IsAdmin(player)) {
                    Reply(player, "NO.ACCESS");
                    return;
                }
                if (playerData.IsAdmin) {
                    playerData.IsAdmin = false;
                    Reply(player, "ADMIN.DISABLE");
                    return;
                }
                playerData.IsAdmin = true;
                Reply(player, "ADMIN.ENABLE");
                return;
                case "moder" : if (!IsModerator(player)) {
                    Reply(player, "NO.ACCESS");
                    return;
                }
                if (playerData.IsModer) {
                    playerData.IsModer = false;
                    Reply(player, "MODERATOR.DISABLE");
                    return;
                }
                playerData.IsModer = true;
                Reply(player, "MODERATOR.ENABLE");
                return;
                case "censor" : if (playerData.Censor) {
                    playerData.Censor = false;
                    Reply(player, "CENSOR.DISABLED");
                    return;
                }
                playerData.Censor = true;
                Reply(player, "CENSOR.ENABLED");
                return;
                case "ignore" : if (args.Length == 2 && args[1] == "list") {
                    if (playerData.BlackList.Count == 0) {
                        Reply(player, "IGNORE.LIST.IS.EMPTY");
                        return;
                    }
                    Reply(player, "IGNORE.LIST", string.Join(", ", playerData.BlackList.Select(p => GetPlayerData(p).Name).ToArray()));
                    return;
                }
                if (args.Length < 3 || (args[1] != "add" && args[1] != "remove")) {
                    Reply(player, "CMD.CHAT.IGNORE.HELP");
                    return;
                }
                bool mode = args[1] == "add" ? true : false;
                var reply = 777;
                var recivers = players.FindPlayers(args[2]);
                if (recivers == null || !recivers.Any()) {
                    Reply(player, "PLAYER.NOT.FOUND", args[2]);
                    return;
                }
                if (recivers.Count() > 1) {
                    Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", recivers.Select(p => $"{p.Name} ({p.Id})").ToArray()));
                    return;
                }
                var ignorePlayer = recivers.First();
                if (mode) {
                    if (!playerData.BlackList.Contains(ignorePlayer.Id)) {
                        playerData.BlackList.Add(ignorePlayer.Id);
                        Reply(player, "USER.ADD.IGNORE.LIST", ignorePlayer.Name);
                        if (ignorePlayer.IsConnected) Reply(ignorePlayer, "YOU.ADD.IGNORE.LIST", player.Name);
                        return;
                    }
                    Reply(player, "USER.IS.IGNORE.LIST", ignorePlayer.Name);
                    return;
                }
                else {
                    if (playerData.BlackList.Contains(ignorePlayer.Id)) {
                        playerData.BlackList.Remove(ignorePlayer.Id);
                        Reply(player, "USER.REMOVE.IGNORE.LIST", ignorePlayer.Name);
                        Reply(ignorePlayer, "YOU.REMOVE.IGNORE.LIST", player.Name);
                        return;
                    }
                    Reply(player, "NOT.ON.IGNORE.LIST", ignorePlayer.Name);
                    return;
                }
                case "sound" : if (args.Length == 1 || (args[1] != "on" && args[1] != "off")) {
                    Reply(player, "CMD.CHAT.SOUND.HELP");
                    return;
                }
                bool pmSound = args[1] == "on";
                playerData.PMSound = pmSound;
                if (pmSound) {
                    Reply(player, "SOUND.ENABLED");
                    return;
                }
                else {
                    Reply(player, "SOUND.DISABLED");
                    return;
                }
                case "prefix" : var aviablePrefixes = config.prefixes.Where(p => PermissionService.HasPermission(player.Id, p.Perm) && playerData.Prefix != p.Perm || p.Perm == "chatplus.default" && playerData.Prefix != p.Perm).ToList();
                if (aviablePrefixes.Count == 0) {
                    Reply(player, "NO.AVAILABLE.PREFIXS");
                    return;
                }
                if (args.Length == 1) {
                    Reply(player, "AVAILABLE.COLORS.PREFIX", string.Join(", ", aviablePrefixes.Select(p => $"{p.Arg}({covalence.FormatText(p.Format)})").ToArray()));
                    return;
                }
                var selectedPrefix = aviablePrefixes.FirstOrDefault(p => p.Arg == args[1]);
                if (selectedPrefix == null) {
                    Reply(player, "PREFIX.NOT.FOUND", args[1]);
                    return;
                }
                playerData.Prefix = selectedPrefix.Perm;
                Reply(player, "PREFIX.CHANGED", selectedPrefix.Arg);
                return;
                case "name" : var aviableNameColors = config.names.Where(p => PermissionService.HasPermission(player.Id, p.Perm) && playerData.NameColor != p.Perm || p.Perm == "chatplus.default" && playerData.NameColor != p.Perm).ToList();
                if (aviableNameColors.Count == 0) {
                    Reply(player, "NO.AVAILABLE.COLORS");
                    return;
                }
                if (args.Length == 1) {
                    Reply(player, "AVAILABLE.COLORS.NAME", string.Join(", ", aviableNameColors.Select(p => covalence.FormatText(string.Format(p.Format, p.Arg))).ToArray()));
                    return;
                }
                var selectedNameColor = aviableNameColors.FirstOrDefault(p => p.Arg == args[1]);
                if (selectedNameColor == null) {
                    Reply(player, "COLOR.NOT.FOUND", args[1]);
                    return;
                }
                playerData.NameColor = selectedNameColor.Perm;
                Reply(player, "NAME.COLOR.CHANGED", selectedNameColor.Arg);
                return;
                case "message" : var aviableMessageColors = config.messages.Where(p => PermissionService.HasPermission(player.Id, p.Perm) && playerData.MessageColor != p.Perm || p.Perm == "chatplus.default" && playerData.MessageColor != p.Perm).ToList();
                if (aviableMessageColors.Count == 0) {
                    Reply(player, "NO.AVAILABLE.COLORS");
                    return;
                }
                if (args.Length == 1) {
                    Reply(player, "AVAILABLE.COLORS.MESSAGE", string.Join(", ", aviableMessageColors.Select(p => covalence.FormatText(string.Format(p.Format, p.Arg))).ToArray()));
                    return;
                }
                var selectedMessageColor = aviableMessageColors.FirstOrDefault(p => p.Arg == args[1]);
                if (selectedMessageColor == null) {
                    Reply(player, "COLOR.NOT.FOUND", args[1]);
                    return;
                }
                playerData.MessageColor = selectedMessageColor.Perm;
                Reply(player, "MESSAGE.COLOR.CHANGED", selectedMessageColor.Arg);
                return;
                default : SendChatHelp(player);
                return;
            }
        }
#endregion
#region Private messaging
#if RUST
        private bool PmAvatar() => config.PMAva.HasValue && config.PMAva.Value;
        private void RustChat(IPlayer player, string langkey, string avatar, params object[] args) {
            var msg = string.Format(GetMsg(langkey, player.Id), args);
            player.Command("chat.add 0", PmAvatar() ? avatar : "0", covalence.FormatText(msg));
        }
#endif
        Dictionary<string, string> pmHistory = new Dictionary<string, string>();
        [Command("pm")]
        void cmdChatPM(IPlayer player, string cmd, string[] args) {
            if (args.Length < 2) {
                Reply(player, "CMD.PM.HELP");
                return;
            }
            var argList = args.ToList();
            argList.RemoveAt(0);
            string message = string.Join(" ", argList.ToArray());
            var receivers = players.Connected.Where(p => p.Name.ToLower().Contains(args[0].ToLower()) || p.Id == args[0]).ToList();
            if (receivers == null || receivers.Count == 0) {
                Reply(player, "PLAYER.NOT.FOUND", args[0]);
                return;
            }
            if (receivers.Count > 1) {
                Reply(player, "MULTIPLE.PLAYERS.FOUND", string.Join("\n", receivers.Select(p => $"{p.Name} ({p.Id})").ToArray()));
                return;
            }
            IPlayer receiver = receivers[0];
            if (receiver.Id == player.Id) {
                Reply(player, "PM.SELF");
                return;
            }
            if (GetPlayerData(receiver).BlackList.Contains(player.Id)) {
                Reply(player, "PM.YOU.ARE.BLACK.LIST", receiver.Name);
                return;
            }
            pmHistory[player.Id] = receiver.Id;
            pmHistory[receiver.Id] = player.Id;
#if RUST
            string msg;
            if (player.IsServer) {
                ConsoleIPly = player;
                Reply(player, "PM.SENDER.FORMAT", receiver.Name, message);
                RustChat(receiver, "PM.RECEIVER.FORMAT", "0", config.ConsoleName, message);
            }
            else {
                RustChat(player, "PM.SENDER.FORMAT", player.Id, receiver.Name, message);
                RustChat(receiver, "PM.RECEIVER.FORMAT", player.Id, player.Name, message);
            }
            var bply = receiver.Object as BasePlayer;
            if (GetPlayerData(receiver).PMSound) {
                Effect.server.Run(strName : config.PrivateSoundMessagePath, ent : bply, boneID : 0, posLocal : Vector3.zero, normLocal : Vector3.zero);
            }
#else
            Reply(player, "PM.SENDER.FORMAT", receiver.Name, message);
            if (player.IsServer) {
                ConsoleIPly = player;
                Reply(receiver, "PM.RECEIVER.FORMAT", config.ConsoleName, message);
            }
            else Reply(receiver, "PM.RECEIVER.FORMAT", player.Name, message);
#endif
            Log(LogType.PM, string.Format(GetMsg("PM.LOG"), $"{player.Name}({player.Id})", $"{receiver.Name}({receiver.Id})", message));
        }
        [Command("r")]
        void cmdChatR(IPlayer player, string cmd, string[] args) {
            if (args.Length == 0) {
                Reply(player, "CMD.R.HELP");
                return;
            }
            string message = string.Join(" ", args);
            string recieverUserId;
            if (!pmHistory.TryGetValue(player.Id, out recieverUserId)) {
                Reply(player, "PM.NO.MESSAGES");
                return;
            }
            if (recieverUserId== "server_console") {
#if RUST
                RustChat(player, "PM.SENDER.FORMAT", player.Id, config.ConsoleName, message);
#else
                Reply(player, "PM.SENDER.FORMAT", config.ConsoleName, message);
#endif
                Reply(ConsoleIPly, "PM.RECEIVER.FORMAT", player.Name, message);
                Log(LogType.PM, string.Format(GetMsg("PM.LOG"), $"{player.Name}({player.Id})", $"Server console", message));
                return;
            }
            var receiver = players.Connected.FirstOrDefault(p => p.Id == recieverUserId);
            if (receiver == null) {
                Reply(player, "PM.PLAYER.LEAVE");
                return;
            }
            if (GetPlayerData(receiver).BlackList.Contains(player.Id)) {
                Reply(player, "PM.YOU.ARE.BLACK.LIST", receiver.Name);
                return;
            }
#if RUST
            if (player.IsServer) {
                Reply(player, "PM.SENDER.FORMAT", receiver.Name, message);
                RustChat(receiver, "PM.RECEIVER.FORMAT", "0", config.ConsoleName, message);
            }
            else {
                RustChat(player, "PM.SENDER.FORMAT", player.Id, receiver.Name, message);
                RustChat(receiver, "PM.RECEIVER.FORMAT", player.Id, player.Name, message);
            }
            var bply = receiver.Object as BasePlayer;
            if (GetPlayerData(receiver).PMSound) {
                Effect.server.Run(strName : config.PrivateSoundMessagePath, ent : bply, boneID : 0, posLocal : Vector3.zero, normLocal : Vector3.zero);
            }
#else
            Reply(player, "PM.SENDER.FORMAT", receiver.Name, message);
            Reply(receiver, "PM.RECEIVER.FORMAT", player.IsServer ? config.ConsoleName : player.Name, message);
#endif
            Log(LogType.PM, string.Format(GetMsg("PM.LOG"), $"{player.Name}({player.Id})", $"{receiver.Name}({receiver.Id})", message));
        }
#endregion
#region Data
        private class MuteData {
            public readonly string Initiator;
            public readonly string Reason;
            public readonly DateTime ExpireDate;
            [JsonIgnore]
            private bool Timed => ExpireDate != DateTime.MinValue;
            [JsonIgnore]
            public bool Expired => Timed && ExpireDate < DateTime.UtcNow;
            [JsonIgnore]
            public string Remain => Timed ? TimeToString(ExpireDate - DateTime.UtcNow) : "Unlimited";
            public static bool IsMuted(string userID) => mutes.ContainsKey(userID);
            public MuteData(string Initiator, string Reason, TimeSpan? Until = null) {
                this.ExpireDate = Until.HasValue ? DateTime.UtcNow + Until.Value : DateTime.MinValue;
                this.Reason = Reason;
                this.Initiator = Initiator;
            }
            [JsonConstructor]
            public MuteData(string Initiator, string Reason, DateTime ExpireDate) {
                Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Chat, $"Mutedata initilizere called with: {Initiator} | {Reason} | {ExpireDate}");
                this.ExpireDate = ExpireDate;
                this.Reason = Reason;
                this.Initiator = Initiator;
            }
            public static string TimeToString(TimeSpan elapsedTime) {
                int hours = elapsedTime.Hours;
                int minutes = elapsedTime.Minutes;
                int seconds = elapsedTime.Seconds;
                int days = elapsedTime.Days;
                string s = "";
                if (days > 0) s += $"{day
// ... [Code preview truncated due to length. Full source in attached file] ...

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