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

FREE DiscordChat : 2.2.0 2.2.0

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Ext.Discord.Clients;
using Oxide.Ext.Discord.Connections;
using Oxide.Ext.Discord.Constants;
using Oxide.Ext.Discord.Entities;
using Oxide.Ext.Discord.Interfaces;
using Oxide.Ext.Discord.Libraries;
using Oxide.Ext.Discord.Logging;
using Oxide.Ext.Discord.Rest;
#if RUST
using ConVar;
#endif

// ReSharper disable MemberCanBePrivate.Global
namespace Oxide.Plugins
{
    [Info("Discord Chat", "MJSU", "2.2.0")]
    [Description("Allows chatting through discord")]
    internal class DiscordChat : CovalencePlugin, IDiscordPlugin
    {
        #region Class Fields
        [PluginReference]
        private Plugin AdminChat, AdminDeepCover, AntiSpam, BetterChat, BetterChatMute, Clans, ChatTranslator, TranslationAPI, UFilter;
        
        public DiscordClient Client { get; set;}

        private readonly BotConnection _discordSettings = new BotConnection
        {
            Intents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages
        };

        private readonly AllowedMentions _allowedMention = new AllowedMentions
        {
            AllowedTypes = new List<AllowedMentionTypes>(),
            Roles = new List<Snowflake>(),
            Users = new List<Snowflake>()
        };

        private DiscordGuild _guild;
        private Snowflake _guildId;

        private readonly DiscordSubscriptions _subscriptions = GetLibrary<DiscordSubscriptions>();

        private PluginConfig _pluginConfig;

        private readonly Hash<MessageType, DiscordTimedSend> _sends = new Hash<MessageType, DiscordTimedSend>();

        private static DiscordChat _ins;

        public enum MessageType
        {
            Discord,
            Server,
            Team,
            Cards,
            JoinLeave,
            AdminChat,
            OnlineOffline
        }

        private readonly StringBuilder _name = new StringBuilder();
        private readonly StringBuilder _message = new StringBuilder();
        private readonly StringBuilder _mentions = new StringBuilder();
        
        private readonly Regex _channelMention = new Regex("(<#\\d+>)", RegexOptions.IgnoreCase | RegexOptions.Compiled);

        private bool _isServerStartup;
        #endregion

        #region Setup & Loading
        private void Init()
        {
            _ins = this;

            _discordSettings.ApiToken = _pluginConfig.DiscordApiKey;
            _discordSettings.LogLevel = _pluginConfig.ExtensionDebugging;
        }

        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                [LangKeys.Discord.NotLinkedError] = "You're not allowed to chat with the server unless you are linked.",
                [LangKeys.Discord.JoinLeave.ConnectedMessage] = ":white_check_mark: ({0:HH:mm}) **{1}** has joined.",
                [LangKeys.Discord.JoinLeave.DisconnectedMessage] = ":x: ({0:HH:mm}) **{1}** has disconnected.({2})",
                [LangKeys.Discord.OnlineOffline.OnlineMessage] = ":green_circle: The server is now online",
                [LangKeys.Discord.OnlineOffline.OfflineMessage] = ":red_circle: The server has shutdown",
                [LangKeys.Discord.ChatChannel.Message] = ":desktop: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.ChatChannel.LinkedMessage] = ":speech_left: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.ChatChannel.UnlinkedMessage] = ":chains: ({0:HH:mm}) **{1}#{2}**: {3}",
                [LangKeys.Discord.TeamChannel.Message] = ":busts_in_silhouette: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.CardsChannel.Message] = ":black_joker: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.AdminChat.Message] = ":mechanic: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.AdminChat.Permission] = ":no_entry: You're not allowed to use admin chat channel because you do not have permission.",
                [LangKeys.Server.DiscordTag] = "[#5f79d6][Discord][/#]",
                [LangKeys.Server.UnlinkedMessage] = "{0} [#5f79d6]{1}#{2}[/#]: {3}",
                [LangKeys.Server.LinkedMessage] = "{0} [#5f79d6]{1}[/#]: {2}",
                [LangKeys.Server.ClanTag] = "[{0}] "
            }, this);

            lang.RegisterMessages(new Dictionary<string, string>
            {
                [LangKeys.Discord.NotLinkedError] = "Вам не разрешено писать в чат сервера, если ваши аккаунты не связаны.",
                [LangKeys.Discord.JoinLeave.ConnectedMessage] = ":white_check_mark: {0:HH:mm} **{1}** подключился",
                [LangKeys.Discord.JoinLeave.DisconnectedMessage] = ":x: {0:HH:mm} **{1}** отключился.Причина: {2}",
                [LangKeys.Discord.OnlineOffline.OnlineMessage] = ":green_circle: Выключение сервера",
                [LangKeys.Discord.OnlineOffline.OfflineMessage] = ":red_circle: Сервер снова онлайн",
                [LangKeys.Discord.ChatChannel.Message] = ":desktop: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.ChatChannel.LinkedMessage] = ":speech_left: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.ChatChannel.UnlinkedMessage] = ":chains: ({0:HH:mm}) **{1}#{2}**: {3}",
                [LangKeys.Discord.TeamChannel.Message] = ":busts_in_silhouette: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.CardsChannel.Message] = ":black_joker: ({0:HH:mm}) **{1}**: {2}",
                [LangKeys.Discord.AdminChat.Message] = ":mechanic: ({0:HH:mm}) **{1}** {2}",
                [LangKeys.Discord.AdminChat.Permission] = "Вам не разрешено использовать канал чата администратора, потому что у вас нет разрешения.",
                [LangKeys.Server.DiscordTag] = "[#5f79d6][Discord][/#]",
                [LangKeys.Server.UnlinkedMessage] = "{0} [#5f79d6]{1}#{2}[/#]: {3}",
                [LangKeys.Server.LinkedMessage] = "{0} [#5f79d6]{1}[/#]: {2}",
                [LangKeys.Server.ClanTag] = "[{0}] "
            }, this, "ru");
        }

        protected override void LoadDefaultConfig()
        {
            PrintWarning("Loading Default Config");
        }

        protected override void LoadConfig()
        {
            base.LoadConfig();
            _pluginConfig = AdditionalConfig(Config.ReadObject<PluginConfig>());
            Config.WriteObject(_pluginConfig);
        }

        private PluginConfig AdditionalConfig(PluginConfig config)
        {
            config.ChannelSettings = new ChannelSettings(config.ChannelSettings);
            config.MessageSettings = new MessageSettings(config.MessageSettings);
            config.PluginSupport = new PluginSupport(config.PluginSupport);
            return config;
        }

        private void OnServerInitialized(bool startup)
        {
            _isServerStartup = startup;
            if (IsPluginLoaded(BetterChat))
            {
                if (BetterChat.Version < new VersionNumber(5, 2, 7))
                {
                    PrintWarning("Please update your version of BetterChat to version >= 5.2.7");
                }

                if (_pluginConfig.EnableServerChatTag)
                {
                    BetterChat.Call("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(GetBetterChatTag));
                }
            }

            if (_pluginConfig.PluginSupport.AntiSpam.ValidateNicknames
                || _pluginConfig.PluginSupport.AntiSpam.ServerMessage
                || _pluginConfig.PluginSupport.AntiSpam.DiscordMessage
#if RUST
                || _pluginConfig.PluginSupport.AntiSpam.TeamMessage
#endif
            )
            {
                if (AntiSpam == null)
                {
                    PrintWarning("AntiSpam is enabled in the config but is not loaded." +
                                 "Please disable the setting in the config or load AntiSpam: https://umod.org/plugins/anti-spam");
                    return;
                }

                if (AntiSpam.Version < new VersionNumber(2, 0, 0))
                {
                    PrintError("AntiSpam plugin must be version 2.0.0 or higher");
                }
            }

            if (string.IsNullOrEmpty(_pluginConfig.DiscordApiKey))
            {
                PrintWarning("Please set the Discord Bot Token and reload the plugin");
                return;
            }

            Client.Connect(_discordSettings);

            if (!_pluginConfig.ChannelSettings.ChatChannel.IsValid()
#if RUST
                && !_pluginConfig.ChannelSettings.TeamChannel.IsValid()
                && !_pluginConfig.ChannelSettings.CardsChannel.IsValid()
#endif
            )
            {
#if RUST
                Unsubscribe(nameof(OnPlayerChat));
#else
                Unsubscribe(nameof(OnUserChat));
#endif
            }

            if (!_pluginConfig.ChannelSettings.JoinLeaveChannel.IsValid())
            {
                Unsubscribe(nameof(OnUserConnected));
                Unsubscribe(nameof(OnUserDisconnected));
            }

            if (!_pluginConfig.ChannelSettings.OnlineOfflineChannel.IsValid())
            {
                Unsubscribe(nameof(OnServerShutdown));
            }
        }

        private void OnServerShutdown()
        {
            string message = JsonConvert.SerializeObject(new MessageCreate { Content = Lang(LangKeys.Discord.OnlineOffline.OfflineMessage) }, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
            webrequest.Enqueue( $"{DiscordEndpoints.Rest.ApiUrl}/channels/{_pluginConfig.ChannelSettings.OnlineOfflineChannel.ToString()}/messages",
                message,
                (i, s) => { },
                null,
                RequestMethod.POST,
                new Dictionary<string, string> { ["Authorization"] = $"Bot {_pluginConfig.DiscordApiKey}", ["Content-Type"] = "application/json" });
        }

        private void Unload()
        {
            _ins = null;
        }
        #endregion

        #region Discord Setup
        [HookMethod(DiscordExtHooks.OnDiscordGatewayReady)]
        private void OnDiscordGatewayReady(GatewayReadyEvent ready)
        {
            if (ready.Guilds.Count == 0)
            {
                PrintError("Your bot was not found in any discord servers.Please invite it to a server and reload the plugin.");
                return;
            }

            DiscordGuild guild = null;
            if (ready.Guilds.Count == 1 && !_pluginConfig.GuildId.IsValid())
            {
                guild = ready.Guilds.Values.FirstOrDefault();
            }

            if (guild == null)
            {
                guild = ready.Guilds[_pluginConfig.GuildId];
                if (guild == null)
                {
                    PrintError("Failed to find a matching guild for the Discord Server Id." +
                               "Please make sure your guild Id is correct and the bot is in the discord server.");
                    return;
                }
            }

            DiscordApplication app = Client.Bot.Application;
            if (!app.HasApplicationFlag(ApplicationFlags.GatewayMessageContentLimited) && !app.HasApplicationFlag(ApplicationFlags.GatewayMessageContent))
            {
                PrintWarning($"You will need to enable \"Message Content Intent\" for {Client.Bot.BotUser.Username} @ https://discord.com/developers/applications\n by April 2022" +
                             $"{Name} will stop function correctly after that date until that is fixed.Once updated please reload {Name}.");
            }

            _guildId = guild.Id;
            Puts($"{Title} Ready");
        }

        [HookMethod(DiscordExtHooks.OnDiscordGuildCreated)]
        private void OnDiscordGuildCreated(DiscordGuild guild)
        {
            if (guild.Id != _guildId)
            {
                return;
            }

            _guild = guild;
            if (_pluginConfig.MessageSettings.DiscordToServer)
            {
                SetupChannel(MessageType.Server, _pluginConfig.ChannelSettings.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay, HandleDiscordChatMessage);
            }
            else
            {
                SetupChannel(MessageType.Server, _pluginConfig.ChannelSettings.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay);
            }

            SetupChannel(MessageType.JoinLeave, _pluginConfig.ChannelSettings.JoinLeaveChannel, false);
            SetupChannel(MessageType.OnlineOffline, _pluginConfig.ChannelSettings.OnlineOfflineChannel, false);
            SetupChannel(MessageType.AdminChat, _pluginConfig.PluginSupport.AdminChat.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay, HandleAdminChatDiscordMessage);

#if RUST
            SetupChannel(MessageType.Team, _pluginConfig.ChannelSettings.TeamChannel, false);
            SetupChannel(MessageType.Cards, _pluginConfig.ChannelSettings.CardsChannel, false);
#endif

            if (_isServerStartup)
            {
                _sends[MessageType.OnlineOffline]?.QueueMessage(Lang(LangKeys.Discord.OnlineOffline.OnlineMessage));
            }
        }

        public void SetupChannel(MessageType messageChannel, Snowflake id, bool wipeNonBotMessages, Action<DiscordMessage> message = null)
        {
            if (!id.IsValid())
            {
                return;
            }

            DiscordChannel channel = _guild.Channels[id];
            if (channel == null)
            {
                PrintWarning($"Channel with ID: '{id}' not found in guild");
                return;
            }

            if (message != null)
            {
                _subscriptions.AddChannelSubscription(Client, id, message);
            }

            if (wipeNonBotMessages)
            {
                channel.GetMessages(Client, new ChannelMessagesRequest{Limit = 100}).Then(messages => OnGetChannelMessages(messages, channel));
            }

            _sends[messageChannel] = new DiscordTimedSend(id);
        }

        private void OnGetChannelMessages(List<DiscordMessage> messages, DiscordChannel channel)
        {
            if (messages.Count == 0)
            {
                return;
            }

            DiscordMessage[] messagesToDelete = messages.Where(m => !ShouldIgnoreDiscordUser(m.Author)).ToArray();

            if (messagesToDelete.Length == 0)
            {
                return;
            }

            if (messagesToDelete.Length == 1)
            {
                messagesToDelete[0]?.Delete(Client);
                return;
            }

            channel.BulkDeleteMessages(Client, messagesToDelete.Take(100).Select(m => m.Id).ToArray());
        }
        #endregion

        #region Oxide Chat Hooks
#if RUST
        private void OnPlayerChat(BasePlayer rustPlayer, string message, Chat.ChatChannel chatChannel)
        {
            IPlayer player = rustPlayer.IPlayer;
            int channel = (int)chatChannel;

#else
        private void OnUserChat(IPlayer player, string message)
        {
            int channel = 0;
#endif

            if (channel == 0 && !_pluginConfig.MessageSettings.ServerToDiscord)
            {
                return;
            }

            //Ignore Admin Chat Messages
            //Processed by OnAdminChat Hook
            if (IsAdminChatMessage(player, message))
            {
                return;
            }

            if (IsBetterChatMuted(player))
            {
                return;
            }

            MessageType type = GetMessageType(message, channel, player);
            //Check if type is enabled
            if (!_sends.ContainsKey(type))
            {
                return;
            }

            if (IsInAdminDeepCover(player, type))
            {
                return;
            }

            GetMessage(message, type, newMessage => { _sends[type]?.QueueMessage(FormatServerMessage(player, type, newMessage.ToString())); });
        }

        private MessageType GetMessageType(string message, int channel, IPlayer player)
        {
            switch (channel)
            {
                case 1:
                    return MessageType.Team;
                case 3:
                    return MessageType.Cards;
                default:
                    return IsAdminChatMessage(player, message) ? MessageType.AdminChat : MessageType.Server;
            }
        }
        #endregion

        #region Discord Hooks
        public void HandleDiscordChatMessage(DiscordMessage message)
        {
            if (ShouldIgnoreDiscordUser(message.Author))
            {
                return;
            }

            if (ShouldIgnorePrefix(message.Content))
            {
                return;
            }

            IPlayer player = message.Author.Player;
            if (Interface.Oxide.CallHook("OnDiscordChatMessage", player, message.Content, message.Author) != null)
            {
                return;
            }

            if (player != null && IsBetterChatMuted(player))
            {
                if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
                {
                    timer.In(.25f, () =>
                    {
                        message.Delete(Client);
                    });
                }
                return;
            }

            ProcessMentions(message);
            GetMessage(message.Content, MessageType.Discord, sb =>
            {
                if (player == null)
                {
                    if (!IsUnlinkedBlocked(message))
                    {
                        HandleUnlinkedMessage(message, sb);
                    }
                }
                else
                {
                    HandleLinkedMessage(player, sb, message);
                }
            });
        }

        public void HandleLinkedMessage(IPlayer player, StringBuilder sb, DiscordMessage discordMessage)
        {
            string message = sb.ToString();
            if (string.IsNullOrEmpty(message) || message.Trim().Length == 0)
            {
                discordMessage.Delete(Client);
                return;
            }

            if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
            {
                _sends[MessageType.Server].QueueMessage(FormatServerMessage(player, MessageType.Discord, message));
                discordMessage.Delete(Client);
            }

            if (_pluginConfig.MessageSettings.AllowPluginProcessing)
            {
                bool playerReturn = false;
#if RUST
                //Let other chat plugins process first
                if (player.Object != null)
                {
                    Unsubscribe(nameof(OnPlayerChat));
                    playerReturn = Interface.Call(nameof(OnPlayerChat), player.Object, message, Chat.ChatChannel.Global) != null;
                    Subscribe(nameof(OnPlayerChat));
                }
#endif

                //Let other chat plugins process first
                Unsubscribe("OnUserChat");
                bool userReturn = Interface.Call("OnUserChat", player, message) != null;
                Subscribe("OnUserChat");

                if (playerReturn || userReturn)
                {
                    return;
                }

                if (SendBetterChatMessage(player, message))
                {
                    return;
                }
            }

            string discordTag = string.Empty;
            if (_pluginConfig.EnableServerChatTag)
            {
                discordTag = Lang(LangKeys.Server.DiscordTag, player);
            }

            message = Lang(LangKeys.Server.LinkedMessage, player, discordTag, player.Name, message);
            server.Broadcast(message);
            Puts(Formatter.ToPlaintext(message));
        }

        public void HandleUnlinkedMessage(DiscordMessage discordMessage, StringBuilder sb)
        {
            string message = sb.ToString();
            if (string.IsNullOrEmpty(message) || message.Trim().Length == 0)
            {
                discordMessage.Delete(Client);
                return;
            }

            if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
            {
                _sends[MessageType.Server].QueueMessage(Lang(LangKeys.Discord.ChatChannel.UnlinkedMessage, null, GetServerTime(), discordMessage.Author.Username, discordMessage.Author.Discriminator, message));
                discordMessage.Delete(Client);
            }

            string name = _guild.Members[discordMessage.Author.Id]?.DisplayName ?? discordMessage.Author.Username;

            string serverMessage = Lang(LangKeys.Server.UnlinkedMessage, null, Lang(LangKeys.Server.DiscordTag), name, discordMessage.Author.Discriminator, message);
            server.Broadcast(serverMessage);
            Puts(Formatter.ToPlaintext(serverMessage));
        }
        #endregion

        #region Join Leave Handling
        private void OnUserConnected(IPlayer player)
        {
            _sends[MessageType.JoinLeave].QueueMessage(Lang(LangKeys.Discord.JoinLeave.ConnectedMessage, player, GetServerTime(), GetPlayerName(player), player.Id));
        }

        private void OnUserDisconnected(IPlayer player, string reason)
        {
            _sends[MessageType.JoinLeave].QueueMessage(Lang(LangKeys.Discord.JoinLeave.DisconnectedMessage, player, GetServerTime(), GetPlayerName(player), reason, player.Id));
        }
        #endregion

        #region Plugin Support
        #region AdminDeepCover
        public bool IsInAdminDeepCover(IPlayer player, MessageType type)
        {
            return IsPluginLoaded(AdminDeepCover)
                   && player.Object != null
                   && (type == MessageType.Server || type == MessageType.Discord)
                   && AdminDeepCover.Call<bool>("API_IsDeepCovered", player.Object);
        }
        #endregion

        #region AdminChat
        private const string AdminChatPermission = "adminchat.use";

        public bool IsAdminChatEnabled() => IsPluginLoaded(AdminChat) && _pluginConfig.PluginSupport.AdminChat.Enabled && _sends.ContainsKey(MessageType.AdminChat);
        public bool CanPlayerAdminChat(IPlayer player) => IsAdminChatEnabled() && player.HasPermission(AdminChatPermission);
        public bool IsAdminChatMessage(IPlayer player, string message) => CanPlayerAdminChat(player) && (message.StartsWith(_pluginConfig.PluginSupport.AdminChat.AdminChatPrefix) || AdminChat.Call<bool>("HasAdminChatEnabled", player));

        //Hook called from AdminChat Plugin
        [HookMethod(nameof(OnAdminChat))]
        public void OnAdminChat(IPlayer player, string message)
        {
            if (IsAdminChatEnabled())
            {
                _sends[MessageType.AdminChat].QueueMessage(Lang(LangKeys.Discord.AdminChat.Message, player, GetServerTime(), player.Name, message));
            }
        }

        //If this is an admin chat message from the server ignore it as we use hook to process.public bool HandledAdminChatServerMessage(IPlayer player, string message)
        {
            return IsAdminChatMessage(player, message);
        }

        //Message sent in admin chat channel.Process bot replace and sending to server
        public void HandleAdminChatDiscordMessage(DiscordMessage message)
        {
            AdminChatSettings settings = _pluginConfig.PluginSupport.AdminChat;

            IPlayer player = message.Author.Player;
            if (player == null)
            {
                message.Reply(Client, Lang(LangKeys.Discord.NotLinkedError));
                return;
            }

            if (!CanPlayerAdminChat(player))
            {
                message.Reply(Client, Lang(LangKeys.Discord.AdminChat.Permission, player));
                return;
            }

            if (settings.ReplaceWithBot)
            {
                timer.In(.25f, () => { message.Delete(Client); });

                _sends[MessageType.AdminChat].QueueMessage(Lang(LangKeys.Discord.AdminChat.Message, player, GetServerTime(), player.Name, message.Content));
            }

            AdminChat.Call("SendAdminMessage", player, message.Content);
        }
        #endregion

        #region AntiSpam
        public bool AntiSpamLoaded() => AntiSpam != null && AntiSpam.IsLoaded;
        public bool CanAntiSpamPlayerNames() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.ValidateNicknames;
        public bool CanAntiSpamGlobalMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.ServerMessage;
        public bool CanAntiSpamDiscordMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.DiscordMessage;
#if RUST
        public bool CanAntiSpamTeamMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.TeamMessage;
        public bool CanAntiSpamCardsMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.CardMessages;
#endif
        public bool CanAntiSpam(MessageType type)
        {
            switch (type)
            {
                case MessageType.Server:
                    return CanAntiSpamGlobalMessage();

                case MessageType.Discord:
                    return CanAntiSpamDiscordMessage();

#if RUST
                case MessageType.Team:
                    return CanAntiSpamTeamMessage();

                case MessageType.Cards:
                    return CanAntiSpamCardsMessage();
#endif
            }

            return false;
        }

        public void ProcessMessageAntiSpam(StringBuilder message, MessageType type)
        {
            if (CanAntiSpam(type))
            {
                string clearMessage = AntiSpam.Call<string>("GetSpamFreeText", message.ToString());
                message.Length = 0;
                message.Append(clearMessage);
            }
        }

        public void ProcessNameAntiSpam(IPlayer player, StringBuilder sb)
        {
            if (CanAntiSpamPlayerNames())
            {
                sb.Length = 0;
                sb.Append(AntiSpam.Call<string>("GetClearName", player));
            }
        }
        #endregion

        #region BetterChat
        public bool CanBetterChat() => IsPluginLoaded(BetterChat);

        public bool SendBetterChatMessage(IPlayer player, string message)
        {
            if (CanBetterChat())
            {
                Dictionary<string, object> data = BetterChat.Call<Dictionary<string, object>>("API_GetMessageData", player, message);
                BetterChat.Call("API_SendMessage", data);
                return true;
            }

            return false;
        }

        public void GetBetterChatMessage(IPlayer player, string message, out string playerInfo, out string messageInfo)
        {
            string bcMessage = GetBetterChatConsoleMessage(player, message);
            int index = bcMessage.IndexOf(':');

            if (index != -1)
            {
                playerInfo = bcMessage.Substring(0, index);
                messageInfo = bcMessage.Substring(index + 2);
            }
            else
            {
                playerInfo = string.Empty;
                messageInfo = bcMessage;
            }
        }

        public string GetBetterChatConsoleMessage(IPlayer player, string message)
        {
            return BetterChat.Call<string>("API_GetFormattedMessage", player, message, true);
        }

        public string GetBetterChatTag(IPlayer player)
        {
            return player.IsConnected ? null : Lang(LangKeys.Server.DiscordTag, player);
        }
        #endregion

        #region BetterChatMute
        public bool IsBetterChatMuted(IPlayer player) => IsPluginLoaded(BetterChatMute) && _pluginConfig.PluginSupport.BetterChatMuteSettings.IgnoreMuted && BetterChatMute.Call<bool>("API_IsMuted", player);
        #endregion

        #region Clans
        public void ProcessClanName(StringBuilder name, IPlayer player)
        {
            if (!_pluginConfig.PluginSupport.Clans.ShowClanTag || !IsPluginLoaded(Clans))
            {
                return;
            }

            string clanTag = Clans.Call<string>("GetClanOf", player.Id);
            if (!string.IsNullOrEmpty(clanTag))
            {
                name.Insert(0, Lang(LangKeys.Server.ClanTag, player, clanTag));
            }
        }
        #endregion

        #region Translation API
        public bool CanChatTranslator() => IsPluginLoaded(ChatTranslator) && _pluginConfig.PluginSupport.ChatTranslator.Enabled;

        public bool CanChatTranslatorGlobalMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.ServerMessage;
        public bool CanChatTranslatorDiscordMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.DiscordMessage;
#if RUST
        public bool CanChatTranslatorTeamMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.TeamMessage;
        public bool CanChatTranslatorCardsMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.CardMessages;
#endif

        public bool CanChatTranslatorSource(MessageType type)
        {
            switch (type)
            {
                case MessageType.Server:
                    return CanChatTranslatorGlobalMessage();

                case MessageType.Discord:
                    return CanChatTranslatorDiscordMessage();

#if RUST
                case MessageType.Team:
                    return CanChatTranslatorTeamMessage();

                case MessageType.Cards:
                    return CanChatTranslatorCardsMessage();
#endif
            }

            return false;
        }

        public void TranslateMessage(string message, MessageType type, Action<StringBuilder> callback)
        {
            if (CanChatTranslatorSource(type))
            {
                TranslationAPI.Call("Translate", message, _pluginConfig.PluginSupport.ChatTranslator.DiscordServerLanguage, "auto", new Action<string>(translatedText =>
                {
                    _message.Length = 0;
                    _message.Append(message);
                    callback.Invoke(_message);
                }));
            }

            _message.Length = 0;
            _message.Append(message);
            callback.Invoke(_message);
        }
        #endregion

        #region UFilter
        public bool IsUFilterLoaded() => UFilter != null && UFilter.IsLoaded;
        public bool CanUFilterPlayerNames() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.ValidateNicknames;
        public bool CanUFilterGlobalMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.GlobalMessage;
        public bool CanUFilterDiscordMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.DiscordMessages;
#if RUST
        public bool CanUFilterTeamMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.TeamMessage;
        public bool CanUFilterCardMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.CardMessage;
#endif

        public bool CanUFilter(MessageType type)
        {
            switch (type)
            {
                case MessageType.Server:
                    return CanUFilterGlobalMessage();

                case MessageType.Discord:
                    return CanUFilterDiscordMessage();

#if RUST
                case MessageType.Team:
                    return CanUFilterTeamMessage();

                case MessageType.Cards:
                    return CanUFilterCardMessage();
#endif
            }

            return false;
        }

        public void ProcessMessageUFilter(StringBuilder text, MessageType type)
        {
            if (CanUFilter(type))
            {
                UFilterText(text);
            }
        }

        public void ProcessNameUFilter(StringBuilder name)
        {
            if (CanUFilterPlayerNames())
            {
                UFilterText(name);
            }
        }

        public void UFilterText(StringBuilder text)
        {
            string[] profanities = UFilter.Call<string[]>("Profanities", text.ToString());
            if (profanities.Length == 0)
            {
                return;
            }

            foreach (string profanity in profanities)
            {
                text.Replace(profanity, new string('*', profanity.Length));
            }
        }
        #endregion
        #endregion

        #region Helpers
        private DateTime GetServerTime()
        {
            return DateTime.Now + TimeSpan.FromHours(_pluginConfig.MessageSettings.ServerTimeOffset);
        }

        private void ProcessTextReplacements(StringBuilder message)
        {
            foreach (KeyValuePair<string, string> replacement in _pluginConfig.MessageSettings.TextReplacements)
            {
                message.Replace(replacement.Key, replacement.Value);
            }
        }

        private void SendMessageToChannel(Snowflake channelId, StringBuilder message)
        {
            DiscordMessage.Create(Client, channelId, new MessageCreate
            {
                Content = message.ToString(),
                AllowedMentions = _allowedMention
            });
        }

        public string GetPlayerName(IPlayer player)
        {
            _name.Length = 0;
            _name.Append(player.Name);
            ProcessNameAntiSpam(player, _name);
            ProcessNameUFilter(_name);
            ProcessClanName(_name, player);

            return _name.ToString();
        }
        
        private void ProcessMentions(DiscordMessage message)
        {
            _mentions.Length = 0;
            _mentions.Append(message.Content);

            bool changed = false;
            if (message.Mentions != null)
            {
                foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions)
                {
                    _mentions.Replace($"<@{mention.Key.ToString()}>", $"@{mention.Value.Username}");
                    changed = true;
                }
            
                foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions)
                {
                    GuildMember member = _guild.Members[mention.Key];
                    _mentions.Replace($"<@!{mention.Key.ToString()}>", $"@{member?.Nickname ?? mention.Value.Username}");
                    changed = true;
                }
            }
            
            if (message.MentionsChannels != null)
            {
                foreach (KeyValuePair<Snowflake, ChannelMention> mention in message.MentionsChannels)
                {
                    _mentions.Replace($"<#{mention.Key.ToString()}>", $"#{mention.Value.Name}");
                    changed = true;
                }
            }

            foreach (Match match in _channelMention.Matches(message.Content))
            {
                string value = match.Value;
                Snowflake id = new Snowflake(value.Substring(2, value.Length - 3));
                DiscordChannel channel = _guild.Channels[id];
                if (channel != null)
                {
                    _mentions.Replace(value, $"#{channel.Name}");
                }

                changed = true;
            }

            if (message.MentionRoles != null)
            {
                foreach (Snowflake roleId in message.MentionRoles)
                {
                    DiscordRole role = _guild.Roles[roleId];
                    _mentions.Replace($"<@&{roleId.ToString()}>", $"@{role.Name ?? roleId}");
                    changed = true;
                }
            }

            if (changed)
            {
                message.Content = _mentions.ToString();
            }
        }

        public void GetMessage(string message, MessageType type, Action<StringBuilder> callback)
        {
            TranslateMessage(message, type, sb =>
            {
                ProcessTextReplacements(sb);
                ProcessMessageUFilter(sb, type);
                ProcessMessageAntiSpam(sb, type);

                callback.Invoke(sb);
            });
        }

        private bool IsUnlinkedBlocked(DiscordMessage message)
        {
            if (!_pluginConfig.MessageSettings.UnlinkedSettings.AllowedUnlinked)
            {
                message.Reply(Client, Lang(LangKeys.Discord.NotLinkedError)).Then(newMessage => { timer.In(5f, () => { newMessage.Delete(Client); }); });

                return true;
            }

            return false;
        }

        public string FormatServerMessage(IPlayer player, MessageType type, string message)
        {
            string format;
            switch (type)
            {
                case MessageType.Server:
                    format = LangKeys.Discord.ChatChannel.Message;
                    break;

                case MessageType.Team:
                    format = LangKeys.Discord.TeamChannel.Message;
                    break;

                case MessageType.Cards:
                    format = LangKeys.Discord.CardsChannel.Message;
                    break;

                case MessageType.AdminChat:
                    format = LangKeys.Discord.AdminChat.Message;
                    break;

                case MessageType.Discord:
                    format = LangKeys.Discord.ChatChannel.LinkedMessage;
                    break;

                default:
                    return message;
            }

            string playerName;

            if (_pluginConfig.MessageSettings.AllowPluginProcessing && type != MessageType.AdminChat && CanBetterChat())
            {
                GetBetterChatMessage(player, message, out playerName, out message);
            }
            else
            {
                playerName = GetPlayerName(player);
            }

            return Lang(format, player, GetServerTime(), playerName, message);
        }

        public bool ShouldIgnoreDiscordUser(DiscordUser user)
        {
            if (user.Bot ?? false)
            {
                return true;
            }

            MessageFilterSettings filter = _pluginConfig.MessageSettings.Filter;
            if (filter.IgnoreUsers.Contains(user.Id))
            {
                return true;
            }

            GuildMember member = _guild.Members[user.Id];
            if (member != null)
            {
                foreach (Snowflake role in filter.IgnoreRoles)
                {
                    if (member.Roles.Contains(role))
                    {
                        return true;
                    }
                }
            }

            return false;
        }

        public bool ShouldIgnorePrefix(string message)
        {
            for (int index = 0; index < _pluginConfig.MessageSettings.Filter.IgnoredPrefixes.Count; index++)
            {
                string prefix = _pluginConfig.MessageSettings.Filter.IgnoredPrefixes[index];
                if (message.StartsWith(prefix))
                {
                    return true;
                }
            }

            return false;
        }
        
        public bool IsPluginLoaded(Plugin plugin) => plugin != null && plugin.IsLoaded;

        public string Lang(string key, IPlayer player = null)
        {
            return lang.GetMessage(key, this, player?.Id);
        }
        
        public string Lang(string key, IPlayer player = null, params object[] args)
        {
            string lang = Lang(key, player);
            try
            {
                return string.Format(lang, args);
            }
            catch (Exception ex)
            {
                PrintError($"Lang Key '{key}'\nMessage:{lang}\nException:{ex}");
                throw;
            }
        }
        #endregion

        #region Classes
        public class PluginConfig
        {
            [JsonProperty(PropertyName = "Discord Bot Token")]
            public string DiscordApiKey { get; set; } = string.Empty;

            [JsonProperty(PropertyName = "Discord Server ID (Optional if bot only in 1 guild)")]
            public Snowflake GuildId { get; set; }

            [DefaultValue(true)]
            [JsonProperty("Enable Adding Discord Tag To In Game Messages When Sent From Discord")]
            public bool EnableServerChatTag { get; set; } = true;

            [JsonProperty("Channel Settings")]
            public ChannelSettings ChannelSettings { get; set; }

            [JsonProperty("Message Settings")]
            public MessageSettings MessageSettings { get; set; }

            [JsonProperty("Plugin Support")]
            public PluginSupport PluginSupport { get; set; }

            [JsonConverter(typeof(StringEnumConverter))]
            [DefaultValue(DiscordLogLevel.Info)]
            [JsonProperty(PropertyName = "Discord Extension Log Level (Verbose, Debug, Info, Warning, Error, Exception, Off)")]
            public DiscordLogLevel ExtensionDebugging { get; set; } = DiscordLogLevel.Info;
        }

        public class ChannelSettings
        {
            [JsonProperty("Chat Channel ID")]
            public Snowflake ChatChannel { get; set; }

#if RUST
            [JsonProperty("Team Channel ID")]
            public Snowflake TeamChannel { get; set; }

            [JsonProperty("Cards Channel ID")]
            public Snowflake CardsChannel { get; set; }
#endif

            [JsonProperty("Join / Leave Channel ID")]
            public Snowflake JoinLeaveChannel { get; set; }

            [JsonProperty("Server Online / Offline Channel ID")]
            public Snowflake OnlineOfflineChannel { get; set; }

            public ChannelSettings(ChannelSettings settings)
            {
                ChatChannel = settings?.ChatChannel ?? default(Snowflake);
                JoinLeaveChannel = settings?.JoinLeaveChannel ?? default(Snowflake);
                OnlineOfflineChannel = settings?.OnlineOfflineChannel ?? default(Snowflake);
#if RUST
                TeamChannel = settings?.TeamChannel ?? default(Snowflake);
                CardsChannel = settings?.CardsChannel ?? default(Snowflake);
#endif
            }
        }

        public class MessageSettings
        {
            [JsonProperty("Replace Discord User Message With Bot Message")]
            public bool UseBotMessageDisplay { get; set; }

            [JsonProperty("Send Messages From Server Chat To Discord Channel")]
            public bool ServerToDiscord { get; set; }

            [JsonProperty("Send Messages From Discord Channel To Server Chat")]
            public bool DiscordToServer { get; set; }

            [JsonProperty("Allow plugins to process Discord to Server Chat Messages")]
            public bool AllowPluginProcessing { get; set; }

            [JsonProperty("Discord Message Server Time Offset (Hours)")]
            public float ServerTimeOffset { get; set; }

            [JsonProperty("Text Replacements")]
            public Hash<string, string> TextReplacements { get; set; }

            [JsonProperty("Unlinked Settings")]
            public UnlinkedSettings UnlinkedSettings { get; set; }

            [JsonProperty("Message Filter Settings")]
            public MessageFilterSettings Filter { get; set; }

            public MessageSettings(MessageSettings settings)
            {
                UseBotMessageDisplay = settings?.UseBotMessageDisplay ?? true;
                ServerToDiscord = settings?.ServerToDiscord ?? true;
                DiscordToServer = settings?.DiscordToServer ?? true;
                AllowPluginProcessing = settings?.AllowPluginProcessing ?? true;
                ServerTimeOffset = settings?.ServerTimeOffset ?? 0f;
                TextReplacements = settings?.TextReplacements ?? new Hash<string, string> { ["TextToBeReplaced"] = "ReplacedText" };
                UnlinkedSettings = new UnlinkedSettings(settings?.UnlinkedSettings);
                Filter = new MessageFilterSettings(settings?.Filter);
            }
        }

        public class UnlinkedSettings
        {
            [JsonProperty("Allow Unlinked Players To Chat With Server")]
            public bool AllowedUnlinked { get; set; }

#if RUST
            [JsonProperty("Steam Icon ID")]
            public ulong SteamIcon { get; set; }
#endif

            public UnlinkedSettings(UnlinkedSettings settings)
            {
                AllowedUnlinked = settings?.AllowedUnlinked ?? true;
#if RUST
                SteamIcon = settings?.SteamIcon ?? 76561199144296099;
#endif
            }
        }

        public class MessageFilterSettings
        {
            [JsonProperty("Ignore messages from users in this list (Discord ID)")]
            public List<Snowflake> IgnoreUsers { get; set; }

            [JsonProperty("Ignore messages from users in this role (Role ID)")]
            public List<Snowflake> IgnoreRoles { get; set; }

            [JsonProperty("Ignored Prefixes")]
            public List<string> IgnoredPrefixes { get; set; }

            public MessageFilterSettings(MessageFilterSettings settings)
            {
                IgnoreUsers = settings?.IgnoreUsers ?? new List<Snowflake>();
                IgnoreRoles = settings?.IgnoreRoles ?? new List<Snowflake>();
                IgnoredPrefixes = settings?.IgnoredPrefixes ?? new List<string>();
            }
        }

        public class PluginSupport
        {
            [JsonProperty("AdminChat Settings")]
            public AdminChatSettings AdminChat { get; set; }

            [JsonProperty("AntiSpam Settings")]
            public AntiSpamSettings AntiSpam { get; set; }

            [JsonProperty("BetterChatMute Settings")]
            public BetterChatMuteSettings BetterChatMuteSettings { get; set; }

            [JsonProperty("ChatTranslator Settings")]
            public ChatTranslatorSettings ChatTranslator { get; set; }

            [JsonProperty("Clan Settings")]
            public ClanSettings Clans { get; set; }

            [JsonProperty("UFilter Settings")]
            public UFilterSettings UFilter { get; set; }

            public PluginSupport(PluginSupport settings)
            {
                AdminChat = new AdminChatSettings(settings?.AdminChat);
                BetterChatMuteSettings = new BetterChatMuteSettings(settings?.BetterChatMuteSettings);
                ChatTranslator = new ChatTranslatorSettings(settings?.ChatTranslator);
                Clans = new ClanSettings(settings?.Clans);
                AntiSpam = new AntiSpamSettings(settings?.AntiSpam);
                UFilter = new UFilterSettings(settings?.UFilter);
            }
        }

        public class AdminChatSettings
        {
            [JsonProperty("Enable AdminChat Plugin Support")]
            public bool Enabled { get; set; }

            [JsonProperty("Chat Channel ID")]
            public Snowflake ChatChannel { get; set; }

            [JsonProperty("Chat Prefix")]
            public string AdminChatPrefix { get; set; }

            [JsonProperty("Replace Discord Message With Bot")]
            public bool ReplaceWithBot { get; set; }

            public AdminChatSettings(AdminChatSettings settings)
            {
                Enabled = settings?.Enabled ?? false;
                ChatChannel = settings?.ChatChannel ?? default(Snowflake);
                AdminChatPrefix = settings?.AdminChatPrefix ?? "@";
                ReplaceWithBot = settings?.ReplaceWithBot ?? true;
            }
        }

        public class BetterChatMuteSettings
        {
            [JsonProperty("Ignore Muted Players")]
            public bool IgnoreMuted { get; set; }

      
// ... [Code preview truncated due to length. Full source in attached file] ...

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