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

FREE ChatPlus : 1.5.1 1.5.1

Нет прав для скачивания
C#:
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 CompanionServer;
using Oxide.Core.Libraries.Covalence;
using UnityEngine;
using ConVar;
using Facepunch.Math;
namespace Oxide.Plugins {
    [Info("ChatPlus", "https://topplugin.ru/", "1.5.1", ResourceId = 82)]
    public class ChatPlus : CovalencePlugin {
        /*  covalence.FormatText(msg);
         *  Formatter.ToPlaintext(msg);
         *  Original autor: Unknown
         *  Editor: https://discord.com/invite/5DPTsRmd3G
         *  Editor info:
         *    Vk: vk.com/rustnastroika
         * 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
         *   Убрана возможность форматирования текста игроками(перед форматированием сообщение очищается от тэегов)
         *   Поправлена цензура чата. Теперь если исключение находиться на нулевой позиции оно так же будет учтено.
         *   Исправлена ошибка из-за которой время блокировки чата не сохранялось при перезагрузках.
         *      Всем администраторам - пересмотрите список тех, кому блокировали чат. Возможно часть из этих блокировок уже давно должна была закончится =)
         * v1.4.1
         *   Исправлена проверка исключений в списке нецензурных слов. Теперь должна работать корректно.
         * v1.4.2
         *   Исправлен чат после обновления от 7-го ноября
         * v1.5.0
         *   Полноценная поддержка чата команд и Rust+
         *    (В приложении Rust+ НЕ будут работать префиксы и цвета - приложение само по себе их не поддерживает)
         *   Перенаправление чата в rcon консоль
         *   Поддержка offline чата Rust+
         * v1.5.1
         *   Исправлена ошибка, из-за которой личные сообщения через /pm отправлялись дважды
         */
#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
        private object OnPlayerOfflineChat(ulong playerId, string playerName, string message, Chat.ChatChannel channel) {
            if (GlobalMute) {
                return false;
            }
            var userId = playerId.ToString();
            var pData = GetPlayerData(userId, playerName);
            if (SpamCheck(message) != null) return false;
            if (MuteData.IsMuted(userId)) return false;
            if (config.CapsBlock) {
                message = RemoveCaps(message);
            }
            message = RemoveTags(message);
            bool mute;
            var censorMessage = CensorBadWords(message, out mute);
            if (config.BadWordsBlock & mute) {
                Mute(userId, playerName, new TimeSpan(0, 0, config.MuteBadWordsDefault), config.MuteReasonAutoMute);
            }
            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, RemoveTags(playerName));
            message = string.Format(messageColor, message);
            censorMessage = string.Format(messageColor, censorMessage);
            if (prefix.Length > 0) name = $"{prefix} {name}";
            if (channel != Chat.ChatChannel.Team) {
                SendChat(name, message, censorMessage, userId);
                Log(LogType.Chat, $"{name}[{userId}]: {message}");
            }
            else {
                var playerTeam = RelationshipManager.Instance.FindPlayersTeam(playerId);
                if (playerTeam == null) return false;
                var onlineMembers = playerTeam.GetOnlineMemberConnections();
                if (onlineMembers != null) SendChat(name, message, censorMessage, userId, onlineMembers.Select(x => x.player as BasePlayer));
                playerTeam.BroadcastTeamChat(playerId, Formatter.ToPlaintext(name), Formatter.ToPlaintext(message), "#fff");
                Log(LogType.TeamChat, $"{name}[{userId}]: {message}");
            }
            Chat.ChatEntry chatEntry = new Chat.ChatEntry {
                Channel = channel, Message = Formatter.ToPlaintext(message), UserId = userId, Username = Formatter.ToPlaintext(name), Color = "#5af", Time = Epoch.Current
            }
            ;
            Chat.History.Add(chatEntry);
            Facepunch.RCon.Broadcast(Facepunch.RCon.LogType.Chat, chatEntry);
            ServerConsole.PrintColoured(ConsoleColor.DarkYellow, $"[{channel}] {Formatter.ToPlaintext(name)}({userId}) : ", ConsoleColor.DarkGreen, Formatter.ToPlaintext(message));
            return true;
        }
        object OnPlayerChat(BasePlayer player, string message, Chat.ChatChannel channel) {
            var sender = player.IPlayer;
            if (GlobalMute) {
                if (!CanMuteAll(sender)) {
                    Reply(sender, "MUTE.ALL.DISABLED");
                    return false;
                }
            }
            var pData = GetPlayerData(sender);
            if (pData.IsAdmin && channel != Chat.ChatChannel.Team) {
                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("", message, cens);
                return false;
            }
            if (pData.IsModer) {
                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("", message, cens);
                return false;
            }
            if (SpamCheck(sender, message) != null) return false;
            if (MuteCheck(sender) != null) {
                //TODO find a way to make DiscordMesssages die
                return false;
            }
            if (config.CapsBlock) {
                message = RemoveCaps(message);
            }
            message = RemoveTags(message);
            bool mute;
            var censorMessage = CensorBadWords(message, out mute);
            if (config.BadWordsBlock & mute) {
                Mute(sender, new TimeSpan(0, 0, config.MuteBadWordsDefault), config.MuteReasonAutoMute, sender);
            }
            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, RemoveTags(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);
                var dict = result as Dictionary<string, object>;
                if (dict != null) {
                    try {
                        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}";
            if (channel != Chat.ChatChannel.Team) {
                SendChat(name, message, censorMessage, sender.Id);
                Log(LogType.Chat, $"{name}[{sender.Id}]: {message}");
            }
            else {
                var playerTeam = RelationshipManager.Instance.FindPlayersTeam(player.userID);
                if (playerTeam == null) return false;
                var onlineMembers = playerTeam.GetOnlineMemberConnections();
                if (onlineMembers != null) SendChat(name, message, censorMessage, sender.Id, onlineMembers.Select(x => x.player as BasePlayer));
                playerTeam.BroadcastTeamChat(player.userID, Formatter.ToPlaintext(name), Formatter.ToPlaintext(message), "#fff");
                Log(LogType.TeamChat, $"{name}[{sender.Id}]: {message}");
            }
            Chat.ChatEntry chatEntry = new Chat.ChatEntry {
                Channel = channel, Message = Formatter.ToPlaintext(message), UserId = sender.Id, Username = Formatter.ToPlaintext(name), Color = "#5af", Time = Epoch.Current
            }
            ;
            Chat.History.Add(chatEntry);
            Facepunch.RCon.Broadcast(Facepunch.RCon.LogType.Chat, chatEntry);
            ServerConsole.PrintColoured(ConsoleColor.DarkYellow, $"[{channel}] {Formatter.ToPlaintext(name)}({sender.Id}) : ", ConsoleColor.DarkGreen, Formatter.ToPlaintext(message));
            return true;
        }
#region Chat handling
        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).EscapeRichText();
        }
        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;
        }
        bool? SpamCheck(string message) {
            if (message.Length > 100) 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, StringComparison.Ordinal);
                if (firstIndex >= 0 && swear.Value.All(exception => temp.IndexOf(exception, StringComparison.Ordinal) < 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, TeamChat, Mute, Pm, ServerConsole
        }
        private void Log(LogType type, string msg) {
            var text = Formatter.ToPlaintext(msg);
            switch (type) {
                case LogType.Chat : Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Info, $"[CHAT] {text}");
                return;
                case LogType.Mute : Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Info, $"[MUTE] {text}");
                return;
                case LogType.Pm : Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Info, $"[PM] {text}");
                return;
                case LogType.ServerConsole : Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Info, $"[ServerConsole] {text}");
                return;
                case LogType.TeamChat : Interface.Oxide.RootLogger.Write(Core.Logging.LogType.Info, $"[TEAM CHAT] {text}");
                return;
            }
        }
#endregion
#region Broadcasting
        void SendChat(string name, string message, string censorMessage = "", string userId = "0", IEnumerable<BasePlayer> receivers = null) {
            name = covalence.FormatText(name);
            message = covalence.FormatText(message);
            censorMessage = covalence.FormatText(censorMessage);
            if (string.IsNullOrEmpty(censorMessage)) censorMessage = message;
            var channel = receivers == null ? 0 : 1;
            receivers = receivers ?? BasePlayer.activePlayerList;
            foreach (var player in receivers) {
                var msg = GetPlayerData(player).Censor ? censorMessage : message;
                player?.SendConsoleCommand("chat.add", channel, 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) {
            if (player == null) return;
            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 targetId, string targetName, TimeSpan? time, string reason) {
            if (string.IsNullOrEmpty(reason)) reason = config.MuteReason;
            string sender = "ChatPlus";
            string log;
            if (!time.HasValue) {
                mutes[targetId] = new MuteData(sender, reason);
                BroadcastChat("USER.MUTED.REASON", sender, targetName, reason, "Unlimited");
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, targetName, "Unlimited", reason);
                Interface.CallHook("OnBetterChatMuted", targetName, null, reason);
            }
            else {
                mutes[targetId] = new MuteData(sender, reason, time.Value);
                BroadcastChat("USER.MUTED.REASON", sender, targetName, reason, MuteData.TimeToString(time.Value));
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, targetName, MuteData.TimeToString(time.Value), reason);
                Interface.CallHook("OnBetterChatTimeMuted", targetName, null, time.Value, reason);
            }
            Log(LogType.Mute, log);
            SaveMutes();
        }
        void Mute(IPlayer target, TimeSpan? time, string reason, IPlayer player) {
            if (string.IsNullOrEmpty(reason)) reason = config.MuteReason;
            string sender = target == player ? "ChatPlus" : player.IsServer ? config.ConsoleName : player.Name;
            if (config.adminPrivilages.HideAdmins.HasValue && config.adminPrivilages.HideAdmins.Value && !player.IsServer) sender = config.adminPrivilages.AdminReplace;
            string log;
            if (!time.HasValue) {
                mutes[target.Id] = new MuteData(sender, reason);
                BroadcastChat("USER.MUTED.REASON", sender, target.Name, reason, "Unlimited");
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, target.Name, "Unlimited", reason);
                Interface.CallHook("OnBetterChatMuted", target, player, reason);
            }
            else {
                mutes[target.Id] = new MuteData(sender, reason, time.Value);
                BroadcastChat("USER.MUTED.REASON", sender, target.Name, reason, MuteData.TimeToString(time.Value));
                log = string.Format(GetMsg("USER.MUTED.LOG"), sender, target.Name, MuteData.TimeToString(time.Value), reason);
                Interface.CallHook("OnBetterChatTimeMuted", target, player, time.Value, reason);
            }
            Log(LogType.Mute, log);
            SaveMutes();
        }
        private List<IPlayer> GetPlayers(string NameOrID) {
            return players.FindPlayers(NameOrID).ToList();
        }
        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
        object OnServerCommand(ConsoleSystem.Arg arg) {
            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("", message, cens);
                return true;
            }
            else return null;
        }
        [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.Name} ({p.Id})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target);
            if (!PermissionService.HasPermission(target.Id, 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.Name} ({p.Id})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target);
            if (!PermissionService.HasPermission(target.Id, 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.Name} ({p.Id})").ToArray()));
                return;
            }
            var target = recivers.First();
            var pdata = GetPlayerData(target);
            if (!PermissionService.HasPermission(target.Id, 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.Name} ({p.Id})").ToArray()));
                return;
            }
            var mutePlayer = recivers.First();
            if (MuteData.IsMuted(mutePlayer.Id)) {
                Reply(player, "USER.ALREADY.MUTED", mutePlayer.Name, mutes[mutePlayer.Id].Reason, mutes[mutePlayer.Id].Remain);
                return;
            }
            TimeSpan time;
            if (args.Length == 1) {
                Mute(mutePlayer, null, null, player);
                return;
            }
            if (MuteData.StringToTime(args[1], out time)) {
                Mute(mutePlayer, time, string.Join(" ", args.Skip(2).ToArray()), player);
                return;
            }
            Mute(mutePlayer, null, string.Join(" ", args.Skip(1).ToArray()), player);
        }
        [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.Id)).ToList();
            if (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.Name} ({p.Id})").ToArray()));
                return;
            }
            var mutePlayer = recivers.First();
            mutes.Remove(mutePlayer.Id);
            BroadcastChat("USER.UNMUTED", player.Name, mutePlayer.Name);
            string log = GetMsg("USER.UNMUTED.LOG");
            log = string.Format(log, player.Name, mutePlayer.Name);
            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";
                var reply = 2736;
                var recivers = players.FindPlayers(args[2]).ToList();
                if (!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
        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", 2, PmAvatar() ? avatar : "0", covalence.FormatText(msg));
        }
        readonly 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.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))
// ... [Code preview truncated due to length. Full source in attached file] ...

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