Guest User

Discord chat modified

a guest
Jul 10th, 2022
316
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 56.68 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.RegularExpressions;
  7. using Newtonsoft.Json;
  8. using Newtonsoft.Json.Converters;
  9. using Oxide.Core;
  10. using Oxide.Core.Libraries;
  11. using Oxide.Core.Libraries.Covalence;
  12. using Oxide.Core.Plugins;
  13. using Oxide.Ext.Discord;
  14. using Oxide.Ext.Discord.Attributes;
  15. using Oxide.Ext.Discord.Constants;
  16. using Oxide.Ext.Discord.Entities;
  17. using Oxide.Ext.Discord.Entities.Applications;
  18. using Oxide.Ext.Discord.Entities.Channels;
  19. using Oxide.Ext.Discord.Entities.Gatway;
  20. using Oxide.Ext.Discord.Entities.Gatway.Events;
  21. using Oxide.Ext.Discord.Entities.Guilds;
  22. using Oxide.Ext.Discord.Entities.Messages;
  23. using Oxide.Ext.Discord.Entities.Messages.AllowedMentions;
  24. using Oxide.Ext.Discord.Entities.Permissions;
  25. using Oxide.Ext.Discord.Entities.Users;
  26. using Oxide.Ext.Discord.Libraries.Subscription;
  27. using Oxide.Ext.Discord.Logging;
  28. using Oxide.Ext.Discord.Rest;
  29. #if RUST
  30. using ConVar;
  31. #endif
  32.  
  33. // ReSharper disable MemberCanBePrivate.Global
  34. namespace Oxide.Plugins
  35. {
  36. [Info("Discord Chat", "MJSU", "2.1.2")]
  37. [Description("Allows chatting through discord")]
  38. internal class DiscordChat : CovalencePlugin
  39. {
  40. #region Class Fields
  41. [PluginReference]
  42. private Plugin AdminChat, AdminDeepCover, AntiSpam, BetterChat, BetterChatMute, Clans, ChatTranslator, TranslationAPI, UFilter;
  43.  
  44. [DiscordClient]
  45. private DiscordClient _client;
  46.  
  47. private readonly DiscordSettings _discordSettings = new DiscordSettings
  48. {
  49. Intents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages
  50. };
  51.  
  52. private readonly AllowedMention _allowedMention = new AllowedMention
  53. {
  54. AllowedTypes = new List<AllowedMentionTypes>(),
  55. Roles = new List<Snowflake>(),
  56. Users = new List<Snowflake>()
  57. };
  58.  
  59. private DiscordGuild _guild;
  60. private Snowflake _guildId;
  61.  
  62. private readonly DiscordSubscriptions _subscriptions = GetLibrary<DiscordSubscriptions>();
  63.  
  64. private PluginConfig _pluginConfig;
  65.  
  66. private readonly Hash<MessageType, DiscordTimedSend> _sends = new Hash<MessageType, DiscordTimedSend>();
  67.  
  68. private static DiscordChat _ins;
  69.  
  70. public enum MessageType
  71. {
  72. Discord,
  73. Server,
  74. Team,
  75. Cards,
  76. JoinLeave,
  77. AdminChat,
  78. OnlineOffline
  79. }
  80.  
  81. private readonly StringBuilder _name = new StringBuilder();
  82. private readonly StringBuilder _message = new StringBuilder();
  83. private readonly StringBuilder _mentions = new StringBuilder();
  84.  
  85. private readonly Regex _channelMention = new Regex("(<#\\d+>)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
  86.  
  87. private bool _isServerStartup;
  88. #endregion
  89.  
  90. #region Setup & Loading
  91. private void Init()
  92. {
  93. _ins = this;
  94.  
  95. _discordSettings.ApiToken = _pluginConfig.DiscordApiKey;
  96. _discordSettings.LogLevel = _pluginConfig.ExtensionDebugging;
  97. }
  98.  
  99. protected override void LoadDefaultMessages()
  100. {
  101. lang.RegisterMessages(new Dictionary<string, string>
  102. {
  103. [LangKeys.Discord.NotLinkedError] = "You're not allowed to chat with the server unless you are linked.",
  104. [LangKeys.Discord.JoinLeave.ConnectedMessage] = ":white_check_mark: ({0:HH:mm}) **{1}** has joined.",
  105. [LangKeys.Discord.JoinLeave.DisconnectedMessage] = ":x: ({0:HH:mm}) **{1}** has disconnected. ({2})",
  106. [LangKeys.Discord.OnlineOffline.OnlineMessage] = ":green_circle: The server is now online",
  107. [LangKeys.Discord.OnlineOffline.OfflineMessage] = ":red_circle: The server has shutdown",
  108. [LangKeys.Discord.ChatChannel.Message] = ":desktop: ({0:HH:mm}) **{1}**: {2}",
  109. [LangKeys.Discord.ChatChannel.LinkedMessage] = ":speech_left: ({0:HH:mm}) **{1}**: {2}",
  110. [LangKeys.Discord.ChatChannel.UnlinkedMessage] = ":chains: ({0:HH:mm}) **{1}#{2}**: {3}",
  111. [LangKeys.Discord.TeamChannel.Message] = ":busts_in_silhouette: ({0:HH:mm}) **{1}**: {2}",
  112. [LangKeys.Discord.CardsChannel.Message] = ":black_joker: ({0:HH:mm}) **{1}**: {2}",
  113. [LangKeys.Discord.AdminChat.Message] = ":mechanic: ({0:HH:mm}) **{1}**: {2}",
  114. [LangKeys.Discord.AdminChat.Permission] = ":no_entry: You're not allowed to use admin chat channel because you do not have permission.",
  115. [LangKeys.Server.DiscordTag] = "[#5f79d6][Discord][/#]",
  116. [LangKeys.Server.UnlinkedMessage] = "{0} [#5f79d6]{1}#{2}[/#]: {3}",
  117. [LangKeys.Server.LinkedMessage] = "{0} [#5f79d6]{1}[/#]: {2}",
  118. [LangKeys.Server.ClanTag] = "[{0}] "
  119. }, this);
  120.  
  121. lang.RegisterMessages(new Dictionary<string, string>
  122. {
  123. [LangKeys.Discord.NotLinkedError] = "Вам не разрешено писать в чат сервера, если ваши аккаунты не связаны.",
  124. [LangKeys.Discord.JoinLeave.ConnectedMessage] = ":white_check_mark: {0:HH:mm} **{1}** подключился",
  125. [LangKeys.Discord.JoinLeave.DisconnectedMessage] = ":x: {0:HH:mm} **{1}** отключился. Причина: {2}",
  126. [LangKeys.Discord.OnlineOffline.OnlineMessage] = ":green_circle: Выключение сервера",
  127. [LangKeys.Discord.OnlineOffline.OfflineMessage] = ":red_circle: Сервер снова онлайн",
  128. [LangKeys.Discord.ChatChannel.Message] = ":desktop: ({0:HH:mm}) **{1}**: {2}",
  129. [LangKeys.Discord.ChatChannel.LinkedMessage] = ":speech_left: ({0:HH:mm}) **{1}**: {2}",
  130. [LangKeys.Discord.ChatChannel.UnlinkedMessage] = ":chains: ({0:HH:mm}) **{1}#{2}**: {3}",
  131. [LangKeys.Discord.TeamChannel.Message] = ":busts_in_silhouette: ({0:HH:mm}) **{1}**: {2}",
  132. [LangKeys.Discord.CardsChannel.Message] = ":black_joker: ({0:HH:mm}) **{1}**: {2}",
  133. [LangKeys.Discord.AdminChat.Message] = ":mechanic: ({0:HH:mm}) **{1}** {2}",
  134. [LangKeys.Discord.AdminChat.Permission] = "Вам не разрешено использовать канал чата администратора, потому что у вас нет разрешения.",
  135. [LangKeys.Server.DiscordTag] = "[#5f79d6][Discord][/#]",
  136. [LangKeys.Server.UnlinkedMessage] = "{0} [#5f79d6]{1}#{2}[/#]: {3}",
  137. [LangKeys.Server.LinkedMessage] = "{0} [#5f79d6]{1}[/#]: {2}",
  138. [LangKeys.Server.ClanTag] = "[{0}] "
  139. }, this, "ru");
  140. }
  141.  
  142. protected override void LoadDefaultConfig()
  143. {
  144. PrintWarning("Loading Default Config");
  145. }
  146.  
  147. protected override void LoadConfig()
  148. {
  149. base.LoadConfig();
  150. _pluginConfig = AdditionalConfig(Config.ReadObject<PluginConfig>());
  151. Config.WriteObject(_pluginConfig);
  152. }
  153.  
  154. private PluginConfig AdditionalConfig(PluginConfig config)
  155. {
  156. config.ChannelSettings = new ChannelSettings(config.ChannelSettings);
  157. config.MessageSettings = new MessageSettings(config.MessageSettings);
  158. config.PluginSupport = new PluginSupport(config.PluginSupport);
  159. return config;
  160. }
  161.  
  162. private void OnServerInitialized(bool startup)
  163. {
  164. _isServerStartup = startup;
  165. if (IsPluginLoaded(BetterChat))
  166. {
  167. if (BetterChat.Version < new VersionNumber(5, 2, 7))
  168. {
  169. PrintWarning("Please update your version of BetterChat to version >= 5.2.7");
  170. }
  171.  
  172. if (_pluginConfig.EnableServerChatTag)
  173. {
  174. BetterChat.Call("API_RegisterThirdPartyTitle", this, new Func<IPlayer, string>(GetBetterChatTag));
  175. }
  176. }
  177.  
  178. if (_pluginConfig.PluginSupport.AntiSpam.ValidateNicknames
  179. || _pluginConfig.PluginSupport.AntiSpam.ServerMessage
  180. || _pluginConfig.PluginSupport.AntiSpam.DiscordMessage
  181. #if RUST
  182. || _pluginConfig.PluginSupport.AntiSpam.TeamMessage
  183. #endif
  184. )
  185. {
  186. if (AntiSpam == null)
  187. {
  188. PrintWarning("AntiSpam is enabled in the config but is not loaded. " +
  189. "Please disable the setting in the config or load AntiSpam: https://umod.org/plugins/anti-spam");
  190. return;
  191. }
  192.  
  193. if (AntiSpam.Version < new VersionNumber(2, 0, 0))
  194. {
  195. PrintError("AntiSpam plugin must be version 2.0.0 or higher");
  196. }
  197. }
  198.  
  199. if (string.IsNullOrEmpty(_pluginConfig.DiscordApiKey))
  200. {
  201. PrintWarning("Please set the Discord Bot Token and reload the plugin");
  202. return;
  203. }
  204.  
  205. _client.Connect(_discordSettings);
  206.  
  207. if (!_pluginConfig.ChannelSettings.ChatChannel.IsValid()
  208. #if RUST
  209. && !_pluginConfig.ChannelSettings.TeamChannel.IsValid()
  210. && !_pluginConfig.ChannelSettings.CardsChannel.IsValid()
  211. #endif
  212. )
  213. {
  214. #if RUST
  215. Unsubscribe(nameof(OnPlayerChat));
  216. #else
  217. Unsubscribe(nameof(OnUserChat));
  218. #endif
  219. }
  220.  
  221. if (!_pluginConfig.ChannelSettings.JoinLeaveChannel.IsValid())
  222. {
  223. Unsubscribe(nameof(OnUserConnected));
  224. Unsubscribe(nameof(OnUserDisconnected));
  225. }
  226.  
  227. if (!_pluginConfig.ChannelSettings.OnlineOfflineChannel.IsValid())
  228. {
  229. Unsubscribe(nameof(OnServerShutdown));
  230. }
  231. }
  232.  
  233. private void OnServerShutdown()
  234. {
  235. string message = JsonConvert.SerializeObject(new MessageCreate { Content = Lang(LangKeys.Discord.OnlineOffline.OfflineMessage) }, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
  236. webrequest.Enqueue( $"{Request.UrlBase}/{Request.ApiVersion}/channels/{_pluginConfig.ChannelSettings.OnlineOfflineChannel.ToString()}/messages",
  237. message,
  238. (i, s) => { },
  239. null,
  240. RequestMethod.POST,
  241. new Dictionary<string, string> { ["Authorization"] = $"Bot {_pluginConfig.DiscordApiKey}", ["Content-Type"] = "application/json" });
  242. }
  243.  
  244. private void Unload()
  245. {
  246. _ins = null;
  247. }
  248. #endregion
  249.  
  250. #region Discord Setup
  251. [HookMethod(DiscordExtHooks.OnDiscordGatewayReady)]
  252. private void OnDiscordGatewayReady(GatewayReadyEvent ready)
  253. {
  254. if (ready.Guilds.Count == 0)
  255. {
  256. PrintError("Your bot was not found in any discord servers. Please invite it to a server and reload the plugin.");
  257. return;
  258. }
  259.  
  260. DiscordGuild guild = null;
  261. if (ready.Guilds.Count == 1 && !_pluginConfig.GuildId.IsValid())
  262. {
  263. guild = ready.Guilds.Values.FirstOrDefault();
  264. }
  265.  
  266. if (guild == null)
  267. {
  268. guild = ready.Guilds[_pluginConfig.GuildId];
  269. if (guild == null)
  270. {
  271. PrintError("Failed to find a matching guild for the Discord Server Id. " +
  272. "Please make sure your guild Id is correct and the bot is in the discord server.");
  273. return;
  274. }
  275. }
  276.  
  277. DiscordApplication app = _client.Bot.Application;
  278. if (!app.HasApplicationFlag(ApplicationFlags.GatewayMessageContentLimited) && !app.HasApplicationFlag(ApplicationFlags.GatewayMessageContent))
  279. {
  280. PrintWarning($"You will need to enable \"Message Content Intent\" for {_client.Bot.BotUser.Username} @ https://discord.com/developers/applications\n by April 2022" +
  281. $"{Name} will stop function correctly after that date until that is fixed. Once updated please reload {Name}.");
  282. }
  283.  
  284. _guildId = guild.Id;
  285. Puts($"{Title} Ready");
  286. }
  287.  
  288. [HookMethod(DiscordExtHooks.OnDiscordGuildCreated)]
  289. private void OnDiscordGuildCreated(DiscordGuild guild)
  290. {
  291. if (guild.Id != _guildId)
  292. {
  293. return;
  294. }
  295.  
  296. _guild = guild;
  297. if (_pluginConfig.MessageSettings.DiscordToServer)
  298. {
  299. SetupChannel(MessageType.Server, _pluginConfig.ChannelSettings.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay, HandleDiscordChatMessage);
  300. }
  301. else
  302. {
  303. SetupChannel(MessageType.Server, _pluginConfig.ChannelSettings.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay);
  304. }
  305.  
  306. SetupChannel(MessageType.JoinLeave, _pluginConfig.ChannelSettings.JoinLeaveChannel, false);
  307. SetupChannel(MessageType.OnlineOffline, _pluginConfig.ChannelSettings.OnlineOfflineChannel, false);
  308. SetupChannel(MessageType.AdminChat, _pluginConfig.PluginSupport.AdminChat.ChatChannel, _pluginConfig.MessageSettings.UseBotMessageDisplay, HandleAdminChatDiscordMessage);
  309.  
  310. #if RUST
  311. SetupChannel(MessageType.Team, _pluginConfig.ChannelSettings.TeamChannel, false);
  312. SetupChannel(MessageType.Cards, _pluginConfig.ChannelSettings.CardsChannel, false);
  313. #endif
  314.  
  315. if (_isServerStartup)
  316. {
  317. _sends[MessageType.OnlineOffline]?.QueueMessage(Lang(LangKeys.Discord.OnlineOffline.OnlineMessage));
  318. }
  319. }
  320.  
  321. public void SetupChannel(MessageType messageChannel, Snowflake id, bool wipeNonBotMessages, Action<DiscordMessage> message = null)
  322. {
  323. if (!id.IsValid())
  324. {
  325. return;
  326. }
  327.  
  328. DiscordChannel channel = _guild.Channels[id];
  329. if (channel == null)
  330. {
  331. PrintWarning($"Channel with ID: '{id}' not found in guild");
  332. return;
  333. }
  334.  
  335. if (message != null)
  336. {
  337. _subscriptions.AddChannelSubscription(this, id, message);
  338. }
  339.  
  340. if (wipeNonBotMessages)
  341. {
  342. channel.GetChannelMessages(_client, new ChannelMessagesRequest{Limit = 100}, messages => OnGetChannelMessages(messages, channel));
  343. }
  344.  
  345. _sends[messageChannel] = new DiscordTimedSend(id);
  346. }
  347.  
  348. private void OnGetChannelMessages(List<DiscordMessage> messages, DiscordChannel channel)
  349. {
  350. if (messages.Count == 0)
  351. {
  352. return;
  353. }
  354.  
  355. DiscordMessage[] messagesToDelete = messages
  356. .Where(m => !ShouldIgnoreDiscordUser(m.Author))
  357. .ToArray();
  358.  
  359. if (messagesToDelete.Length == 0)
  360. {
  361. return;
  362. }
  363.  
  364. if (messagesToDelete.Length == 1)
  365. {
  366. messagesToDelete[0]?.DeleteMessage(_client);
  367. return;
  368. }
  369.  
  370. channel.BulkDeleteMessages(_client, messagesToDelete.Take(100).Select(m => m.Id).ToArray());
  371. }
  372. #endregion
  373.  
  374. #region Oxide Chat Hooks
  375. #if RUST
  376. private void OnPlayerChat(BasePlayer rustPlayer, string message, Chat.ChatChannel chatChannel)
  377. {
  378. IPlayer player = rustPlayer.IPlayer;
  379. int channel = (int)chatChannel;
  380.  
  381. #else
  382. private void OnUserChat(IPlayer player, string message)
  383. {
  384. int channel = 0;
  385. #endif
  386.  
  387. if (channel == 0 && !_pluginConfig.MessageSettings.ServerToDiscord)
  388. {
  389. return;
  390. }
  391.  
  392. //Ignore Admin Chat Messages
  393. //Processed by OnAdminChat Hook
  394. if (IsAdminChatMessage(player, message))
  395. {
  396. return;
  397. }
  398.  
  399. MessageType type = GetMessageType(message, channel, player);
  400. //Check if type is enabled
  401. if (!_sends.ContainsKey(type))
  402. {
  403. return;
  404. }
  405.  
  406. if (IsInAdminDeepCover(player, type))
  407. {
  408. return;
  409. }
  410.  
  411. GetMessage(message, type, newMessage => { _sends[type]?.QueueMessage(FormatServerMessage(player, type, newMessage.ToString())); });
  412. }
  413.  
  414. private MessageType GetMessageType(string message, int channel, IPlayer player)
  415. {
  416. switch (channel)
  417. {
  418. case 1:
  419. return MessageType.Team;
  420. case 3:
  421. return MessageType.Cards;
  422. default:
  423. return IsAdminChatMessage(player, message) ? MessageType.AdminChat : MessageType.Server;
  424. }
  425. }
  426. #endregion
  427.  
  428. #region Discord Hooks
  429. public void HandleDiscordChatMessage(DiscordMessage message)
  430. {
  431. if (ShouldIgnoreDiscordUser(message.Author))
  432. {
  433. return;
  434. }
  435.  
  436. if (ShouldIgnorePrefix(message.Content))
  437. {
  438. return;
  439. }
  440.  
  441. IPlayer player = message.Author.Player;
  442. if (Interface.Oxide.CallHook("OnDiscordChatMessage", player, message.Content, message.Author) != null)
  443. {
  444. return;
  445. }
  446.  
  447. if (player != null && IsBetterChatMuted(player))
  448. {
  449. if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
  450. {
  451. timer.In(.25f, () =>
  452. {
  453. message.DeleteMessage(_client);
  454. });
  455. }
  456. return;
  457. }
  458.  
  459. ProcessMentions(message);
  460. GetMessage(message.Content, MessageType.Discord, sb =>
  461. {
  462. if (player == null)
  463. {
  464. if (!IsUnlinkedBlocked(message))
  465. {
  466. HandleUnlinkedMessage(message, sb);
  467. }
  468. }
  469. else
  470. {
  471. HandleLinkedMessage(player, sb, message);
  472. }
  473. });
  474. }
  475.  
  476. public void HandleLinkedMessage(IPlayer player, StringBuilder sb, DiscordMessage discordMessage)
  477. {
  478. string message = sb.ToString();
  479. if (string.IsNullOrEmpty(message) || message.Trim().Length == 0)
  480. {
  481. discordMessage.DeleteMessage(_client);
  482. return;
  483. }
  484.  
  485. if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
  486. {
  487. _sends[MessageType.Server].QueueMessage(FormatServerMessage(player, MessageType.Discord, message));
  488. discordMessage.DeleteMessage(_client);
  489. }
  490.  
  491. if (_pluginConfig.MessageSettings.AllowPluginProcessing)
  492. {
  493. bool playerReturn = false;
  494. #if RUST
  495. //Let other chat plugins process first
  496. if (player.Object != null)
  497. {
  498. Unsubscribe(nameof(OnPlayerChat));
  499. playerReturn = Interface.Call(nameof(OnPlayerChat), player.Object, message, Chat.ChatChannel.Global) != null;
  500. Subscribe(nameof(OnPlayerChat));
  501. }
  502. #endif
  503.  
  504. //Let other chat plugins process first
  505. Unsubscribe("OnUserChat");
  506. bool userReturn = Interface.Call("OnUserChat", player, message) != null;
  507. Subscribe("OnUserChat");
  508.  
  509. if (playerReturn || userReturn)
  510. {
  511. return;
  512. }
  513.  
  514. if (SendBetterChatMessage(player, message))
  515. {
  516. return;
  517. }
  518. }
  519.  
  520. string discordTag = string.Empty;
  521. if (_pluginConfig.EnableServerChatTag)
  522. {
  523. discordTag = Lang(LangKeys.Server.DiscordTag, player);
  524. }
  525.  
  526. message = Lang(LangKeys.Server.LinkedMessage, player, discordTag, player.Name, message);
  527. server.Broadcast(message);
  528. Puts(Formatter.ToPlaintext(message));
  529. }
  530.  
  531. public void HandleUnlinkedMessage(DiscordMessage discordMessage, StringBuilder sb)
  532. {
  533. string message = sb.ToString();
  534. if (string.IsNullOrEmpty(message) || message.Trim().Length == 0)
  535. {
  536. discordMessage.DeleteMessage(_client);
  537. return;
  538. }
  539.  
  540. if (_pluginConfig.MessageSettings.UseBotMessageDisplay)
  541. {
  542. _sends[MessageType.Server].QueueMessage(Lang(LangKeys.Discord.ChatChannel.UnlinkedMessage, null, GetServerTime(), discordMessage.Author.Username, discordMessage.Author.Discriminator, message));
  543. discordMessage.DeleteMessage(_client);
  544. }
  545.  
  546. string name = _guild.Members[discordMessage.Author.Id]?.DisplayName ?? discordMessage.Author.Username;
  547.  
  548. string serverMessage = Lang(LangKeys.Server.UnlinkedMessage, null, Lang(LangKeys.Server.DiscordTag), name, discordMessage.Author.Discriminator, message);
  549. server.Broadcast(serverMessage);
  550. Puts(Formatter.ToPlaintext(serverMessage));
  551. }
  552. #endregion
  553.  
  554. #region Join Leave Handling
  555. private void OnUserConnected(IPlayer player)
  556. {
  557. _sends[MessageType.JoinLeave].QueueMessage(Lang(LangKeys.Discord.JoinLeave.ConnectedMessage, player, GetServerTime(), GetPlayerName(player), player.Id));
  558. }
  559.  
  560. private void OnUserDisconnected(IPlayer player, string reason)
  561. {
  562. _sends[MessageType.JoinLeave].QueueMessage(Lang(LangKeys.Discord.JoinLeave.DisconnectedMessage, player, GetServerTime(), GetPlayerName(player), reason, player.Id));
  563. }
  564. #endregion
  565.  
  566. #region Plugin Support
  567. #region AdminDeepCover
  568. public bool IsInAdminDeepCover(IPlayer player, MessageType type)
  569. {
  570. return IsPluginLoaded(AdminDeepCover)
  571. && player.Object != null
  572. && (type == MessageType.Server || type == MessageType.Discord)
  573. && AdminDeepCover.Call<bool>("API_IsDeepCovered", player.Object);
  574. }
  575. #endregion
  576.  
  577. #region AdminChat
  578. private const string AdminChatPermission = "adminchat.use";
  579.  
  580. public bool IsAdminChatEnabled() => IsPluginLoaded(AdminChat) && _pluginConfig.PluginSupport.AdminChat.Enabled && _sends.ContainsKey(MessageType.AdminChat);
  581. public bool CanPlayerAdminChat(IPlayer player) => IsAdminChatEnabled() && player.HasPermission(AdminChatPermission);
  582. public bool IsAdminChatMessage(IPlayer player, string message) => CanPlayerAdminChat(player) && (message.StartsWith(_pluginConfig.PluginSupport.AdminChat.AdminChatPrefix) || AdminChat.Call<bool>("HasAdminChatEnabled", player));
  583.  
  584. //Hook called from AdminChat Plugin
  585. [HookMethod(nameof(OnAdminChat))]
  586. public void OnAdminChat(IPlayer player, string message, bool fromDiscord)
  587. {
  588. if (IsAdminChatEnabled())
  589. {
  590. if(fromDiscord){return;}
  591. _sends[MessageType.AdminChat].QueueMessage(Lang(LangKeys.Discord.AdminChat.Message, player, GetServerTime(), player.Name, message));
  592. }
  593. }
  594.  
  595. //If this is an admin chat message from the server ignore it as we use hook to process.
  596. public bool HandledAdminChatServerMessage(IPlayer player, string message)
  597. {
  598. return IsAdminChatMessage(player, message);
  599. }
  600.  
  601. //Message sent in admin chat channel. Process bot replace and sending to server
  602. public void HandleAdminChatDiscordMessage(DiscordMessage message)
  603. {
  604. AdminChatSettings settings = _pluginConfig.PluginSupport.AdminChat;
  605.  
  606. IPlayer player = message.Author.Player;
  607. if (player == null)
  608. {
  609. message.Reply(_client, Lang(LangKeys.Discord.NotLinkedError));
  610. return;
  611. }
  612.  
  613. if (!CanPlayerAdminChat(player))
  614. {
  615. message.Reply(_client, Lang(LangKeys.Discord.AdminChat.Permission, player));
  616. return;
  617. }
  618.  
  619. if (settings.ReplaceWithBot)
  620. {
  621. timer.In(.25f, () => { message.DeleteMessage(_client); });
  622.  
  623. _sends[MessageType.AdminChat].QueueMessage(Lang(LangKeys.Discord.AdminChat.Message, player, GetServerTime(), player.Name, message.Content));
  624. }
  625.  
  626. AdminChat.Call("SendAdminMessage", player, message.Content, true);
  627. }
  628. #endregion
  629.  
  630. #region AntiSpam
  631. public bool AntiSpamLoaded() => AntiSpam != null && AntiSpam.IsLoaded;
  632. public bool CanAntiSpamPlayerNames() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.ValidateNicknames;
  633. public bool CanAntiSpamGlobalMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.ServerMessage;
  634. public bool CanAntiSpamDiscordMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.DiscordMessage;
  635. #if RUST
  636. public bool CanAntiSpamTeamMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.TeamMessage;
  637. public bool CanAntiSpamCardsMessage() => AntiSpamLoaded() && _pluginConfig.PluginSupport.AntiSpam.CardMessages;
  638. #endif
  639. public bool CanAntiSpam(MessageType type)
  640. {
  641. switch (type)
  642. {
  643. case MessageType.Server:
  644. return CanAntiSpamGlobalMessage();
  645.  
  646. case MessageType.Discord:
  647. return CanAntiSpamDiscordMessage();
  648.  
  649. #if RUST
  650. case MessageType.Team:
  651. return CanAntiSpamTeamMessage();
  652.  
  653. case MessageType.Cards:
  654. return CanAntiSpamCardsMessage();
  655. #endif
  656. }
  657.  
  658. return false;
  659. }
  660.  
  661. public void ProcessMessageAntiSpam(StringBuilder message, MessageType type)
  662. {
  663. if (CanAntiSpam(type))
  664. {
  665. string clearMessage = AntiSpam.Call<string>("GetSpamFreeText", message.ToString());
  666. message.Length = 0;
  667. message.Append(clearMessage);
  668. }
  669. }
  670.  
  671. public void ProcessNameAntiSpam(IPlayer player, StringBuilder sb)
  672. {
  673. if (CanAntiSpamPlayerNames())
  674. {
  675. sb.Length = 0;
  676. sb.Append(AntiSpam.Call<string>("GetClearName", player));
  677. }
  678. }
  679. #endregion
  680.  
  681. #region BetterChat
  682. public bool CanBetterChat() => IsPluginLoaded(BetterChat);
  683.  
  684. public bool SendBetterChatMessage(IPlayer player, string message)
  685. {
  686. if (CanBetterChat())
  687. {
  688. Dictionary<string, object> data = BetterChat.Call<Dictionary<string, object>>("API_GetMessageData", player, message);
  689. BetterChat.Call("API_SendMessage", data);
  690. return true;
  691. }
  692.  
  693. return false;
  694. }
  695.  
  696. public void GetBetterChatMessage(IPlayer player, string message, out string playerInfo, out string messageInfo)
  697. {
  698. string bcMessage = GetBetterChatConsoleMessage(player, message);
  699. int index = bcMessage.IndexOf(':');
  700.  
  701. if (index != -1)
  702. {
  703. playerInfo = bcMessage.Substring(0, index);
  704. messageInfo = bcMessage.Substring(index + 2);
  705. }
  706. else
  707. {
  708. playerInfo = string.Empty;
  709. messageInfo = bcMessage;
  710. }
  711. }
  712.  
  713. public string GetBetterChatConsoleMessage(IPlayer player, string message)
  714. {
  715. return BetterChat.Call<string>("API_GetFormattedMessage", player, message, true);
  716. }
  717.  
  718. public string GetBetterChatTag(IPlayer player)
  719. {
  720. return player.IsConnected ? null : Lang(LangKeys.Server.DiscordTag, player);
  721. }
  722. #endregion
  723.  
  724. #region BetterChatMute
  725. public bool IsBetterChatMuted(IPlayer player) => IsPluginLoaded(BetterChatMute) && _pluginConfig.PluginSupport.BetterChatMuteSettings.IgnoreMuted && BetterChatMute.Call<bool>("API_IsMuted", player);
  726. #endregion
  727.  
  728. #region Clans
  729. public void ProcessClanName(StringBuilder name, IPlayer player)
  730. {
  731. if (!_pluginConfig.PluginSupport.Clans.ShowClanTag || !IsPluginLoaded(Clans))
  732. {
  733. return;
  734. }
  735.  
  736. string clanTag = Clans.Call<string>("GetClanOf", player.Id);
  737. if (!string.IsNullOrEmpty(clanTag))
  738. {
  739. name.Insert(0, Lang(LangKeys.Server.ClanTag, player, clanTag));
  740. }
  741. }
  742. #endregion
  743.  
  744. #region Translation API
  745. public bool CanChatTranslator() => IsPluginLoaded(ChatTranslator) && _pluginConfig.PluginSupport.ChatTranslator.Enabled;
  746.  
  747. public bool CanChatTranslatorGlobalMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.ServerMessage;
  748. public bool CanChatTranslatorDiscordMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.DiscordMessage;
  749. #if RUST
  750. public bool CanChatTranslatorTeamMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.TeamMessage;
  751. public bool CanChatTranslatorCardsMessage() => CanChatTranslator() && _pluginConfig.PluginSupport.ChatTranslator.CardMessages;
  752. #endif
  753.  
  754. public bool CanChatTranslatorSource(MessageType type)
  755. {
  756. switch (type)
  757. {
  758. case MessageType.Server:
  759. return CanChatTranslatorGlobalMessage();
  760.  
  761. case MessageType.Discord:
  762. return CanChatTranslatorDiscordMessage();
  763.  
  764. #if RUST
  765. case MessageType.Team:
  766. return CanChatTranslatorTeamMessage();
  767.  
  768. case MessageType.Cards:
  769. return CanChatTranslatorCardsMessage();
  770. #endif
  771. }
  772.  
  773. return false;
  774. }
  775.  
  776. public void TranslateMessage(string message, MessageType type, Action<StringBuilder> callback)
  777. {
  778. if (CanChatTranslatorSource(type))
  779. {
  780. TranslationAPI.Call("Translate", message, _pluginConfig.PluginSupport.ChatTranslator.DiscordServerLanguage, "auto", new Action<string>(translatedText =>
  781. {
  782. _message.Length = 0;
  783. _message.Append(message);
  784. callback.Invoke(_message);
  785. }));
  786. }
  787.  
  788. _message.Length = 0;
  789. _message.Append(message);
  790. callback.Invoke(_message);
  791. }
  792. #endregion
  793.  
  794. #region UFilter
  795. public bool IsUFilterLoaded() => UFilter != null && UFilter.IsLoaded;
  796. public bool CanUFilterPlayerNames() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.ValidateNicknames;
  797. public bool CanUFilterGlobalMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.GlobalMessage;
  798. public bool CanUFilterDiscordMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.DiscordMessages;
  799. #if RUST
  800. public bool CanUFilterTeamMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.TeamMessage;
  801. public bool CanUFilterCardMessage() => IsUFilterLoaded() && _pluginConfig.PluginSupport.UFilter.CardMessage;
  802. #endif
  803.  
  804. public bool CanUFilter(MessageType type)
  805. {
  806. switch (type)
  807. {
  808. case MessageType.Server:
  809. return CanUFilterGlobalMessage();
  810.  
  811. case MessageType.Discord:
  812. return CanUFilterDiscordMessage();
  813.  
  814. #if RUST
  815. case MessageType.Team:
  816. return CanUFilterTeamMessage();
  817.  
  818. case MessageType.Cards:
  819. return CanUFilterCardMessage();
  820. #endif
  821. }
  822.  
  823. return false;
  824. }
  825.  
  826. public void ProcessMessageUFilter(StringBuilder text, MessageType type)
  827. {
  828. if (CanUFilter(type))
  829. {
  830. UFilterText(text);
  831. }
  832. }
  833.  
  834. public void ProcessNameUFilter(StringBuilder name)
  835. {
  836. if (CanUFilterPlayerNames())
  837. {
  838. UFilterText(name);
  839. }
  840. }
  841.  
  842. public void UFilterText(StringBuilder text)
  843. {
  844. string[] profanities = UFilter.Call<string[]>("Profanities", text.ToString());
  845. if (profanities.Length == 0)
  846. {
  847. return;
  848. }
  849.  
  850. foreach (string profanity in profanities)
  851. {
  852. text.Replace(profanity, new string('*', profanity.Length));
  853. }
  854. }
  855. #endregion
  856. #endregion
  857.  
  858. #region Helpers
  859. private DateTime GetServerTime()
  860. {
  861. return DateTime.Now + TimeSpan.FromHours(_pluginConfig.MessageSettings.ServerTimeOffset);
  862. }
  863.  
  864. private void ProcessTextReplacements(StringBuilder message)
  865. {
  866. foreach (KeyValuePair<string, string> replacement in _pluginConfig.MessageSettings.TextReplacements)
  867. {
  868. message.Replace(replacement.Key, replacement.Value);
  869. }
  870. }
  871.  
  872. private void SendMessageToChannel(Snowflake channelId, StringBuilder message)
  873. {
  874. DiscordMessage.CreateMessage(_client, channelId, new MessageCreate
  875. {
  876. Content = message.ToString(),
  877. AllowedMention = _allowedMention
  878. });
  879. }
  880.  
  881. public string GetPlayerName(IPlayer player)
  882. {
  883. _name.Length = 0;
  884. _name.Append(player.Name);
  885. ProcessNameAntiSpam(player, _name);
  886. ProcessNameUFilter(_name);
  887. ProcessClanName(_name, player);
  888.  
  889. return _name.ToString();
  890. }
  891.  
  892. private void ProcessMentions(DiscordMessage message)
  893. {
  894. _mentions.Length = 0;
  895. _mentions.Append(message.Content);
  896.  
  897. bool changed = false;
  898. if (message.Mentions != null)
  899. {
  900. foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions)
  901. {
  902. _mentions.Replace($"<@{mention.Key.ToString()}>", $"@{mention.Value.Username}");
  903. changed = true;
  904. }
  905.  
  906. foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions)
  907. {
  908. GuildMember member = _guild.Members[mention.Key];
  909. _mentions.Replace($"<@!{mention.Key.ToString()}>", $"@{member?.Nickname ?? mention.Value.Username}");
  910. changed = true;
  911. }
  912. }
  913.  
  914. if (message.MentionsChannels != null)
  915. {
  916. foreach (KeyValuePair<Snowflake, ChannelMention> mention in message.MentionsChannels)
  917. {
  918. _mentions.Replace($"<#{mention.Key.ToString()}>", $"#{mention.Value.Name}");
  919. changed = true;
  920. }
  921. }
  922.  
  923. foreach (Match match in _channelMention.Matches(message.Content))
  924. {
  925. string value = match.Value;
  926. Snowflake id = new Snowflake(value.Substring(2, value.Length - 3));
  927. DiscordChannel channel = _guild.Channels[id];
  928. if (channel != null)
  929. {
  930. _mentions.Replace(value, $"#{channel.Name}");
  931. }
  932.  
  933. changed = true;
  934. }
  935.  
  936. if (message.MentionRoles != null)
  937. {
  938. foreach (Snowflake roleId in message.MentionRoles)
  939. {
  940. DiscordRole role = _guild.Roles[roleId];
  941. _mentions.Replace($"<@&{roleId.ToString()}>", $"@{role.Name ?? roleId}");
  942. changed = true;
  943. }
  944. }
  945.  
  946. if (changed)
  947. {
  948. message.Content = _mentions.ToString();
  949. }
  950. }
  951.  
  952. public void GetMessage(string message, MessageType type, Action<StringBuilder> callback)
  953. {
  954. TranslateMessage(message, type, sb =>
  955. {
  956. ProcessTextReplacements(sb);
  957. ProcessMessageUFilter(sb, type);
  958. ProcessMessageAntiSpam(sb, type);
  959.  
  960. callback.Invoke(sb);
  961. });
  962. }
  963.  
  964. private bool IsUnlinkedBlocked(DiscordMessage message)
  965. {
  966. if (!_pluginConfig.MessageSettings.UnlinkedSettings.AllowedUnlinked)
  967. {
  968. message.Reply(_client, Lang(LangKeys.Discord.NotLinkedError), newMessage => { timer.In(5f, () => { newMessage.DeleteMessage(_client); }); });
  969.  
  970. return true;
  971. }
  972.  
  973. return false;
  974. }
  975.  
  976. public string FormatServerMessage(IPlayer player, MessageType type, string message)
  977. {
  978. string format;
  979. switch (type)
  980. {
  981. case MessageType.Server:
  982. format = LangKeys.Discord.ChatChannel.Message;
  983. break;
  984.  
  985. case MessageType.Team:
  986. format = LangKeys.Discord.TeamChannel.Message;
  987. break;
  988.  
  989. case MessageType.Cards:
  990. format = LangKeys.Discord.CardsChannel.Message;
  991. break;
  992.  
  993. case MessageType.AdminChat:
  994. format = LangKeys.Discord.AdminChat.Message;
  995. break;
  996.  
  997. case MessageType.Discord:
  998. format = LangKeys.Discord.ChatChannel.LinkedMessage;
  999. break;
  1000.  
  1001. default:
  1002. return message;
  1003. }
  1004.  
  1005. string playerName;
  1006.  
  1007. if (_pluginConfig.MessageSettings.AllowPluginProcessing && type != MessageType.AdminChat && CanBetterChat())
  1008. {
  1009. GetBetterChatMessage(player, message, out playerName, out message);
  1010. }
  1011. else
  1012. {
  1013. playerName = GetPlayerName(player);
  1014. }
  1015.  
  1016. return Lang(format, player, GetServerTime(), playerName, message);
  1017. }
  1018.  
  1019. public bool ShouldIgnoreDiscordUser(DiscordUser user)
  1020. {
  1021. if (user.Bot ?? false)
  1022. {
  1023. return true;
  1024. }
  1025.  
  1026. MessageFilterSettings filter = _pluginConfig.MessageSettings.Filter;
  1027. if (filter.IgnoreUsers.Contains(user.Id))
  1028. {
  1029. return true;
  1030. }
  1031.  
  1032. GuildMember member = _guild.Members[user.Id];
  1033. if (member != null)
  1034. {
  1035. foreach (Snowflake role in filter.IgnoreRoles)
  1036. {
  1037. if (member.Roles.Contains(role))
  1038. {
  1039. return true;
  1040. }
  1041. }
  1042. }
  1043.  
  1044. return false;
  1045. }
  1046.  
  1047. public bool ShouldIgnorePrefix(string message)
  1048. {
  1049. for (int index = 0; index < _pluginConfig.MessageSettings.Filter.IgnoredPrefixes.Count; index++)
  1050. {
  1051. string prefix = _pluginConfig.MessageSettings.Filter.IgnoredPrefixes[index];
  1052. if (message.StartsWith(prefix))
  1053. {
  1054. return true;
  1055. }
  1056. }
  1057.  
  1058. return false;
  1059. }
  1060.  
  1061. public bool IsPluginLoaded(Plugin plugin) => plugin != null && plugin.IsLoaded;
  1062.  
  1063. public string Lang(string key, IPlayer player = null)
  1064. {
  1065. return lang.GetMessage(key, this, player?.Id);
  1066. }
  1067.  
  1068. public string Lang(string key, IPlayer player = null, params object[] args)
  1069. {
  1070. string lang = Lang(key, player);
  1071. try
  1072. {
  1073. return string.Format(lang, args);
  1074. }
  1075. catch (Exception ex)
  1076. {
  1077. PrintError($"Lang Key '{key}'\nMessage:{lang}\nException:{ex}");
  1078. throw;
  1079. }
  1080. }
  1081. #endregion
  1082.  
  1083. #region Classes
  1084. public class PluginConfig
  1085. {
  1086. [JsonProperty(PropertyName = "Discord Bot Token")]
  1087. public string DiscordApiKey { get; set; } = string.Empty;
  1088.  
  1089. [JsonProperty(PropertyName = "Discord Server ID (Optional if bot only in 1 guild)")]
  1090. public Snowflake GuildId { get; set; }
  1091.  
  1092. [DefaultValue(true)]
  1093. [JsonProperty("Enable Adding Discord Tag To In Game Messages When Sent From Discord")]
  1094. public bool EnableServerChatTag { get; set; } = true;
  1095.  
  1096. [JsonProperty("Channel Settings")]
  1097. public ChannelSettings ChannelSettings { get; set; }
  1098.  
  1099. [JsonProperty("Message Settings")]
  1100. public MessageSettings MessageSettings { get; set; }
  1101.  
  1102. [JsonProperty("Plugin Support")]
  1103. public PluginSupport PluginSupport { get; set; }
  1104.  
  1105. [JsonConverter(typeof(StringEnumConverter))]
  1106. [DefaultValue(DiscordLogLevel.Info)]
  1107. [JsonProperty(PropertyName = "Discord Extension Log Level (Verbose, Debug, Info, Warning, Error, Exception, Off)")]
  1108. public DiscordLogLevel ExtensionDebugging { get; set; } = DiscordLogLevel.Info;
  1109. }
  1110.  
  1111. public class ChannelSettings
  1112. {
  1113. [JsonProperty("Chat Channel ID")]
  1114. public Snowflake ChatChannel { get; set; }
  1115.  
  1116. #if RUST
  1117. [JsonProperty("Team Channel ID")]
  1118. public Snowflake TeamChannel { get; set; }
  1119.  
  1120. [JsonProperty("Cards Channel ID")]
  1121. public Snowflake CardsChannel { get; set; }
  1122. #endif
  1123.  
  1124. [JsonProperty("Join / Leave Channel ID")]
  1125. public Snowflake JoinLeaveChannel { get; set; }
  1126.  
  1127. [JsonProperty("Server Online / Offline Channel ID")]
  1128. public Snowflake OnlineOfflineChannel { get; set; }
  1129.  
  1130. public ChannelSettings(ChannelSettings settings)
  1131. {
  1132. ChatChannel = settings?.ChatChannel ?? default(Snowflake);
  1133. JoinLeaveChannel = settings?.JoinLeaveChannel ?? default(Snowflake);
  1134. OnlineOfflineChannel = settings?.OnlineOfflineChannel ?? default(Snowflake);
  1135. #if RUST
  1136. TeamChannel = settings?.TeamChannel ?? default(Snowflake);
  1137. CardsChannel = settings?.CardsChannel ?? default(Snowflake);
  1138. #endif
  1139. }
  1140. }
  1141.  
  1142. public class MessageSettings
  1143. {
  1144. [JsonProperty("Replace Discord User Message With Bot Message")]
  1145. public bool UseBotMessageDisplay { get; set; }
  1146.  
  1147. [JsonProperty("Send Messages From Server Chat To Discord Channel")]
  1148. public bool ServerToDiscord { get; set; }
  1149.  
  1150. [JsonProperty("Send Messages From Discord Channel To Server Chat")]
  1151. public bool DiscordToServer { get; set; }
  1152.  
  1153. [JsonProperty("Allow plugins to process Discord to Server Chat Messages")]
  1154. public bool AllowPluginProcessing { get; set; }
  1155.  
  1156. [JsonProperty("Discord Message Server Time Offset (Hours)")]
  1157. public float ServerTimeOffset { get; set; }
  1158.  
  1159. [JsonProperty("Text Replacements")]
  1160. public Hash<string, string> TextReplacements { get; set; }
  1161.  
  1162. [JsonProperty("Unlinked Settings")]
  1163. public UnlinkedSettings UnlinkedSettings { get; set; }
  1164.  
  1165. [JsonProperty("Message Filter Settings")]
  1166. public MessageFilterSettings Filter { get; set; }
  1167.  
  1168. public MessageSettings(MessageSettings settings)
  1169. {
  1170. UseBotMessageDisplay = settings?.UseBotMessageDisplay ?? true;
  1171. ServerToDiscord = settings?.ServerToDiscord ?? true;
  1172. DiscordToServer = settings?.DiscordToServer ?? true;
  1173. AllowPluginProcessing = settings?.AllowPluginProcessing ?? true;
  1174. ServerTimeOffset = settings?.ServerTimeOffset ?? 0f;
  1175. TextReplacements = settings?.TextReplacements ?? new Hash<string, string> { ["TextToBeReplaced"] = "ReplacedText" };
  1176. UnlinkedSettings = new UnlinkedSettings(settings?.UnlinkedSettings);
  1177. Filter = new MessageFilterSettings(settings?.Filter);
  1178. }
  1179. }
  1180.  
  1181. public class UnlinkedSettings
  1182. {
  1183. [JsonProperty("Allow Unlinked Players To Chat With Server")]
  1184. public bool AllowedUnlinked { get; set; }
  1185.  
  1186. #if RUST
  1187. [JsonProperty("Steam Icon ID")]
  1188. public ulong SteamIcon { get; set; }
  1189. #endif
  1190.  
  1191. public UnlinkedSettings(UnlinkedSettings settings)
  1192. {
  1193. AllowedUnlinked = settings?.AllowedUnlinked ?? true;
  1194. #if RUST
  1195. SteamIcon = settings?.SteamIcon ?? 76561199144296099;
  1196. #endif
  1197. }
  1198. }
  1199.  
  1200. public class MessageFilterSettings
  1201. {
  1202. [JsonProperty("Ignore messages from users in this list (Discord ID)")]
  1203. public List<Snowflake> IgnoreUsers { get; set; }
  1204.  
  1205. [JsonProperty("Ignore messages from users in this role (Role ID)")]
  1206. public List<Snowflake> IgnoreRoles { get; set; }
  1207.  
  1208. [JsonProperty("Ignored Prefixes")]
  1209. public List<string> IgnoredPrefixes { get; set; }
  1210.  
  1211. public MessageFilterSettings(MessageFilterSettings settings)
  1212. {
  1213. IgnoreUsers = settings?.IgnoreUsers ?? new List<Snowflake>();
  1214. IgnoreRoles = settings?.IgnoreRoles ?? new List<Snowflake>();
  1215. IgnoredPrefixes = settings?.IgnoredPrefixes ?? new List<string>();
  1216. }
  1217. }
  1218.  
  1219. public class PluginSupport
  1220. {
  1221. [JsonProperty("AdminChat Settings")]
  1222. public AdminChatSettings AdminChat { get; set; }
  1223.  
  1224. [JsonProperty("AntiSpam Settings")]
  1225. public AntiSpamSettings AntiSpam { get; set; }
  1226.  
  1227. [JsonProperty("BetterChatMute Settings")]
  1228. public BetterChatMuteSettings BetterChatMuteSettings { get; set; }
  1229.  
  1230. [JsonProperty("ChatTranslator Settings")]
  1231. public ChatTranslatorSettings ChatTranslator { get; set; }
  1232.  
  1233. [JsonProperty("Clan Settings")]
  1234. public ClanSettings Clans { get; set; }
  1235.  
  1236. [JsonProperty("UFilter Settings")]
  1237. public UFilterSettings UFilter { get; set; }
  1238.  
  1239. public PluginSupport(PluginSupport settings)
  1240. {
  1241. AdminChat = new AdminChatSettings(settings?.AdminChat);
  1242. BetterChatMuteSettings = new BetterChatMuteSettings(settings?.BetterChatMuteSettings);
  1243. ChatTranslator = new ChatTranslatorSettings(settings?.ChatTranslator);
  1244. Clans = new ClanSettings(settings?.Clans);
  1245. AntiSpam = new AntiSpamSettings(settings?.AntiSpam);
  1246. UFilter = new UFilterSettings(settings?.UFilter);
  1247. }
  1248. }
  1249.  
  1250. public class AdminChatSettings
  1251. {
  1252. [JsonProperty("Enable AdminChat Plugin Support")]
  1253. public bool Enabled { get; set; }
  1254.  
  1255. [JsonProperty("Chat Channel ID")]
  1256. public Snowflake ChatChannel { get; set; }
  1257.  
  1258. [JsonProperty("Chat Prefix")]
  1259. public string AdminChatPrefix { get; set; }
  1260.  
  1261. [JsonProperty("Replace Discord Message With Bot")]
  1262. public bool ReplaceWithBot { get; set; }
  1263.  
  1264. public AdminChatSettings(AdminChatSettings settings)
  1265. {
  1266. Enabled = settings?.Enabled ?? false;
  1267. ChatChannel = settings?.ChatChannel ?? default(Snowflake);
  1268. AdminChatPrefix = settings?.AdminChatPrefix ?? "@";
  1269. ReplaceWithBot = settings?.ReplaceWithBot ?? true;
  1270. }
  1271. }
  1272.  
  1273. public class BetterChatMuteSettings
  1274. {
  1275. [JsonProperty("Ignore Muted Players")]
  1276. public bool IgnoreMuted { get; set; }
  1277.  
  1278. public BetterChatMuteSettings(BetterChatMuteSettings settings)
  1279. {
  1280. IgnoreMuted = settings?.IgnoreMuted ?? true;
  1281. }
  1282. }
  1283.  
  1284. public class ChatTranslatorSettings
  1285. {
  1286. [JsonProperty("Enable Chat Translator")]
  1287. public bool Enabled { get; set; }
  1288.  
  1289. [JsonProperty("Use ChatTranslator On Server Messages")]
  1290. public bool ServerMessage { get; set; }
  1291.  
  1292. [JsonProperty("Use ChatTranslator On Chat Messages")]
  1293. public bool DiscordMessage { get; set; }
  1294.  
  1295. #if RUST
  1296. [JsonProperty("Use ChatTranslator On Team Messages")]
  1297. public bool TeamMessage { get; set; }
  1298.  
  1299. [JsonProperty("Use ChatTranslator On Card Messages")]
  1300. public bool CardMessages { get; set; }
  1301. #endif
  1302.  
  1303. [JsonProperty("Discord Server Chat Language")]
  1304. public string DiscordServerLanguage { get; set; }
  1305.  
  1306. public ChatTranslatorSettings(ChatTranslatorSettings settings)
  1307. {
  1308. Enabled = settings?.Enabled ?? false;
  1309. ServerMessage = settings?.ServerMessage ?? false;
  1310. DiscordMessage = settings?.DiscordMessage ?? false;
  1311. #if RUST
  1312. TeamMessage = settings?.TeamMessage ?? false;
  1313. CardMessages = settings?.CardMessages ?? false;
  1314. #endif
  1315. DiscordServerLanguage = settings?.DiscordServerLanguage ?? Interface.Oxide.GetLibrary<Lang>().GetServerLanguage();
  1316. }
  1317. }
  1318.  
  1319. public class ClanSettings
  1320. {
  1321. [JsonProperty("Display Clan Tag")]
  1322. public bool ShowClanTag { get; set; }
  1323.  
  1324. public ClanSettings(ClanSettings settings)
  1325. {
  1326. ShowClanTag = settings?.ShowClanTag ?? true;
  1327. }
  1328. }
  1329.  
  1330. public class AntiSpamSettings
  1331. {
  1332. [JsonProperty("Use AntiSpam On Player Names")]
  1333. public bool ValidateNicknames { get; set; }
  1334.  
  1335. [JsonProperty("Use AntiSpam On Server Messages")]
  1336. public bool ServerMessage { get; set; }
  1337.  
  1338. [JsonProperty("Use AntiSpam On Chat Messages")]
  1339. public bool DiscordMessage { get; set; }
  1340.  
  1341. #if RUST
  1342. [JsonProperty("Use AntiSpam On Team Messages")]
  1343. public bool TeamMessage { get; set; }
  1344.  
  1345. [JsonProperty("Use AntiSpam On Card Messages")]
  1346. public bool CardMessages { get; set; }
  1347. #endif
  1348.  
  1349. public AntiSpamSettings(AntiSpamSettings settings)
  1350. {
  1351. ValidateNicknames = settings?.ValidateNicknames ?? false;
  1352. ServerMessage = settings?.ServerMessage ?? false;
  1353. DiscordMessage = settings?.DiscordMessage ?? false;
  1354. #if RUST
  1355. TeamMessage = settings?.TeamMessage ?? false;
  1356. CardMessages = settings?.CardMessages ?? false;
  1357. #endif
  1358. }
  1359. }
  1360.  
  1361. public class UFilterSettings
  1362. {
  1363. [JsonProperty("Use UFilter On Player Names")]
  1364. public bool ValidateNicknames { get; set; }
  1365.  
  1366. [JsonProperty("Use UFilter On Server Messages")]
  1367. public bool GlobalMessage { get; set; }
  1368.  
  1369. [JsonProperty("Use UFilter On Discord Messages")]
  1370. public bool DiscordMessages { get; set; }
  1371.  
  1372. #if RUST
  1373. [JsonProperty("Use UFilter On Team Messages")]
  1374. public bool TeamMessage { get; set; }
  1375.  
  1376. [JsonProperty("Use UFilter On Card Messages")]
  1377. public bool CardMessage { get; set; }
  1378. #endif
  1379.  
  1380. public UFilterSettings(UFilterSettings settings)
  1381. {
  1382. ValidateNicknames = settings?.ValidateNicknames ?? false;
  1383. GlobalMessage = settings?.GlobalMessage ?? false;
  1384. DiscordMessages = settings?.DiscordMessages ?? false;
  1385. #if RUST
  1386. TeamMessage = settings?.TeamMessage ?? false;
  1387. CardMessage = settings?.CardMessage ?? false;
  1388. #endif
  1389. }
  1390. }
  1391.  
  1392. public class DiscordTimedSend
  1393. {
  1394. private readonly StringBuilder _message = new StringBuilder();
  1395. private Timer _sendTimer;
  1396. private readonly Snowflake _channelId;
  1397.  
  1398. public DiscordTimedSend(Snowflake channelId)
  1399. {
  1400. _channelId = channelId;
  1401. }
  1402.  
  1403. public void QueueMessage(string message)
  1404. {
  1405. if (string.IsNullOrEmpty(message) || message.Trim().Length == 0)
  1406. {
  1407. return;
  1408. }
  1409.  
  1410. if (_message.Length + message.Length > 2000)
  1411. {
  1412. Send();
  1413. }
  1414.  
  1415. if (_sendTimer == null)
  1416. {
  1417. _sendTimer = _ins.timer.In(1f, Send);
  1418. }
  1419.  
  1420. _message.AppendLine(message);
  1421. }
  1422.  
  1423. private void Send()
  1424. {
  1425. _ins.SendMessageToChannel(_channelId, _message);
  1426. _message.Length = 0;
  1427. _sendTimer = null;
  1428. }
  1429. }
  1430. #endregion
  1431.  
  1432. #region Lang
  1433. private static class LangKeys
  1434. {
  1435. public const string Root = "V1.";
  1436.  
  1437. public static class Discord
  1438. {
  1439. private const string Base = Root + nameof(Discord) + ".";
  1440.  
  1441. public const string NotLinkedError = Base + nameof(NotLinkedError);
  1442.  
  1443. public static class ChatChannel
  1444. {
  1445. private const string Base = Discord.Base + nameof(ChatChannel) + ".";
  1446.  
  1447. public const string Message = Base + nameof(Message);
  1448. public const string LinkedMessage = Base + nameof(LinkedMessage);
  1449. public const string UnlinkedMessage = Base + nameof(UnlinkedMessage);
  1450. }
  1451.  
  1452. public static class TeamChannel
  1453. {
  1454. private const string Base = Discord.Base + nameof(TeamChannel) + ".";
  1455.  
  1456. public const string Message = Base + nameof(Message);
  1457. }
  1458.  
  1459. public static class CardsChannel
  1460. {
  1461. private const string Base = Discord.Base + nameof(CardsChannel) + ".";
  1462.  
  1463. public const string Message = Base + nameof(Message);
  1464. }
  1465.  
  1466. public static class JoinLeave
  1467. {
  1468. private const string Base = Discord.Base + nameof(JoinLeave) + ".";
  1469.  
  1470. public const string ConnectedMessage = Base + nameof(ConnectedMessage);
  1471. public const string DisconnectedMessage = Base + nameof(DisconnectedMessage);
  1472. }
  1473.  
  1474. public static class OnlineOffline
  1475. {
  1476. private const string Base = Discord.Base + nameof(OnlineOffline) + ".";
  1477.  
  1478. public const string OnlineMessage = Base + nameof(OnlineMessage);
  1479. public const string OfflineMessage = Base + nameof(OfflineMessage);
  1480. }
  1481.  
  1482. public static class AdminChat
  1483. {
  1484. private const string Base = Discord.Base + nameof(AdminChat) + ".";
  1485.  
  1486. public const string Message = Base + nameof(Message);
  1487. public const string Permission = Base + nameof(Permission);
  1488. }
  1489. }
  1490.  
  1491. public static class Server
  1492. {
  1493. private const string Base = Root + nameof(Server) + ".";
  1494.  
  1495. public const string LinkedMessage = Base + nameof(LinkedMessage);
  1496. public const string UnlinkedMessage = Base + nameof(UnlinkedMessage);
  1497. public const string DiscordTag = Base + nameof(DiscordTag);
  1498. public const string ClanTag = Base + nameof(ClanTag);
  1499. }
  1500. }
  1501. #endregion
  1502. }
  1503. }
  1504.  
Advertisement
Add Comment
Please, Sign In to add comment