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

FREE DiscordPlayers : 2.1.3 2.1.3

Нет прав для скачивания
C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Ext.Discord.Builders;
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 UnityEngine;

namespace Oxide.Plugins
{
    [Info("Discord Players", "MJSU", "2.1.3")]
    [Description("Displays online players in discord")]
    internal class DiscordPlayers : CovalencePlugin, IDiscordPlugin
    {
        #region Class Fields
        public DiscordClient Client { get; set; }
        
        [PluginReference] private Plugin Clans;

        private PluginConfig _pluginConfig; //Plugin Config
        private PluginData _pluginData;
        
        private readonly DiscordCommand _dcCommands = GetLibrary<DiscordCommand>();
        private readonly BotConnection _discordSettings = new BotConnection();

        private readonly Hash<string, DateTime> _onlineSince = new Hash<string, DateTime>();
        private readonly Hash<Snowflake, PermanentMessageHandler> _permanentState = new Hash<Snowflake, PermanentMessageHandler>();

        private readonly StringBuilderPool _pool = new StringBuilderPool();
        
        private readonly EmbedState _state = new EmbedState();

        private const string BaseCommand = "DiscordPlayers_";
        private const string BackCommand = BaseCommand + "Back";
        private const string RefreshCommand = BaseCommand + "Reload";
        private const string ForwardCommand = BaseCommand + "Forward";
        private const string ChangeSort = BaseCommand + "ChangeSort";
        private const string CommandVersion = "V1";
        
        public enum SortBy {Name, Time}
        private readonly SortBy[] _sortBy = (SortBy[])Enum.GetValues(typeof(SortBy));

        private static DiscordPlayers _ins;
        #endregion

        #region Setup & Loading
        private void Init()
        {
            _ins = this;
            _discordSettings.ApiToken = _pluginConfig.DiscordApiKey;
            _discordSettings.LogLevel = _pluginConfig.ExtensionDebugging;
            
            if(_pluginConfig.CommandEmbeds.Any(c => c.Value.Permissions.AllowInDm))
            {
                _discordSettings.Intents |= GatewayIntents.DirectMessages;
            }
            
            if(_pluginConfig.CommandEmbeds.Any(c => c.Value.Permissions.AllowInGuild))
            {
                _discordSettings.Intents |= GatewayIntents.Guilds | GatewayIntents.GuildMessages;
            }

            HashSet<string> perms = new HashSet<string>();
            foreach (EmbedSettings settings in _pluginConfig.CommandEmbeds.Values)
            {
                if (settings.Permissions.RequirePermissions)
                {
                    perms.Add(settings.Permissions.OxidePermission);
                }
            }

            foreach (string perm in perms)
            {
                permission.RegisterPermission(perm, this);
            }

            _pluginData = Interface.Oxide.DataFileSystem.ReadObject<PluginData>(Name);
        }
        
        protected override void LoadDefaultMessages()
        {
            lang.RegisterMessages(new Dictionary<string, string>
            {
                [LangKeys.NoPermission] = "You do not have permission to use this command",
                [LangKeys.BackButtonLabel] = "Back",
                [LangKeys.BackButtonEmoji] = "⬅",
                [LangKeys.PageButtonLabel] = "Page: {0}/{1}",
                [LangKeys.PageButtonEmoji] = "",
                [LangKeys.NextButtonLabel] = "Next",
                [LangKeys.NextButtonEmoji] = "➡",
                [LangKeys.RefreshButtonLabel] = "Refresh",
                [LangKeys.RefreshButtonEmoji] = "🔄",
                [LangKeys.SortedByButtonLabel] = "Sorted By: {0}",
                [LangKeys.SortedByButtonEmoji] = "",
                [LangKeys.SortByEnumName] = "Name",
                [LangKeys.SortByEnumTime] = "Time",
                [LangKeys.OnlineTimeFormat] = "{1}h {2}m {3}s",
            }, this);
        }
        
        protected override void LoadDefaultConfig()
        {
            PrintWarning("Loading Default Config");
        }

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

        private PluginConfig AdditionalConfig(PluginConfig config)
        {
            if (config.PermanentMessages == null)
            {
                config.PermanentMessages = new List<PermanentMessageConfig>();
            }

            if (config.PermanentMessages.Count == 0)
            {
                config.PermanentMessages.Add(new PermanentMessageConfig(null)
                {
                    Command = "players"
                });
                config.PermanentMessages.Add(new PermanentMessageConfig(null)
                {
                    Command = "playersadmin"
                });
            }

            for (int i = 0; i < config.PermanentMessages.Count; i++)
            {
                config.PermanentMessages[i] = new PermanentMessageConfig(config.PermanentMessages[i]);
            }
            
            if (config.CommandEmbeds == null)
            {
                config.CommandEmbeds = new Hash<string, EmbedSettings>();
            }

            //Set default commands if empty
            if (config.CommandEmbeds.Count == 0)
            {
                EmbedSettings playerCommand = new EmbedSettings(null)
                {
                    Embed = new EmbedConfig(null)
                    {
                        Title = "{server.name}",
                        Description = "{server.players}/{server.players.max} Online Players | {server.players.loading} Loading | {server.players.queued} Queued",
                        Color = "#de8732",
                        Image = string.Empty,
                        Thumbnail = string.Empty,
                        Url = string.Empty,
                        Timestamp = true,
                        FieldFormat = new FieldFormat(null)
                        {
                            Title = "{player.name}",
                            Value = "**Online For:** {discordplayers.player.duration}",
                            Inline = true
                        },
                        Footer = new FooterConfig(null)
                        {
                            Enabled = true,
                            Text = string.Empty,
                            IconUrl = string.Empty
                        }
                    },
                    Permissions =
                    {
                        OxidePermission = "discordplayers.use"
                    }
                };

                EmbedSettings adminCommand = new EmbedSettings(null)
                {
                    Embed = new EmbedConfig(null)
                    {
                        Title = "{server.name}",
                        Description = "{server.players}/{server.players.max} Online Players | {server.players.loading} Loading | {server.players.queued} Queued",
                        Color = "#de8732",
                        Image = string.Empty,
                        Thumbnail = string.Empty,
                        Url = string.Empty,
                        Timestamp = true,
                        FieldFormat = new FieldFormat(null)
                        {
                            Title = "{player.name}",
                            Value = "**Steam ID:**{player.id}\n**Online For:** {discordplayers.player.duration}\n**Ping:** {player.ping}ms\n**Country:** {player.address.data!country}",
                            Inline = true
                        },
                        Footer = new FooterConfig(null)
                        {
                            Enabled = true,
                            Text = string.Empty,
                            IconUrl = string.Empty
                        }
                    },
                    Permissions =
                    {
                        RequirePermissions = true,
                        OxidePermission = "discordplayers.admin"
                    }
                };

                config.CommandEmbeds["players"] = playerCommand;
                config.CommandEmbeds["playersadmin"] = adminCommand;
            }
            
            foreach (string key in config.CommandEmbeds.Keys.ToList())
            {
                config.CommandEmbeds[key] = new EmbedSettings(config.CommandEmbeds[key]);
            }

            return config;
        }

        private void OnServerInitialized()
        {
            if (string.IsNullOrEmpty(_pluginConfig.DiscordApiKey))
            {
                PrintWarning("Please set the Discord Bot Token and reload the plugin");
                return;
            }
            
            if (!IsPlaceholderApiLoaded())
            {
                PrintError("Missing plugin dependency PlaceholderAPI: https://umod.org/plugins/placeholder-api");
                return;
            }
            
            if(PlaceholderAPI.Version < new VersionNumber(2, 2, 0))
            {
                PrintError("Placeholder API plugin must be version 2.2.0 or higher");
                return;
            }
            
            if (_pluginConfig.EmbedFieldLimit > 25)
            {
                PrintWarning("Player Amount Per Page cannot be greater than 25");
            }
            else if (_pluginConfig.EmbedFieldLimit < 0)
            {
                PrintWarning("Player Amount Per Page cannot be less than 0");
            }

            _pluginConfig.EmbedFieldLimit = Mathf.Clamp(_pluginConfig.EmbedFieldLimit, 0, 25);
            
            foreach (KeyValuePair<string, EmbedSettings> command in _pluginConfig.CommandEmbeds)
            {
                RegisterDiscordCommand(command.Key, nameof(DiscordPlayersCommand), command.Value.Permissions.AllowInDm, command.Value.Permissions.AllowInGuild, command.Value.Permissions.AllowedChannels);
            }

#if RUST
            foreach (Network.Connection connection in Network.Net.sv.connections)
            {
                _onlineSince[connection.ownerid.ToString()] = DateTime.UtcNow - TimeSpan.FromSeconds(connection.GetSecondsConnected());
            }
#else
            foreach (IPlayer player in players.Connected)
            {
                _onlineSince[player.Id] = DateTime.UtcNow;
            }
#endif

            Client.Connect(_discordSettings);
        }

        private void OnUserConnected(IPlayer player)
        {
            _onlineSince[player.Id] = DateTime.UtcNow;
        }

        private void OnUserDisconnected(IPlayer player)
        {
            _onlineSince.Remove(player.Id);
        }

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

        #region Discord Chat Command
        private void DiscordPlayersCommand(DiscordMessage message, string cmd, string[] args)
        {
            EmbedSettings embed = _pluginConfig.CommandEmbeds[cmd];
            if (embed == null)
            {
                return;
            }
            
            if (embed.Permissions.RequirePermissions && !UserHasPermission(message, embed))
            {
                message.Reply(Client, Lang(LangKeys.NoPermission, message.Author.Player));
                return;
            }
            
            _state.Update(cmd, 0, SortBy.Name);

            message.Reply(Client, BuildCreateMessage(_state));
        }

        public bool UserHasPermission(DiscordMessage message, EmbedSettings settings)
        {
            IPlayer player = message.Author.Player;
            if (player != null && player.HasPermission(settings.Permissions.OxidePermission))
            {
                return true;
            }

            if (message.Member != null)
            {
                foreach (Snowflake role in settings.Permissions.AllowedRoles)
                {
                    if (message.Member.Roles.Contains(role))
                    {
                        return true;
                    }
                }
            }

            return false;
        }
        #endregion

        #region Discord Hooks
        [HookMethod(DiscordExtHooks.OnDiscordGatewayReady)]
        private void OnDiscordGatewayReady(GatewayReadyEvent ready)
        {
            DiscordApplication app = Client.Bot.Application;
            if (!app.HasApplicationFlag(ApplicationFlags.GatewayMessageContentLimited))
            {
                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.");
            }

            Puts($"{Title} Ready");
        }

        [HookMethod(DiscordExtHooks.OnDiscordGuildCreated)]
        private void OnDiscordGuildCreated(DiscordGuild created)
        {
            foreach (PermanentMessageConfig permConfig in _pluginConfig.PermanentMessages)
            {
                if (!permConfig.Enabled || !permConfig.ChannelId.IsValid())
                {
                    continue;
                }

                if (!created.Channels.ContainsKey(permConfig.ChannelId))
                {
                    continue;
                }
                
                if (!_pluginConfig.CommandEmbeds.ContainsKey(permConfig.Command))
                {
                    PrintError($"Permanent Command '{permConfig.Command}' Not Found in Embed Command.Possible commands to use are: {string.Join(", ",  _pluginConfig.CommandEmbeds.Keys.ToArray())}");
                    continue;
                }
                
                DiscordChannel channel = created.Channels[permConfig.ChannelId];
                if (channel == null)
                {
                    continue;
                }

                PermanentMessageData existing = _pluginData.GetPermanentMessage(channel.Id, permConfig.Command);
                if (existing != null)
                {
                    channel.GetMessage(Client, existing.MessageId).Then(message =>
                    {
                        _permanentState[message.Id] = new PermanentMessageHandler(message, permConfig);
                    }).Catch<ResponseError>(error =>
                    {
                        if (error.HttpStatusCode == DiscordHttpStatusCode.NotFound)
                        {
                            CreatePermanentMessage(channel, permConfig);
                        }
                    });
                }
                else
                {
                    CreatePermanentMessage(channel, permConfig);
                }
            }
        }

        private void CreatePermanentMessage(DiscordChannel channel, PermanentMessageConfig permConfig)
        {
            EmbedState state = new EmbedState(permConfig.Command, 0, SortBy.Name);
            channel.CreateMessage(Client, BuildCreateMessage(state)).Then(message =>
            {
                _pluginData.SetPermanentMessage(channel.Id, permConfig.Command, new PermanentMessageData
                {
                    MessageId = message.Id
                });
                SaveData();
                _permanentState[message.Id] = new PermanentMessageHandler(message, permConfig);
            });
        }

        [HookMethod(DiscordExtHooks.OnDiscordInteractionCreated)]
        private void OnDiscordInteractionCreated(DiscordInteraction interaction)
        {
            if (interaction.Type != InteractionType.MessageComponent)
            {
                return;
            }

            string customId = interaction.Data.CustomId;
            if (!customId.StartsWith(BaseCommand))
            {
                return;
            }

            EmbedState state = _permanentState[interaction.Message.Id]?.State ?? _state;
            
            state.Update(customId);
            
            EmbedSettings settings = _pluginConfig.CommandEmbeds[state.EmbedCommand];
            if (settings == null)
            {
                return;
            }
            
            switch (state.InteractionCommand)
            {
                case BackCommand:
                    state.Page--;
                    break;
                
                case RefreshCommand:
                    break;
                
                case ForwardCommand:
                    state.Page++;
                    break;
                
                case ChangeSort:
                    state.Sort = NextEnum(state.Sort, _sortBy);
                    break;
            }

            interaction.CreateResponse(Client, new InteractionResponse
            {
                Type = InteractionResponseType.UpdateMessage,
                Data = BuildInteractionCallback(state)
            });
        }
        #endregion

        #region Message Building
        private MessageCreate BuildCreateMessage(EmbedState state)
        {
            MessageCreate message = new MessageCreate
            {
                Embeds = new List<DiscordEmbed> { BuildEmbed(state) },
                Components = BuildComponents(state)
            };

            return message;
        }

        private InteractionCallbackData BuildInteractionCallback(EmbedState state)
        {
            InteractionCallbackData message = new InteractionCallbackData
            {
                Embeds = new List<DiscordEmbed> { BuildEmbed(state) },
                Components = BuildComponents(state)
            };

            return message;
        }

        private DiscordEmbed BuildEmbed(EmbedState state)
        {
            EmbedSettings settings = _pluginConfig.CommandEmbeds[state.EmbedCommand];
            EmbedConfig embed = settings.Embed;
            DiscordEmbedBuilder builder = new DiscordEmbedBuilder();
            if (!string.IsNullOrEmpty(embed.Title))
            {
                builder.AddTitle(ParseField(null, embed.Title));
            }

            if (!string.IsNullOrEmpty(embed.Description))
            {
                builder.AddDescription(ParseField(null, embed.Description));
            }
            
            if (!string.IsNullOrEmpty(embed.Url))
            {
                builder.AddUrl(ParseField(null, embed.Url));
            }
            
            if (!string.IsNullOrEmpty(embed.Image))
            {
                builder.AddImage(ParseField(null, embed.Image));
            }
            
            if (!string.IsNullOrEmpty(embed.Thumbnail))
            {
                builder.AddThumbnail(ParseField(null, embed.Thumbnail));
            }
            
            if (!string.IsNullOrEmpty(embed.Color))
            {
                builder.AddColor(embed.Color);
            }
            
            if (embed.Timestamp)
            {
                builder.AddNowTimestamp();
            }

            if (embed.Footer.Enabled)
            {
                if (string.IsNullOrEmpty(embed.Footer.Text) &&
                    string.IsNullOrEmpty(embed.Footer.IconUrl))
                {
                    AddPluginInfoFooter(builder);
                }
                else
                {
                    string text = ParseField(null, embed.Footer.Text);
                    string footerUrl = ParseField(null, embed.Footer.IconUrl);
                    builder.AddFooter(text, footerUrl);
                }
            }

            int onlineCount = players.Connected.Count();
            if ((state.Page + 1) * _pluginConfig.EmbedFieldLimit > onlineCount)
            {
                state.Page = onlineCount / _pluginConfig.EmbedFieldLimit;
                if (onlineCount % _pluginConfig.EmbedFieldLimit == 0)
                {
                    state.Page = Math.Max(state.Page - 1, 0);
                }
            }

            IEnumerable<IPlayer> sortedPlayers = players.Connected.Where(p => !p.IsAdmin || settings.ShowAdmins);
            if (state.Sort == SortBy.Name)
            {
                sortedPlayers = sortedPlayers.OrderBy(p => p.Name);
            }
            else
            {
                sortedPlayers = sortedPlayers.OrderBy(p => _onlineSince[p.Id]);
            }

            int index = state.Page * _pluginConfig.EmbedFieldLimit + 1;
            sortedPlayers = sortedPlayers.Skip(state.Page * _pluginConfig.EmbedFieldLimit).Take(_pluginConfig.EmbedFieldLimit);
            foreach (IPlayer player in sortedPlayers)
            {
                string title = $"#{index} {ParseField(player, embed.FieldFormat.Title)}";
                builder.AddField(title, ParseField(player, embed.FieldFormat.Value), embed.FieldFormat.Inline);
                index++;
            }

            return builder.Build();
        }

        private List<ActionRowComponent> BuildComponents(EmbedState state)
        {
            int totalPlayers = players.Connected.Count();
            bool disableBack = state.Page <= 0;
            bool disableForward = (state.Page + 1) * _pluginConfig.EmbedFieldLimit >= totalPlayers;

            string buttonCmd = BuildCommand(state);

            string backEmoji = Lang(LangKeys.BackButtonEmoji);
            string pageEmoji = Lang(LangKeys.PageButtonEmoji);
            string nextEmoji = Lang(LangKeys.NextButtonEmoji);
            string refreshEmoji = Lang(LangKeys.RefreshButtonEmoji);
            string sortedByEmoji = Lang(LangKeys.SortedByButtonEmoji);
            string sortByText = Lang(state.Sort == SortBy.Name ? LangKeys.SortByEnumName : LangKeys.SortByEnumTime);
            int maxPage = totalPlayers / _pluginConfig.EmbedFieldLimit;
            if (totalPlayers == 0 || totalPlayers % _pluginConfig.EmbedFieldLimit != 0)
            {
                maxPage += 1;
            }

            MessageComponentBuilder builder = new MessageComponentBuilder();
            builder.AddActionButton(ButtonStyle.Primary, Lang(LangKeys.BackButtonLabel), $"{BackCommand} {buttonCmd}", disableBack, false, string.IsNullOrEmpty(backEmoji) ? null : DiscordEmoji.FromCharacter(backEmoji));
            builder.AddActionButton(ButtonStyle.Primary,  Lang(LangKeys.PageButtonLabel, state.Page + 1, maxPage), "PAGE", true, false, string.IsNullOrEmpty(pageEmoji) ? null : DiscordEmoji.FromCharacter(pageEmoji));
            builder.AddActionButton(ButtonStyle.Primary, Lang(LangKeys.NextButtonLabel), $"{ForwardCommand} {buttonCmd}", disableForward, false, string.IsNullOrEmpty(nextEmoji) ? null : DiscordEmoji.FromCharacter(nextEmoji));
            builder.AddActionButton(ButtonStyle.Primary, Lang(LangKeys.RefreshButtonLabel), $"{RefreshCommand} {buttonCmd}", false, false, string.IsNullOrEmpty(refreshEmoji) ? null : DiscordEmoji.FromCharacter(refreshEmoji));
            builder.AddActionButton(ButtonStyle.Primary,  Lang(LangKeys.SortedByButtonLabel, sortByText), $"{ChangeSort} {buttonCmd}", false, false, string.IsNullOrEmpty(sortedByEmoji) ? null : DiscordEmoji.FromCharacter(sortedByEmoji));

            return builder.Build();
        }

        private string BuildCommand(EmbedState state)
        {
            StringBuilder sb = _pool.Get();
            sb.Append(CommandVersion);
            sb.Append(" ");
            sb.Append(state.EmbedCommand);
            sb.Append(" ");
            sb.Append(state.Page);
            sb.Append(" ");
            sb.Append(state.Sort.ToString());
            string buttonCmd = sb.ToString();
            _pool.Free(ref sb);
            return buttonCmd;
        }
        #endregion

        #region Helper Methods
        private const string PluginIcon = "https://assets.umod.org/images/icons/plugin/61354f8bd5faf.png";
        
        private void AddPluginInfoFooter(DiscordEmbedBuilder builder)
        {
            builder.AddFooter($"{Title} V{Version} by {Author}", PluginIcon);
        }

        private object GetDuration(IPlayer player, string _)
        {
            TimeSpan duration = DateTime.UtcNow - _onlineSince[player.Id];
            return Lang(LangKeys.OnlineTimeFormat, duration.Days, duration.Hours, duration.Minutes, duration.Seconds);
        }
        
        private string GetClanTag(IPlayer player)
        {
            string clanTag = Clans?.Call<string>("GetClanOf", player);
            if (!string.IsNullOrEmpty(clanTag))
            {
                return $"[{clanTag}]";
            }

            return string.Empty;
        }

        public T NextEnum<T>(T src, T[] array) where T : struct
        {
            if (!typeof(T).IsEnum) throw new ArgumentException($"Argument {typeof(T).FullName} is not an Enum");
            
            int index = Array.IndexOf(array, src) + 1;
            return array.Length == index ? array[0] : array[index];            
        }
        
        public string Lang(string key)
        {
            return lang.GetMessage(key, this);
        }
        
        public string Lang(string key, params object[] args)
        {
            try
            {
                return string.Format(Lang(key), args);
            }
            catch(Exception ex)
            {
                PrintError($"Lang Key '{key}' threw exception\n:{ex}");
                throw;
            }
        }
        
        public void RegisterDiscordCommand(string name, string method, bool direct, bool guild, List<Snowflake> allowedChannels)
        {
            if (direct)
            {
                _dcCommands.AddDirectMessageCommand(name, this, method);
            }

            if (guild)
            {
                _dcCommands.AddGuildCommand(name, this, allowedChannels, method);
            }
        }
        
        private void SaveData() => Interface.Oxide.DataFileSystem.WriteObject(Name, _pluginData);
        #endregion

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

            [DefaultValue(25)]
            [JsonProperty(PropertyName = "Player Amount Per Page")]
            public int EmbedFieldLimit { get; set; }
            
            [JsonProperty(PropertyName = "Permanent Embeds")]
            public List<PermanentMessageConfig> PermanentMessages { get; set; }
            
            [JsonProperty(PropertyName = "Command Embeds")]
            public Hash<string, EmbedSettings> CommandEmbeds { 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; }
        }
        
        public class PermanentMessageConfig
        {
            [JsonProperty(PropertyName = "Enabled")]
            public bool Enabled { get; set; }
            
            [JsonProperty(PropertyName = "Permanent Message Channel ID")]
            public Snowflake ChannelId { get; set; }

            [JsonProperty(PropertyName = "Update Rate (Minutes)")]
            public float UpdateRate { get; set; }
            
            [JsonProperty(PropertyName = "Command To Use")]
            public string Command { get; set; }

            public PermanentMessageConfig(PermanentMessageConfig settings)
            {
                Enabled = settings?.Enabled ?? false;
                ChannelId = settings?.ChannelId ?? default(Snowflake);
                UpdateRate = settings?.UpdateRate ?? 1f;
                Command = settings?.Command ?? "";
            }
        }

        public class EmbedSettings
        {
            [JsonProperty(PropertyName = "Permissions Needed To Use Command")]
            public CommandPermissions Permissions { get; set; }
            
            [JsonProperty(PropertyName = "Display Setting For The Embed")]
            public EmbedConfig Embed { get; set; }
            
            [JsonProperty(PropertyName = "Display Admins In The Player List")]
            public bool ShowAdmins { get; set; }

            public EmbedSettings(EmbedSettings settings)
            {
                Permissions = new CommandPermissions(settings?.Permissions);
                Embed = new EmbedConfig(settings?.Embed);
                ShowAdmins = settings?.ShowAdmins ?? true;
            }
        }
        
        public class CommandPermissions
        {
            [JsonProperty(PropertyName = "Require Permissions To Use Command")]
            public bool RequirePermissions { get; set; }
            
            [JsonProperty(PropertyName = "Oxide Permission To Use Command")]
            public string OxidePermission { get; set; }
            
            [JsonProperty(PropertyName = "Allow Discord Commands In Direct Messages")]
            public bool AllowInDm { get; set; }
            
            [JsonProperty(PropertyName = "Allow Discord Commands In Guild")]
            public bool AllowInGuild { get; set; }
            
            [JsonProperty(PropertyName = "Allow Guild Commands Only In The Following Guild Channel Or Category (Channel ID Or Category ID)")]
            public List<Snowflake> AllowedChannels { get; set; }
            
            [JsonProperty(PropertyName = "Allow Commands for members having role (Role ID)")]
            public List<Snowflake> AllowedRoles { get; set; }

            public CommandPermissions(CommandPermissions settings)
            {
                RequirePermissions = settings?.RequirePermissions ?? false;
                OxidePermission = settings?.OxidePermission ?? string.Empty;
                AllowInDm = settings?.AllowInDm ?? true;
                AllowInGuild = settings?.AllowInGuild ?? false;
                AllowedChannels = settings?.AllowedChannels ?? new List<Snowflake>();
                AllowedRoles = settings?.AllowedRoles ?? new List<Snowflake>();
            }
        }

        public class PermanentMessageHandler
        {
            public DiscordMessage Message { get; }

            private MessageUpdate Update = new MessageUpdate
            {
                Embeds = new List<DiscordEmbed>()
            };
            public EmbedState State { get; }
            public Timer Timer { get; }

            public PermanentMessageHandler(DiscordMessage message, PermanentMessageConfig config)
            {
                Message = message;
                string customId = ((ButtonComponent)message.Components[0].Components[0]).CustomId;
                State = new EmbedState(customId);
                Timer = _ins.timer.Every(config.UpdateRate * 60f, SendUpdate);
                SendUpdate();
            }

            private void SendUpdate()
            {
                Update.Embeds.Clear();
                Update.Embeds.Add(_ins.BuildEmbed(State));
                Update.Components = _ins.BuildComponents(State);
                Message.Edit(_ins.Client, Update).Catch<ResponseError>(error =>
                {
                    if (error.HttpStatusCode == DiscordHttpStatusCode.NotFound)
                    {
                        Timer?.Destroy();
                    }
                });
            }
        }

        public static class LangKeys
        {
            public const string NoPermission = nameof(NoPermission);
            public const string BackButtonLabel = nameof(BackButtonLabel);
            public const string BackButtonEmoji = nameof(BackButtonEmoji);
            public const string PageButtonLabel = nameof(PageButtonLabel);
            public const string PageButtonEmoji = nameof(PageButtonEmoji);
            public const string NextButtonLabel = nameof(NextButtonLabel);
            public const string NextButtonEmoji = nameof(NextButtonEmoji);
            public const string RefreshButtonLabel = nameof(RefreshButtonLabel);
            public const string RefreshButtonEmoji = nameof(RefreshButtonEmoji);
            public const string SortedByButtonLabel = nameof(SortedByButtonLabel);
            public const string SortedByButtonEmoji = nameof(SortedByButtonEmoji);
            public const string SortByEnumName = nameof(SortByEnumName);
            public const string SortByEnumTime = nameof(SortByEnumTime);
            public const string OnlineTimeFormat = nameof(OnlineTimeFormat);
        }

        public class EmbedConfig
        {
            [JsonProperty("Title")]
            public string Title { get; set; }
            
            [JsonProperty("Description")]
            public string Description { get; set; }
            
            [JsonProperty("Url")]
            public string Url { get; set; }
            
            [JsonProperty("Embed Color (Hex Color Code)")]
            public string Color { get; set; }
            
            [JsonProperty("Image Url")]
            public string Image { get; set; }
            
            [JsonProperty("Thumbnail Url")]
            public string Thumbnail { get; set; }
            
            [JsonProperty("Add Timestamp")]
            public bool Timestamp { get; set; }
            
            [JsonProperty(PropertyName = "Format Applied To Fields")]
            public FieldFormat FieldFormat { get; set; }

            [JsonProperty("Footer")]
            public FooterConfig Footer { get; set; }

            public EmbedConfig(EmbedConfig settings)
            {
                Title = settings?.Title ?? string.Empty;
                Description = settings?.Description ?? string.Empty;
                Url = settings?.Url ?? string.Empty;
                Color = settings?.Color ?? string.Empty;
                Image = settings?.Image ?? string.Empty;
                Thumbnail = settings?.Thumbnail ?? string.Empty;
                Timestamp = settings?.Timestamp ?? true;
                FieldFormat = new FieldFormat(settings?.FieldFormat);
                Footer = new FooterConfig(settings?.Footer);
            }
        }
        
        public class FooterConfig
        {
            [JsonProperty("Icon Url")]
            public string IconUrl { get; set; }
            
            [JsonProperty("Text")]
            public string Text { get; set; }
            
            [JsonProperty("Enabled")]
            public bool Enabled { get; set; }

            public FooterConfig(FooterConfig settings)
            {
                IconUrl = settings?.IconUrl ?? string.Empty;
                Text = settings?.Text ?? string.Empty;
                Enabled = settings?.Enabled ?? true;
            }
        }
        
        public class FieldFormat
        {
            [JsonProperty("Title")]
            public string Title { get; set; }
            
            [JsonProperty("Value")]
            public string Value { get; set; }
            
            [JsonProperty("Inline")]
            public bool Inline { get; set; }

            public FieldFormat(FieldFormat settings)
            {
                Title = settings?.Title ?? string.Empty;
                Value = settings?.Value ?? string.Empty;
                Inline = settings?.Inline ?? true;
            }
        }

        public class PluginData
        {
            public Hash<string, PermanentMessageData> PermanentMessageIds = new Hash<string, PermanentMessageData>();

            public PermanentMessageData GetPermanentMessage(Snowflake channelId, string command)
            {
                return PermanentMessageIds[$"{channelId.ToString()}_{command}"];
            }

            public void SetPermanentMessage(Snowflake channelId, string command, PermanentMessageData data)
            {
                PermanentMessageIds[$"{channelId.ToString()}_{command}"] = data;
            }
        }

        public class PermanentMessageData
        {
            public Snowflake MessageId { get; set; }
        }

        public class EmbedState
        {
            public string InteractionCommand;
            public string Version;
            public string EmbedCommand;
            public int Page;
            public SortBy Sort;
            
            [JsonConstructor]
            public EmbedState()
            {
                
            }
            
            public EmbedState(string customId)
            {
                Update(customId);
            }
            
            public EmbedState(string commandKey, int page, SortBy sort)
            {
                InteractionCommand = string.Empty;
                Version = CommandVersion;
                Update(commandKey, page, sort);
            }

            public void Update(string commandKey, int page, SortBy sort)
            {
                EmbedCommand = commandKey;
                Page = page;
                Sort = sort;
            }
            
            public void Update(string customId)
            {
                try
                {
                    string[] args = customId.Split(' ');
                    InteractionCommand = args[0];
                    Version = args[1];
                    EmbedCommand = args[2];
                    int.TryParse(args[3], out Page);
                    Sort = (SortBy)Enum.Parse(typeof(SortBy), args[4]);
                }
                catch (Exception ex)
                {
                    _ins.PrintError($"Failed to Update Embed With ID: {customId}");
                    throw;
                }
            }
        }

        private class BasePool<T> where T : class
        {
            protected readonly List<T> Pool = new List<T>();
            protected readonly Func<T> Init;

            public BasePool(Func<T> init)
            {
                Init = init;
            }
            
            public virtual T Get()
            {
                if (Pool.Count == 0)
                {
                    return Init.Invoke();
                }

                int index = Pool.Count - 1; //Removing the last element prevents an array copy.T entity = Pool[index];
                Pool.RemoveAt(index);
                
                return entity;
            }

            public virtual void Free(ref T entity)
            {
                Pool.Add(entity);
                entity = null;
            }
        }
        
        private class StringBuilderPool : BasePool<StringBuilder>
        {
            public StringBuilderPool() : base(() => new StringBuilder())
            {
            }
            
            public override void Free(ref StringBuilder sb)
            {
                sb.Length = 0;
                base.Free(ref sb);
            }
        }
        #endregion
        
        #region PlaceholderAPI
        [PluginReference] private Plugin PlaceholderAPI;
        private Action<IPlayer, StringBuilder, bool> _replacer;
        
        private string ParseField(IPlayer player, string field)
        {
            StringBuilder sb = _pool.Get();
            sb.Append(field);
            GetReplacer()?.Invoke(player, sb, false);
            string parsed = sb.ToString();
            _pool.Free(ref sb);
            return parsed;
        }
        
        private void OnPluginUnloaded(Plugin plugin)
        {
            if (plugin?.Name == "PlaceholderAPI")
            {
                _replacer = null;
            }
        }
        
        private void OnPlaceholderAPIReady()
        {
            RegisterPlaceholder("discordplayers.player.duration", GetDuration, "Displays the online duration for a player");
            RegisterPlaceholder("discordplayers.player.clantag", (player, s) => GetClanTag(player), "Displays the players clan tag");
        }
        
        private void RegisterPlaceholder(string key, Func<IPlayer, string, object> action, string description = null)
        {
            if (IsPlaceholderApiLoaded())
            {
                PlaceholderAPI.Call("AddPlaceholder", this, key, action, description);
            }
        }

        private Action<IPlayer, StringBuilder, bool> GetReplacer()
        {
            if (!IsPlaceholderApiLoaded())
            {
                return _replacer;
            }
            
            return _replacer ?? (_replacer = PlaceholderAPI.Call<Action<IPlayer, StringBuilder, bool>>("GetProcessPlaceholders", 1));
        }

        private bool IsPlaceholderApiLoaded() => PlaceholderAPI != null && PlaceholderAPI.IsLoaded;
        #endregion
    }
}

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