C#:
// Все права принадлежат дискорд сообществу https://discord.gg/VgNHPpNrz6
using ConVar;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Oxide.Core;
using Oxide.Core.Libraries;
using Oxide.Core.Libraries.Covalence;
using Oxide.Core.Plugins;
using Oxide.Ext.Discord.Cache;
using Oxide.Ext.Discord.Clients;
using Oxide.Ext.Discord.Connections;
using Oxide.Ext.Discord.Constants;
using Oxide.Ext.Discord.Entities;
using Oxide.Ext.Discord.Extensions;
using Oxide.Ext.Discord.Interfaces;
using Oxide.Ext.Discord.Libraries;
using Oxide.Ext.Discord.Logging;
using Oxide.Ext.Discord.Types;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
//DiscordChat created with PluginMerge v(1.0.10.0) by MJSU @ https://github.com/dassjosh/Plugin.Merge
namespace Oxide.Plugins {
[Info("Discord Chat", "MJSU", "3.0.6")]
[Description("Allows chatting between discord and game server")]
public partial class DiscordChat : CovalencePlugin, IDiscordPlugin, IDiscordPool {
#region Plugins\DiscordChat.AdminChat.cs
private AdminChatSettings _adminChatSettings;
private const string AdminChatPermission = "adminchat.use";
//Hook called from AdminChat Plugin
[HookMethod(nameof(OnAdminChat))]
public void OnAdminChat(IPlayer player, string message) {
if (IsAdminChatEnabled()) {
HandleMessage(message, player, player.GetDiscordUser(), MessageSource.PluginAdminChat, null);
}
}
//Message sent in admin chat channel.Process bot replace and sending to server
public void HandleAdminChatDiscordMessage(DiscordMessage message) {
IPlayer player = message.Author.Player;
if (player == null) {
message.ReplyWithGlobalTemplate(Client, TemplateKeys.Error.AdminChat.NotLinked, null, GetDefault().AddMessage(message));
return;
}
if (!CanPlayerAdminChat(player)) {
message.ReplyWithGlobalTemplate(Client, TemplateKeys.Error.AdminChat.NoPermission, null, GetDefault().AddPlayer(player).AddMessage(message));
return;
}
HandleMessage(message.Content, player, player.GetDiscordUser(), MessageSource.PluginAdminChat, message);
}
public bool IsAdminChatEnabled() => _adminChatSettings.Enabled && Sends.ContainsKey(MessageSource.PluginAdminChat);
public bool CanPlayerAdminChat(IPlayer player) => player != null && _adminChatSettings.Enabled && player.HasPermission(AdminChatPermission);
#endregion
#region Plugins\DiscordChat.BetterChat.cs
public bool SendBetterChatMessage(IPlayer player, string message, MessageSource source) {
if (!IsPluginLoaded(BetterChat)) {
return false;
}
Dictionary<string, object> data = GetBetterChatMessageData(player, message);
if (source == MessageSource.Discord && !string.IsNullOrEmpty(_pluginConfig.ChatSettings.DiscordTag)) {
BetterChatSettings settings = _pluginConfig.PluginSupport.BetterChat;
List<string> titles = GetBetterChatTags(data);
if (titles != null) {
titles.Add(_pluginConfig.ChatSettings.DiscordTag);
while (titles.Count > settings.ServerMaxTags) {
titles.RemoveAt(0);
}
}
}
BetterChat.Call("API_SendMessage", data);
return true;
}
public Dictionary<string, object> GetBetterChatMessageData(IPlayer player, string message) {
return BetterChat.Call<Dictionary<string, object>>("API_GetMessageData", player, message);
}
public List<string> GetBetterChatTags(Dictionary<string, object> data) {
if (data["Titles"] is List<string> titles) {
titles.RemoveAll(string.IsNullOrWhiteSpace);
for (int index = 0; index < titles.Count; index++) {
string title = titles[index];
}
return titles;
}
return null;
}
#endregion
#region Plugins\DiscordChat.Clans.cs
private void OnClanChat(IPlayer player, string message) {
Sends[MessageSource.PluginClan]?.QueueMessage(Lang(LangKeys.Discord.PluginClans.ClanMessage, GetClanPlaceholders(player, message)));
}
private void OnAllianceChat(IPlayer player, string message) {
Sends[MessageSource.PluginAlliance]?.QueueMessage(Lang(LangKeys.Discord.PluginClans.AllianceMessage, GetClanPlaceholders(player, message)));
}
public PlaceholderData GetClanPlaceholders(IPlayer player, string message) {
return GetDefault().AddPlayer(player).Add(PlaceholderDataKeys.PlayerMessage, message);
}
#endregion
#region Plugins\DiscordChat.DiscordHooks.cs
[HookMethod(DiscordExtHooks.OnDiscordClientCreated)]
private void OnDiscordClientCreated() {
if (!string.IsNullOrEmpty(_pluginConfig.DiscordApiKey)) {
RegisterPlaceholders();
RegisterTemplates();
Client.Connect(new BotConnection {
Intents = GatewayIntents.Guilds | GatewayIntents.GuildMembers | GatewayIntents.GuildMessages | GatewayIntents.MessageContent, ApiToken = _pluginConfig.DiscordApiKey, LogLevel = _pluginConfig.ExtensionDebugging
}
);
}
}
[HookMethod(DiscordExtHooks.OnDiscordGatewayReady)]
private void OnDiscordGatewayReady(GatewayReadyEvent ready) {
if (ready.Guilds.Count == 0) {
PrintError("Your bot was not found in any discord servers.Please invite it to a server and reload the plugin.");
return;
}
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.Once updated please reload {Name}.");
}
Puts($"{Title} Ready");
}
[HookMethod(DiscordExtHooks.OnDiscordGuildCreated)]
private void OnDiscordGuildCreated(DiscordGuild guild) {
if (_pluginConfig.ChatSettings.DiscordToServer) {
SetupChannel(guild, MessageSource.Server, _pluginConfig.ChatSettings.ChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat, HandleDiscordChatMessage);
}
else {
SetupChannel(guild, MessageSource.Server, _pluginConfig.ChatSettings.ChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat);
}
SetupChannel(guild, MessageSource.Discord, _pluginConfig.ChatSettings.ChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat);
SetupChannel(guild, MessageSource.Connecting, _pluginConfig.PlayerStateSettings.PlayerStateChannel);
SetupChannel(guild, MessageSource.Connected, _pluginConfig.PlayerStateSettings.PlayerStateChannel);
SetupChannel(guild, MessageSource.Disconnected, _pluginConfig.PlayerStateSettings.PlayerStateChannel);
SetupChannel(guild, MessageSource.PluginAdminChat, _pluginConfig.PluginSupport.AdminChat.ChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat, HandleAdminChatDiscordMessage);
SetupChannel(guild, MessageSource.PluginClan, _pluginConfig.PluginSupport.Clans.ClansChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat);
SetupChannel(guild, MessageSource.PluginAlliance, _pluginConfig.PluginSupport.Clans.AllianceChatChannel, _pluginConfig.ChatSettings.UseBotToDisplayChat);
SetupChannel(guild, MessageSource.PluginPrivateMessages, _pluginConfig.PluginSupport.PrivateMessages.Channel, _pluginConfig.ChatSettings.UseBotToDisplayChat);
#if RUST
SetupChannel(guild, MessageSource.Team, _pluginConfig.ChatSettings.TeamChannel);
SetupChannel(guild, MessageSource.Cards, _pluginConfig.ChatSettings.CardsChannel);
SetupChannel(guild, MessageSource.Clan, _pluginConfig.ChatSettings.ClansChannel);
#endif
if (_pluginConfig.ChatSettings.ChatChannel.IsValid()
#if RUST
|| _pluginConfig.ChatSettings.TeamChannel.IsValid() || _pluginConfig.ChatSettings.CardsChannel.IsValid()
#endif
) {
#if RUST
Subscribe(nameof(OnPlayerChat));
#else
Subscribe(nameof(OnUserChat));
#endif
}
if (_pluginConfig.PlayerStateSettings.PlayerStateChannel.IsValid()) {
if (_pluginConfig.PlayerStateSettings.SendConnectingMessage) {
Subscribe(nameof(OnUserApproved));
}
if (_pluginConfig.PlayerStateSettings.SendConnectedMessage) {
Subscribe(nameof(OnUserConnected));
}
if (_pluginConfig.PlayerStateSettings.SendDisconnectedMessage) {
Subscribe(nameof(OnUserDisconnected));
}
}
if (_pluginConfig.ServerStateSettings.ServerStateChannel.IsValid()) {
Subscribe(nameof(OnServerShutdown));
}
if (_pluginConfig.PluginSupport.Clans.ClansChatChannel.IsValid()) {
Subscribe(nameof(OnClanChat));
}
if (_pluginConfig.PluginSupport.Clans.AllianceChatChannel.IsValid()) {
Subscribe(nameof(OnAllianceChat));
}
if (_pluginConfig.PluginSupport.PrivateMessages.Channel.IsValid()) {
Subscribe(nameof(OnPMProcessed));
}
timer.In(0.1f, () => {
if (!_serverInitCalled && _pluginConfig.ServerStateSettings.SendBootingMessage) {
SendGlobalTemplateMessage(TemplateKeys.Server.Booting, FindChannel(_pluginConfig.ServerStateSettings.ServerStateChannel), GetDefault());
}
}
);
}
public void SetupChannel(DiscordGuild guild, MessageSource source, Snowflake id, bool wipeNonBotMessages = false, Action<DiscordMessage> callback = null) {
if (!id.IsValid()) {
return;
}
DiscordChannel channel = guild.GetChannel(id);
if (channel == null && id.IsValid()) {
PrintWarning($"Failed to setup source {source} channel with ID: '{id}'.Not found in guild");
return;
}
if (callback != null) {
_subscriptions.AddChannelSubscription(Client, id, callback);
}
if (wipeNonBotMessages) {
channel.GetMessages(Client, new ChannelMessagesRequest {
Limit = 100
}
).Then(messages => {
OnGetChannelMessages(messages, callback);
}
);
}
Sends[source] = new DiscordSendQueue(channel, GetTemplateName(source), timer);
Puts($"Setup Channel {source} With ID: {id}");
}
private void OnGetChannelMessages(List<DiscordMessage> messages, Action<DiscordMessage> callback) {
if (messages.Count == 0 || callback == null) {
return;
}
foreach (DiscordMessage message in messages.Where(m => !m.Author.IsBot && (DateTimeOffset.UtcNow - m.Id.GetCreationDate()).TotalDays < 14 && CanSendMessage(m.Content, m.Author.Player, m.Author, MessageSource.Discord, m))) {
callback.Invoke(message);
}
}
public void HandleDiscordChatMessage(DiscordMessage message) {
IPlayer player = message.Author.Player;
if (Interface.Oxide.CallHook("OnDiscordChatMessage", player, message.Content, message.Author) != null) {
return;
}
HandleMessage(message.Content, player, message.Author, MessageSource.Discord, message);
if (_pluginConfig.ChatSettings.UseBotToDisplayChat) {
message.Delete(Client).Catch<ResponseError>(error => {
if (error.DiscordError is {
Code : 50013
}
) {
PrintError($"ChatSettings.UseBotToDisplayChat is enabled but the bot doesn't have permission to delete messages in channel {Client.Bot.Servers[message.GuildId ?? default]?.Channels[message.ChannelId]?.Name ?? message.ChannelId}");
error.SuppressErrorMessage();
}
}
);
}
}
#endregion
#region Plugins\DiscordChat.Fields.cs
[PluginReference]
private Plugin BetterChat;
public DiscordClient Client {
get;
set;
}
public DiscordPluginPool Pool {
get;
set;
}
private PluginConfig _pluginConfig;
private readonly DiscordSubscriptions _subscriptions = GetLibrary<DiscordSubscriptions>();
private readonly DiscordPlaceholders _placeholders = GetLibrary<DiscordPlaceholders>();
private readonly DiscordMessageTemplates _templates = GetLibrary<DiscordMessageTemplates>();
private bool _serverInitCalled;
public readonly Hash<MessageSource, DiscordSendQueue> Sends = new();
private readonly List<IPluginHandler> _plugins = new();
public static DiscordChat Instance;
private readonly object _true = true;
#endregion
#region Plugins\DiscordChat.Helpers.cs
public MessageSource GetSourceFromServerChannel(int channel) {
switch (channel) {
case 1 : return MessageSource.Team;
case 3 : return MessageSource.Cards;
case 5 : return MessageSource.Clan;
}
return MessageSource.Server;
}
public DiscordChannel FindChannel(Snowflake channelId) {
if (!channelId.IsValid()) {
return null;
}
foreach (DiscordGuild guild in Client.Bot.Servers.Values) {
DiscordChannel channel = guild.Channels[channelId];
if (channel != null) {
return channel;
}
}
return null;
}
public bool IsPluginLoaded(Plugin plugin) => plugin != null && plugin.IsLoaded;
public new void Subscribe(string hook) {
base.Subscribe(hook);
}
public new void Unsubscribe(string hook) {
base.Unsubscribe(hook);
}
public void Puts(string message) {
base.Puts(message);
}
#endregion
#region Plugins\DiscordChat.Hooks.cs
private void OnUserApproved(string name, string id, string ip) {
IPlayer player = players.FindPlayerById(id) ?? PlayerExt.CreateDummyPlayer(id, name, ip);
if (_pluginConfig.PlayerStateSettings.ShowAdmins || !player.IsAdmin) {
PlaceholderData placeholders = GetDefault().AddPlayer(player).AddIp(ip);
ProcessPlayerState(MessageSource.Connecting, LangKeys.Discord.Player.Connecting, placeholders);
}
}
private void OnUserConnected(IPlayer player) {
if (_pluginConfig.PlayerStateSettings.ShowAdmins || !player.IsAdmin) {
PlaceholderData placeholders = GetDefault().AddPlayer(player);
ProcessPlayerState(MessageSource.Connected, LangKeys.Discord.Player.Connected, placeholders);
}
}
private void OnUserDisconnected(IPlayer player, string reason) {
if (_pluginConfig.PlayerStateSettings.ShowAdmins || !player.IsAdmin) {
PlaceholderData placeholders = GetDefault().AddPlayer(player).Add(PlaceholderDataKeys.DisconnectReason, reason);
ProcessPlayerState(MessageSource.Disconnected, LangKeys.Discord.Player.Disconnected, placeholders);
}
}
public void ProcessPlayerState(MessageSource source, string langKey, PlaceholderData data) {
string message = Lang(langKey, data);
Sends[source]?.QueueMessage(message);
}
private void OnPluginLoaded(Plugin plugin) {
if (plugin == null) {
return;
}
OnPluginUnloaded(plugin);
switch (plugin.Name) {
case "AdminChat" : AddHandler(new AdminChatHandler(Client, this, _pluginConfig.PluginSupport.AdminChat, plugin));
break;
case "AdminDeepCover" : AddHandler(new AdminDeepCoverHandler(this, plugin));
break;
case "AntiSpam" : if (plugin.Version < new VersionNumber(2, 0, 0)) {
PrintError("AntiSpam plugin must be version 2.0.0 or higher");
break;
}
AddHandler(new AntiSpamHandler(this, _pluginConfig.PluginSupport.AntiSpam, plugin));
break;
case "BetterChatMute" : BetterChatMuteSettings muteSettings = _pluginConfig.PluginSupport.BetterChatMute;
if (muteSettings.IgnoreMuted) {
AddHandler(new BetterChatMuteHandler(this, muteSettings, plugin));
}
break;
case "BetterChat" : AddHandler(new BetterChatHandler(this, _pluginConfig.PluginSupport.BetterChat, plugin));
break;
case "TranslationAPI" : AddHandler(new TranslationApiHandler(this, _pluginConfig.PluginSupport.ChatTranslator, plugin));
break;
case "UFilter" : AddHandler(new UFilterHandler(this, _pluginConfig.PluginSupport.UFilter, plugin));
break;
}
}
public void AddHandler(IPluginHandler handler) {
_plugins.Add(handler);
}
private void OnPluginUnloaded(Plugin plugin) {
if (plugin.Name != Name) {
_plugins.RemoveAll(h => h.GetPluginName() == plugin.Name);
}
}
#if RUST
private void OnPlayerChat(BasePlayer rustPlayer, string message, Chat.ChatChannel chatChannel) {
HandleChat(rustPlayer.IPlayer, message, (int)chatChannel);
}
#else
private void OnUserChat(IPlayer player, string message) {
HandleChat(player, message, 0);
}
#endif
public void HandleChat(IPlayer player, string message, int channel) {
DiscordUser user = player.GetDiscordUser();
MessageSource source = GetSourceFromServerChannel(channel);
if (Sends.ContainsKey(source)) {
HandleMessage(message, player, user, source, null);
}
}
#endregion
#region Plugins\DiscordChat.Lang.cs
public string Lang(string key, PlaceholderData data) {
string message = lang.GetMessage(key, this);
message = _placeholders.ProcessPlaceholders(message, data);
return message;
}
protected override void LoadDefaultMessages() {
lang.RegisterMessages(new Dictionary<string, string> {
[LangKeys.Discord.Player.Connecting]
= $":yellow_circle: {DefaultKeys.TimestampNow.ShortTime} {DefaultKeys.Ip.CountryEmoji} **{PlaceholderKeys.PlayerName}** is connecting", [LangKeys.Discord.Player.Connected] = $":white_check_mark: {DefaultKeys.TimestampNow.ShortTime} {DefaultKeys.Player.CountryEmoji} **{PlaceholderKeys.PlayerName}** has joined.", [LangKeys.Discord.Player.Disconnected] = $":x: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}** has disconnected.({PlaceholderKeys.DisconnectReason})", [LangKeys.Discord.Chat.Server] = $":desktop: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.Chat.LinkedMessage] = $":speech_left: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.Chat.UnlinkedMessage] = $":chains: {DefaultKeys.TimestampNow.ShortTime} {DefaultKeys.User.Mention}: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.Chat.PlayerName] = $"{DefaultKeys.Player.Name}", [LangKeys.Discord.Team.Message] = $":busts_in_silhouette: {DefaultKeys.TimestampNow.ShortTime} [{PlaceholderKeys.TeamId}] **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.Cards.Message] = $":black_joker: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.Clans.Message] = $":shield: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.AdminChat.ServerMessage] = $":mechanic: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.AdminChat.DiscordMessage] = $":mechanic: {DefaultKeys.TimestampNow.ShortTime} **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.PluginClans.ClanMessage] = $"{DefaultKeys.TimestampNow.ShortTime} [Clan] **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.PluginClans.AllianceMessage] = $"{DefaultKeys.TimestampNow.ShortTime} [Alliance] **{PlaceholderKeys.PlayerName}**: {PlaceholderKeys.PlayerMessage}", [LangKeys.Discord.PrivateMessages.Message] = $"[{DefaultKeys.TimestampNow.ShortTime}] {DefaultKeys.Player.Name} -> {DefaultKeys.PlayerTarget.Name}: {PlaceholderKeys.PlayerMessage}", [LangKeys.Server.UnlinkedMessage] = $"{PlaceholderKeys.DiscordTag} [#5f79d6]{DefaultKeys.Member.Name}[/#]: {PlaceholderKeys.PlayerMessage}", [LangKeys.Server.LinkedMessage] = $"{PlaceholderKeys.DiscordTag} [#5f79d6]{PlaceholderKeys.PlayerName}[/#]: {PlaceholderKeys.PlayerMessage}"
}
, this);
}
#endregion
#region Plugins\DiscordChat.MessageHandling.cs
private readonly Regex _channelMention = new(@"(<#\d+>)", RegexOptions.IgnoreCase | RegexOptions.Compiled);
private readonly Regex _emojiRegex = new(@"(©|®|[ -㌀]|�[퀀-�]|�[퀀-�]|�[퀀-�])", RegexOptions.Compiled);
private readonly MatchEvaluator _emojiEvaluator = match => EmojiCache.Instance.EmojiToText(match.Value) ?? match.Value;
public void HandleMessage(string content, IPlayer player, DiscordUser user, MessageSource source, DiscordMessage sourceMessage) {
if (!CanSendMessage(content, player, user, source, sourceMessage)) {
return;
}
#if RUST
content = ProcessEmojis(content);
#endif
ProcessCallbackMessages(content, player, user, source, processedMessage => {
StringBuilder sb = Pool.GetStringBuilder(processedMessage);
if (sourceMessage != null) {
ProcessMentions(sourceMessage, sb);
}
ProcessMessage(sb, player, user, source);
SendMessage(Pool.ToStringAndFree(sb), player, user, source, sourceMessage);
}
);
}
public string ProcessEmojis(string message) => _emojiRegex.Replace(message, _emojiEvaluator);
public void ProcessMentions(DiscordMessage message, StringBuilder sb) {
DiscordGuild guild = Client.Bot.GetGuild(message.GuildId);
if (message.Mentions != null) {
foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions) {
GuildMember member = guild.Members[mention.Key];
sb.Replace($"<@{mention.Key.ToString()}>", $"@{member?.DisplayName ?? mention.Value.DisplayName}");
}
foreach (KeyValuePair<Snowflake, DiscordUser> mention in message.Mentions) {
GuildMember member = guild.Members[mention.Key];
sb.Replace($"<@!{mention.Key.ToString()}>", $"@{member?.DisplayName ?? mention.Value.DisplayName}");
}
}
if (message.MentionsChannels != null) {
foreach (KeyValuePair<Snowflake, ChannelMention> mention in message.MentionsChannels) {
sb.Replace($"<#{mention.Key.ToString()}>", $"#{mention.Value.Name}");
}
}
foreach (Match match in _channelMention.Matches(message.Content)) {
string value = match.Value;
Snowflake id = new(value.AsSpan().Slice(2, value.Length - 3));
DiscordChannel channel = guild.Channels[id];
if (channel != null) {
sb.Replace(value, $"#{channel.Name}");
}
}
if (message.MentionRoles != null) {
foreach (Snowflake roleId in message.MentionRoles) {
DiscordRole role = guild.Roles[roleId];
sb.Replace($"<@&{roleId.ToString()}>", $"@{role.Name ?? roleId}");
}
}
}
public bool CanSendMessage(string message, IPlayer player, DiscordUser user, MessageSource source, DiscordMessage sourceMessage) {
for (int index = 0; index < _plugins.Count; index++) {
if (!_plugins[index].CanSendMessage(message, player, user, source, sourceMessage)) {
return false;
}
}
return true;
}
public void ProcessCallbackMessages(string message, IPlayer player, DiscordUser user, MessageSource source, Action<string> completed, int index = 0) {
for (; index < _plugins.Count; index++) {
IPluginHandler handler = _plugins[index];
if (handler.HasCallbackMessage()) {
handler.ProcessCallbackMessage(message, player, user, source, callbackMessage => {
ProcessCallbackMessages(callbackMessage, player, user, source, completed, index + 1);
}
);
return;
}
}
completed.Invoke(message);
}
public void ProcessMessage(StringBuilder message, IPlayer player, DiscordUser user, MessageSource source) {
for (int index = 0; index < _plugins.Count; index++) {
_plugins[index].ProcessMessage(message, player, user, source);
}
}
public void SendMessage(string message, IPlayer player, DiscordUser user, MessageSource source, DiscordMessage sourceMessage) {
using PlaceholderData data = GetPlaceholders(message, player, user, sourceMessage);
data.ManualPool();
for (int index = 0; index < _plugins.Count; index++) {
IPluginHandler plugin = _plugins[index];
if (plugin.SendMessage(message, player, user, source, sourceMessage, data)) {
return;
}
}
}
private PlaceholderData GetPlaceholders(string message, IPlayer player, DiscordUser user, DiscordMessage sourceMessage) {
PlaceholderData placeholders = GetDefault().AddPlayer(player).AddUser(user).AddMessage(sourceMessage).Add(PlaceholderDataKeys.PlayerMessage, message);
if (sourceMessage != null) {
placeholders.AddGuildMember(Client.Bot.GetGuild(sourceMessage.GuildId)?.Members[sourceMessage.Author.Id]);
}
return placeholders;
}
#endregion
#region Plugins\DiscordChat.Placeholders.cs
public void RegisterPlaceholders() {
_placeholders.RegisterPlaceholder<string>(this, PlaceholderKeys.TemplateMessage, PlaceholderDataKeys.TemplateMessage);
_placeholders.RegisterPlaceholder<string>(this, PlaceholderKeys.PlayerMessage, PlaceholderDataKeys.PlayerMessage);
_placeholders.RegisterPlaceholder<string>(this, PlaceholderKeys.DisconnectReason, PlaceholderDataKeys.DisconnectReason);
_placeholders.RegisterPlaceholder<IPlayer, string>(this, PlaceholderKeys.PlayerName, GetPlayerName);
_placeholders.RegisterPlaceholder<IPlayer, string>(this, PlaceholderKeys.TargetName, GetPlayerName);
_placeholders.RegisterPlaceholder(this, PlaceholderKeys.DiscordTag, _pluginConfig.ChatSettings.DiscordTag);
_placeholders.RegisterPlaceholder<IPlayer, ulong>(this, PlaceholderKeys.TeamId, GetTeamId);
}
public string GetPlayerName(IPlayer player) {
string name = Lang(LangKeys.Discord.Chat.PlayerName, GetDefault().AddPlayer(player));
StringBuilder sb = Pool.GetStringBuilder(name);
for (int index = 0; index < _plugins.Count; index++) {
_plugins[index].ProcessPlayerName(sb, player);
}
return Pool.ToStringAndFree(sb);
}
public ulong GetTeamId(IPlayer player) {
#if RUST
return RelationshipManager.ServerInstance.playerToTeam.TryGetValue(ulong.Parse(player.Id), out RelationshipManager.PlayerTeam team) ? team.teamID : 0;
#else
return 0;
#endif
}
public PlaceholderData GetDefault() {
return _placeholders.CreateData(this);
}
#endregion
#region Plugins\DiscordChat.PrivateMessages.cs
private void OnPMProcessed(IPlayer sender, IPlayer target, string message) {
Sends[MessageSource.PluginPrivateMessages]?.QueueMessage(Lang(LangKeys.Discord.PrivateMessages.Message, GetPrivateMessagesPlaceholders(sender, target, message)));
}
public PlaceholderData GetPrivateMessagesPlaceholders(IPlayer sender, IPlayer target, string message) {
return GetDefault().AddPlayer(sender).AddTarget(target).Add(PlaceholderDataKeys.PlayerMessage, message);
}
#endregion
#region Plugins\DiscordChat.Setup.cs
private void Init() {
Instance = this;
_adminChatSettings = _pluginConfig.PluginSupport.AdminChat;
#if RUST
Unsubscribe(nameof(OnPlayerChat));
#else
Unsubscribe(nameof(OnUserChat));
#endif
Unsubscribe(nameof(OnUserApproved));
Unsubscribe(nameof(OnUserConnected));
Unsubscribe(nameof(OnUserDisconnected));
Unsubscribe(nameof(OnServerShutdown));
Unsubscribe(nameof(OnClanChat));
Unsubscribe(nameof(OnAllianceChat));
Unsubscribe(nameof(OnPMProcessed));
_plugins.Add(new DiscordChatHandler(this, _pluginConfig.ChatSettings, this, server));
}
protected override void LoadDefaultConfig() {
PrintWarning("Loading Default Config");
}
protected override void LoadConfig() {
base.LoadConfig();
_pluginConfig = AdditionalConfig(Config.ReadObject<PluginConfig>());
Config.WriteObject(_pluginConfig);
}
private PluginConfig AdditionalConfig(PluginConfig config) {
config.ChatSettings = new ChatSettings(config.ChatSettings);
config.PlayerStateSettings = new PlayerStateSettings(config.PlayerStateSettings);
config.ServerStateSettings = new ServerStateSettings(config.ServerStateSettings);
config.PluginSupport = new PluginSupport(config.PluginSupport);
return config;
}
private void OnServerInitialized(bool startup) {
_serverInitCalled = true;
if (IsPluginLoaded(BetterChat)) {
if (BetterChat.Version < new VersionNumber(5, 2, 7)) {
PrintWarning("Please update your version of BetterChat to version >= 5.2.7");
}
}
if (string.IsNullOrEmpty(_pluginConfig.DiscordApiKey)) {
PrintWarning("Please set the Discord Bot Token and reload the plugin");
return;
}
OnPluginLoaded(plugins.Find("AdminChat"));
OnPluginLoaded(plugins.Find("AdminDeepCover"));
OnPluginLoaded(plugins.Find("AntiSpam"));
OnPluginLoaded(plugins.Find("BetterChatMute"));
OnPluginLoaded(plugins.Find("TranslationAPI"));
OnPluginLoaded(plugins.Find("UFilter"));
OnPluginLoaded(plugins.Find("BetterChat"));
if (startup && _pluginConfig.ServerStateSettings.SendOnlineMessage) {
SendGlobalTemplateMessage(TemplateKeys.Server.Online, FindChannel(_pluginConfig.ServerStateSettings.ServerStateChannel), GetDefault());
}
}
private void OnServerShutdown() {
if(_pluginConfig.ServerStateSettings.SendShutdownMessage) {
SendGlobalTemplateMessage(TemplateKeys.Server.Shutdown, FindChannel(_pluginConfig.ServerStateSettings.ServerStateChannel), GetDefault());
}
}
private void Unload() {
Instance = null;
}
#endregion
#region Plugins\DiscordChat.Templates.cs
public void RegisterTemplates() {
DiscordMessageTemplate connecting = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Warning);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Player.Connecting, connecting, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate connected = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Success);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Player.Connected, connected, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate disconnected = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Player.Disconnected, disconnected, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate online = CreateTemplateEmbed($":green_circle: {DefaultKeys.TimestampNow.ShortTime} The server is now online", DiscordColor.Success);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Server.Online, online, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate shutdown = CreateTemplateEmbed($":red_circle: {DefaultKeys.TimestampNow.ShortTime} The server has shutdown", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Server.Shutdown, shutdown, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate booting = CreateTemplateEmbed($":yellow_circle: {DefaultKeys.TimestampNow.ShortTime} The server is now booting", DiscordColor.Warning);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Server.Booting, booting, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate serverChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Blurple);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.General, serverChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate teamChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Success);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.Teams, teamChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate clanChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Success);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.Clan, clanChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate cardsChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.Cards, cardsChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate pluginClanChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", new DiscordColor("a1ff46"));
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.Clans.Clan, pluginClanChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate pluginAllianceChat = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", new DiscordColor("80cc38"));
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.Clans.Alliance, pluginAllianceChat, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate pluginPrivateMessages = CreateTemplateEmbed($"{PlaceholderKeys.TemplateMessage}", new DiscordColor("00FFFF"));
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Chat.PrivateMessages.Message, pluginPrivateMessages, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate errorNotLinked = CreatePrefixedTemplateEmbed("You're not allowed to chat with the server unless you are linked.", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Error.NotLinked, errorNotLinked, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate errorAdminChatNotLinked = CreatePrefixedTemplateEmbed("You're not allowed to use admin chat because you have not linked your Discord and game server accounts", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Error.AdminChat.NotLinked, errorAdminChatNotLinked, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate errorAdminChatNotPermission = CreatePrefixedTemplateEmbed(":no_entry: You're not allowed to use admin chat channel because you do not have permission.", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Error.AdminChat.NoPermission, errorAdminChatNotPermission, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
DiscordMessageTemplate errorBetterChatMuteMuted = CreatePrefixedTemplateEmbed(":no_entry: You're not allowed to chat with the server because you are muted.", DiscordColor.Danger);
_templates.RegisterGlobalTemplateAsync(this, TemplateKeys.Error.BetterChatMute.Muted, errorBetterChatMuteMuted, new TemplateVersion(1, 0, 0), new TemplateVersion(1, 0, 0));
}
public DiscordMessageTemplate CreateTemplateEmbed(string description, DiscordColor color) {
return new DiscordMessageTemplate {
Embeds = new List<DiscordEmbedTemplate> {
new() {
Description = description, Color = color.ToHex()
}
}
}
;
}
public DiscordMessageTemplate CreatePrefixedTemplateEmbed(string description, DiscordColor color) {
return new DiscordMessageTemplate {
Embeds = new List<DiscordEmbedTemplate> {
new() {
Description = $"[{DefaultKeys.Plugin.Name}] {description}", Color = color.ToHex()
}
}
}
;
}
public void SendGlobalTemplateMessage(TemplateKey templateName, DiscordChannel channel, PlaceholderData placeholders) {
if (channel == null) {
return;
}
MessageCreate create = new() {
AllowedMentions = AllowedMentions.None
}
;
channel.CreateGlobalTemplateMessage(Client, templateName, create, placeholders);
}
public TemplateKey GetTemplateName(MessageSource source) {
switch (source) {
case MessageSource.Discord : case MessageSource.Server : return TemplateKeys.Chat.General;
case MessageSource.Team : return TemplateKeys.Chat.Teams;
case MessageSource.Cards : return TemplateKeys.Chat.Cards;
case MessageSource.Clan : return TemplateKeys.Chat.Clan;
case MessageSource.Connecting : return TemplateKeys.Player.Connecting;
case MessageSource.Connected : return TemplateKeys.Player.Connected;
case MessageSource.Disconnected : return TemplateKeys.Player.Disconnected;
case MessageSource.PluginAdminChat : return TemplateKeys.Chat.AdminChat.Message;
case MessageSource.PluginClan : return TemplateKeys.Chat.Clans.Clan;
case MessageSource.PluginAlliance : return TemplateKeys.Chat.Clans.Alliance;
case MessageSource.PluginPrivateMessages : return TemplateKeys.Chat.PrivateMessages.Message;
}
return default;
}
#endregion
#region Configuration\ChatSettings.cs
public class ChatSettings {
[JsonProperty("Chat Channel ID")]
public Snowflake ChatChannel {
get;
set;
}
#if RUST
[JsonProperty("Team Channel ID")]
public Snowflake TeamChannel {
get;
set;
}
[JsonProperty("Cards Channel ID")]
public Snowflake CardsChannel {
get;
set;
}
[JsonProperty("Clans Channel ID")]
public Snowflake ClansChannel {
get;
set;
}
#endif
[JsonProperty("Replace Discord User Message With Bot Message")]
public bool UseBotToDisplayChat {
get;
set;
}
[JsonProperty("Send Messages From Server Chat To Discord Channel")]
public bool ServerToDiscord {
get;
set;
}
[JsonProperty("Send Messages From Discord Channel To Server Chat")]
public bool DiscordToServer {
get;
set;
}
[JsonProperty("Add Discord Tag To In Game Messages When Sent From Discord")]
public string DiscordTag {
get;
set;
}
[JsonProperty("Allow plugins to process Discord to Server Chat Messages")]
public bool AllowPluginProcessing {
get;
set;
}
[JsonProperty("Text Replacements")]
public Hash<string, string> TextReplacements {
get;
set;
}
[JsonProperty("Unlinked Settings")]
public UnlinkedSettings UnlinkedSettings {
get;
set;
}
[JsonProperty("Message Filter Settings")]
public MessageFilterSettings Filter {
get;
set;
}
public ChatSettings(ChatSettings settings) {
ChatChannel = settings?.ChatChannel ?? default(Snowflake);
#if RUST
TeamChannel = settings?.TeamChannel ?? default(Snowflake);
CardsChannel = settings?.CardsChannel ?? default(Snowflake);
#endif
UseBotToDisplayChat = settings?.UseBotToDisplayChat ?? true;
ServerToDiscord = settings?.ServerToDiscord ?? true;
DiscordToServer = settings?.DiscordToServer ?? true;
DiscordTag = settings?.DiscordTag ?? "[#5f79d6][Discord][/#]";
AllowPluginProcessing = settings?.AllowPluginProcessing ?? true;
TextReplacements = settings?.TextReplacements ?? new Hash<string, string> {
["TextToBeReplaced"]
= "ReplacedText"
}
;
UnlinkedSettings = new UnlinkedSettings(settings?.UnlinkedSettings);
Filter = new MessageFilterSettings(settings?.Filter);
}
}
#endregion
#region Configuration\MessageFilterSettings.cs
public class MessageFilterSettings {
[JsonProperty("Ignore messages from users in this list (Discord ID)")]
public List<Snowflake> IgnoreUsers {
get;
set;
}
[JsonProperty("Ignore messages from users in this role (Role ID)")]
public List<Snowflake> IgnoreRoles {
get;
set;
}
[JsonProperty("Ignored Prefixes")]
public List<string> IgnoredPrefixes {
get;
set;
}
public MessageFilterSettings(MessageFilterSettings settings) {
IgnoreUsers = settings?.IgnoreUsers ?? new List<Snowflake>();
IgnoreRoles = settings?.IgnoreRoles ?? new List<Snowflake>();
IgnoredPrefixes = settings?.IgnoredPrefixes ?? new List<string>();
}
public bool IgnoreMessage(DiscordMessage message, GuildMember member) {
return IsIgnoredUser(message.Author, member) || IsIgnoredPrefix(message.Content);
}
public bool IsIgnoredUser(DiscordUser user, GuildMember member) {
if (user.IsBot) {
return true;
}
if (IgnoreUsers.Contains(user.Id)) {
return true;
}
return member != null && IsRoleIgnoredMember(member);
}
public bool IsRoleIgnoredMember(GuildMember member) {
for (int index = 0; index < IgnoreRoles.Count; index++) {
Snowflake role = IgnoreRoles[index];
if (member.Roles.Contains(role)) {
return true;
}
}
return false;
}
public bool IsIgnoredPrefix(string content) {
for (int index = 0; index < IgnoredPrefixes.Count; index++) {
string prefix = IgnoredPrefixes[index];
if (content.StartsWith(prefix)) {
return true;
}
}
return false;
}
}
#endregion
#region Configuration\PlayerStateSettings.cs
public class PlayerStateSettings {
[JsonProperty("Player State Channel ID")]
public Snowflake PlayerStateChannel {
get;
set;
}
[JsonProperty("Show Admins")]
public bool ShowAdmins {
get;
set;
}
[JsonProperty("Send Connecting Message")]
public bool SendConnectingMessage {
get;
set;
}
[JsonProperty("Send Connected Message")]
public bool SendConnectedMessage {
get;
set;
}
[JsonProperty("Send Disconnected Message")]
// ... [Code preview truncated due to length. Full source in attached file] ...