Skip to content

Commit

Permalink
Merge pull request #6 from rust-plugins/develop
Browse files Browse the repository at this point in the history
Discord via webhooks
  • Loading branch information
NickRimmer authored Jan 25, 2020
2 parents ec18735 + ac251ad commit d69a698
Show file tree
Hide file tree
Showing 3 changed files with 121 additions and 120 deletions.
11 changes: 4 additions & 7 deletions Examples/config/TeamsLogger.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
{
"DiscordBot": {
"Api key": "FNoqwinpqupqwuefbweufbAa.dFNWNO.nbpc29bSNiuib198172bp0987b1",
"Channel name": "teams-logger",
"Show server name in status": true
},
"Print logs to console": true,
"Print logs to Discord": true,
"Print logs to file": true
"Print logs to Discord": false,
"Print logs to file": true,

"Discord hook url": null
}
17 changes: 5 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,15 @@ Then restart plugin using command in server console `oxide.reload TeamsLogger`
```JSON
{
"Print logs to console": true,
"Print logs to file": true,
"Print logs to Discord": false,
"Print logs to file": true,

"DiscordBot": {
"Api key": null,
"Channel name": "teams-logger",
"Show server name in status": true
}
"Discord hook url": null
}
```

### Discord extension
To log messages into Discord, you'll need to install [Discord extension](https://umod.org/extensions/discord) and replace text `DISCORD_NOT_INSTALLED` by `DISCORD_INSTALLED` in the beginning of plugin file.

### Discord Api key
To send messages, set `Api key` in configuration file. Instruction how to get this key you will find on [Discord extension page](https://umod.org/extensions/discord#getting-your-api-key).
### Discord
To send logs via Discord, you'll need to configure [Discord WebHook url](https://support.discordapp.com/hc/en-us/articles/228383668-Intro-to-Webhooks).

## Localization
```JSON
Expand All @@ -53,4 +46,4 @@ To file `\oxide\logs\TeamsLogger\teamslogger_common-####-##-##.txt`
17:36:26 Disband 97 | Team leader: 'xan' (76561198051734570)
```
### To Discord
![](https://i.imgur.com/VohQkDJ.png)
![](https://i.imgur.com/tlJiSXg.png)
213 changes: 112 additions & 101 deletions TeamsLogger.cs
Original file line number Diff line number Diff line change
@@ -1,51 +1,32 @@
#define DISCORD_NOT_INSTALLED

using Oxide.Core;
using System;
using System.Linq;
using UnityEngine;
using System.Collections.Generic;
using Newtonsoft.Json;

#if DISCORD_INSTALLED
using Oxide.Ext.Discord;
using Oxide.Ext.Discord.Attributes;
using Oxide.Ext.Discord.DiscordObjects;
#endif
using System.Collections;
using System.Text;
using UnityEngine.Networking;

namespace Oxide.Plugins
{
[Info("Teams Logger", "NickRimmer", "1.3")]
[Info("Teams Logger", "NickRimmer", "1.4")]
[Description("Simple plugin to log team events")]
public class TeamsLogger : RustPlugin
{
#if DISCORD_INSTALLED
[DiscordClient]
private DiscordClient _client;
private Channel _discordChannel;
#endif

private PluginConfig _config;
private DiscordComponent _discord;

void Init()
{
_config = Config.ReadObject<PluginConfig>();
if (IsFirstRun()) LogCurrentTeams();
}

void OnServerInitialized()
{
#if DISCORD_INSTALLED
if (_config.PrintToDiscord) InitDiscord();
#else
if (_config.PrintToDiscord) PrintWarning("To enable Discord features, please define DISCORD_INSTALLED directive");
#endif
}

private void Unload()
{
#if DISCORD_INSTALLED
if (_client != null) Discord.CloseClient(_client);
#endif
if (!string.IsNullOrEmpty(_config.DiscordHookUrl))
{
var loader = new GameObject("WebObject");
_discord = loader.AddComponent<DiscordComponent>().Configure(_config.DiscordHookUrl);
}
}

private void PrintToConsole(string message) => Puts(message);
Expand All @@ -60,25 +41,16 @@ private void PrintToFile(string message)

private void PrintToDiscord(string message)
{
#if DISCORD_INSTALLED
if (_client?.DiscordServer == null)
if(_discord == null)
{
PrintWarning("Discord doesn't connected");
return;
}

if (_discordChannel == null)
{
PrintWarning($"Discord channel with name '{_config.DiscordBot.ChannelName}' not found");
PrintWarning("Discord wasn't configured, message can't be sent");
return;
}

var timestamp = DateTime.Now.ToString("HH:mm:ss");
message = $"{timestamp} | {message}";
_discordChannel.CreateMessage(_client, message);
#else
PrintWarning("To enable discord features, please define DISCORD_INSTALLED directive");
#endif

_discord.SendTextMessage(message);
}

#region Log exist teams on first run
Expand Down Expand Up @@ -119,51 +91,6 @@ private string GetUserInfo(ulong userId)
}
#endregion

#region Discord connection
#if DISCORD_INSTALLED
private void InitDiscord()
{
Puts("Init Discord connection...");
if (string.IsNullOrEmpty(_config.DiscordBot.ApiKey))
{
PrintError($"To enable Discord messages you need to specify 'DiscordConfig.ApiKey' value in config");
return;
}

Discord.CreateClient(this, _config.DiscordBot.ApiKey);
}

void Discord_GuildCreate(Guild guild)
{
if(_config.DiscordBot.EnableBotStatus)
_client.UpdateStatus(new Presence { Game = new Ext.Discord.DiscordObjects.Game
{
Name = covalence.Server.Name,
Type = ActivityType.Watching
}});

UpdateDiscordChannel();
}

void Discord_ChannelCreate(Channel channel) => UpdateDiscordChannel();
void Discord_ChannelUpdate(Channel updatedChannel, Channel oldChannel) => UpdateDiscordChannel();
void Discord_ChannelDelete(Channel channel) => UpdateDiscordChannel();
//void Discord_GuildUpdate(Guild guild) => UpdateDiscordChannel();

private void UpdateDiscordChannel()
{
_discordChannel = _client
.DiscordServer
.channels
.FirstOrDefault(x => x.name.Equals(_config.DiscordBot.ChannelName, StringComparison.InvariantCultureIgnoreCase));

if (_discordChannel == null) PrintWarning($"Discord channel with name '{_config.DiscordBot.ChannelName}' not found");
else Puts($"Connected to discord channel: '{_discordChannel.name}' ({_discordChannel.id})");
}

#endif
#endregion

#region Team hooks

void OnTeamInvite(BasePlayer inviter, BasePlayer target) => LogKey(
Expand Down Expand Up @@ -302,26 +229,110 @@ private class PluginConfig
[JsonProperty("Print logs to Discord")]
public bool PrintToDiscord { get; set; } = false;

public PluginDiscordConfig DiscordBot = new PluginDiscordConfig();
[JsonProperty("Discord hook url")]
public string DiscordHookUrl { get; set; }
}

private class PluginData
{
public bool FirstStart { get; set; } = true;
}

public class PluginDiscordConfig
#endregion

#region Shared.Components

private class DiscordComponent : MonoBehaviour
{
private const float PostDelay = 1f;

private readonly Queue<object> _queue = new Queue<object>();
private string _url;
private bool _busy = false;

public DiscordComponent Configure(string url)
{
[JsonProperty("Api key")]
public string ApiKey { get; set; }
if (url == null) throw new ArgumentNullException(nameof(url));
_url = url;

[JsonProperty("Channel name")]
public string ChannelName { get; set; } = "teams-logger";
return this;
}

[JsonProperty("Show server name in status")]
public bool EnableBotStatus { get; set; } = true;
public DiscordComponent SendTextMessage(string message, params object[] args)
{
message = args?.Any() == true ? string.Format(message, args) : message;
return AddQueue(new MessageRequest(message));
}
}

private class PluginData
{
public bool FirstStart { get; set; } = true;
#region Send requests to server

private DiscordComponent AddQueue(object request)
{
_queue.Enqueue(request);

if (!_busy)
StartCoroutine(ProcessQueue());

return this;
}

private IEnumerator ProcessQueue()
{
if(_busy) yield break;
_busy = true;

while (_queue.Any())
{
var request = _queue.Dequeue();
yield return ProcessRequest(request);
}

_busy = false;
}

private IEnumerator ProcessRequest(object request)
{
if (string.IsNullOrEmpty(_url))
{
print("[ERROR] Discord webhook URL wasn't specified");
yield break;
}

var data = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(request));
var uh = new UploadHandlerRaw(data) {contentType = "application/json"};
var www = UnityWebRequest.Post(_url, UnityWebRequest.kHttpVerbPOST);
www.uploadHandler = uh;

yield return www.SendWebRequest();

if (www.isNetworkError || www.isHttpError)
print($"ERROR: {www.error} | {www.downloadHandler?.text}");

www.Dispose();

// to avoid spam requests to Discord
yield return new WaitForSeconds(PostDelay);
}

#endregion

#region Requests

private class MessageRequest
{
[JsonProperty("content")]
public string Content { get; set; }

public MessageRequest(string content)
{
if (content == null) throw new ArgumentNullException(nameof(content));
Content = content;
}
}

#endregion
}

#endregion
}
}
}

0 comments on commit d69a698

Please sign in to comment.