Exceptions are now forwarded to the JoinLeaveLog channel (now renamed to GuildLogging; see the example config)

This commit is contained in:
Leah Husted 2019-08-17 00:50:20 -05:00
parent cb467d9110
commit ad1691d709
6 changed files with 68 additions and 24 deletions

View file

@ -19,8 +19,8 @@
//same as above but for failures
"log_all_commands": true,
//whether or not to log all commands to the bot's console; enabled by default
"join_leave_log": {
//send a log of the bot's joins/leaves to a channel within a certain guild
"guild_logging": {
//send a log of the bot's guild joins/leaves, as well as any exceptions that occur
"enabled": false,
"guild_id": 0,
"channel_id": 0

View file

@ -1,4 +1,5 @@
using System.Diagnostics;
using System;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Discord.WebSocket;

View file

@ -31,7 +31,7 @@ namespace Volte.Core
SuccessEmbedColor = 0x7000FB,
ErrorEmbedColor = 0xFF0000,
LogAllCommands = true,
JoinLeaveLog = new JoinLeaveLog(),
GuildLogging = new GuildLogging(),
BlacklistedGuildOwners = new ulong[] { },
EnabledFeatures = new EnabledFeatures()
};
@ -90,7 +90,7 @@ namespace Volte.Core
public static bool LogAllCommands => _configuration.LogAllCommands;
public static JoinLeaveLog JoinLeaveLog => _configuration.JoinLeaveLog;
public static GuildLogging GuildLogging => _configuration.GuildLogging;
public static IEnumerable<ulong> BlacklistedOwners => _configuration.BlacklistedGuildOwners;
@ -126,8 +126,8 @@ namespace Volte.Core
[JsonProperty("log_all_commands")]
public bool LogAllCommands { get; internal set; }
[JsonProperty("join_leave_log")]
public JoinLeaveLog JoinLeaveLog { get; internal set; }
[JsonProperty("guild_logging")]
public GuildLogging GuildLogging { get; internal set; }
[JsonProperty("blacklisted_guild_owners")]
public ulong[] BlacklistedGuildOwners { get; internal set; }

View file

@ -2,9 +2,9 @@ using Newtonsoft.Json;
namespace Volte.Core.Models.BotConfig
{
public sealed class JoinLeaveLog
public sealed class GuildLogging
{
internal JoinLeaveLog()
internal GuildLogging()
{
Enabled = false;
GuildId = ulong.MinValue;

View file

@ -1,5 +1,5 @@
using System;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using Discord;
@ -48,7 +48,7 @@ namespace Volte.Services
.ToString())
.AddField("Support Server", "[Join my support Discord here](https://discord.gg/H8bcFr2)");
_logger.Error(LogSource.Volte,
_logger.Debug(LogSource.Volte,
"Attempting to send the guild owner the introduction message.");
try
{
@ -56,7 +56,7 @@ namespace Volte.Services
_logger.Error(LogSource.Volte,
"Sent the guild owner the introduction message.");
}
catch (HttpException ex) when (ex.DiscordCode is 50007)
catch (HttpException ex) when (ex.HttpCode is HttpStatusCode.Forbidden)
{
var c = args.Guild.TextChannels.OrderByDescending(x => x.Position).FirstOrDefault();
_logger.Error(LogSource.Volte,
@ -64,20 +64,20 @@ namespace Volte.Services
if (c != null) await embed.SendToAsync(c);
}
if (!Config.JoinLeaveLog.Enabled) return;
var joinLeave = Config.JoinLeaveLog;
if (joinLeave.GuildId is 0 || joinLeave.ChannelId is 0)
if (!Config.GuildLogging.Enabled) return;
var guildLogging = Config.GuildLogging;
if (guildLogging.GuildId is 0 || guildLogging.ChannelId is 0)
{
_logger.Error(LogSource.Volte,
"Invalid value set for the GuildId or ChannelId in the JoinLeaveLog config option. " +
"To fix, set Enabled to false, or correctly fill in your options.");
"Invalid value set for the guild_id or channel_id in the guild_logging config section. " +
"To fix, set enabled to false, or correctly fill in your options.");
return;
}
var channel = _client.GetGuild(joinLeave.GuildId).GetTextChannel(joinLeave.ChannelId);
var channel = _client.GetGuild(guildLogging.GuildId)?.GetTextChannel(guildLogging.ChannelId);
if (channel is null)
{
_logger.Error(LogSource.Volte, "Invalid JoinLeaveLog.GuildId/JoinLeaveLog.ChannelId configuration. Check your IDs and try again.");
_logger.Error(LogSource.Volte, "Invalid guild_logging.guild_id/guild_logging.channel_id configuration. Check your IDs and try again.");
return;
}
@ -100,14 +100,14 @@ namespace Volte.Services
$"{_client.GetOwner().Mention}: Joined a guild with more bots than users.", false,
e.WithSuccessColor().Build());
else
await channel.SendMessageAsync("", false, e.WithSuccessColor().Build());
await e.WithSuccessColor().SendToAsync(channel);
}
public async Task OnLeaveAsync(LeftGuildEventArgs args)
{
_logger.Debug(LogSource.Volte, "Left a guild.");
if (!Config.JoinLeaveLog.Enabled) return;
var joinLeave = Config.JoinLeaveLog;
if (!Config.GuildLogging.Enabled) return;
var joinLeave = Config.GuildLogging;
if (joinLeave.GuildId is 0 || joinLeave.ChannelId is 0)
{
_logger.Error(LogSource.Volte,

View file

@ -1,10 +1,16 @@
using System;
using System.IO;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using Discord;
using Discord.WebSocket;
using Gommon;
using Humanizer;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using RestSharp;
using Volte.Core;
using Volte.Core.Models;
using Volte.Core.Models.EventArgs;
@ -15,8 +21,18 @@ namespace Volte.Services
{
public sealed class LoggingService : VolteEventService
{
private readonly DiscordShardedClient _client;
private readonly HttpClient _http;
private readonly object _lock;
private const string LogFile = "data/Volte.log";
private readonly object _lock = new object();
public LoggingService(DiscordShardedClient discordShardedClient,
HttpClient httpClient)
{
_client = discordShardedClient;
_http = httpClient;
_lock = new object();
}
public override Task DoAsync(EventArgs args)
{
@ -97,7 +113,7 @@ namespace Volte.Services
/// </summary>
/// <param name="e">Exception to print.</param>
public void LogException(Exception e)
=> Log(LogSeverity.Error, LogSource.Volte, string.Empty, e);
=> Execute(LogSeverity.Error, LogSource.Volte, string.Empty, e);
private void Execute(LogSeverity s, LogSource src, string message, Exception e)
{
@ -122,6 +138,7 @@ namespace Volte.Services
var toWrite = $"{Environment.NewLine}{e.Message}{Environment.NewLine}{e.StackTrace}";
Append(toWrite, Color.IndianRed);
content.Append(toWrite);
LogExceptionInDiscord(e);
}
Console.Write(Environment.NewLine);
@ -163,5 +180,31 @@ namespace Volte.Services
LogSeverity.Debug => (Color.SandyBrown, "DEBG"),
_ => throw new ArgumentNullException(nameof(severity), "severity cannot be null")
};
private void LogExceptionInDiscord(Exception e)
{
if (!Config.GuildLogging.Enabled) return;
var guildLogging = Config.GuildLogging;
var channel = _client.GetGuild(guildLogging.GuildId)?.GetTextChannel(guildLogging.ChannelId);
if (channel is null)
{
Error(LogSource.Volte, "Invalid guild_logging.guild_id/guild_logging.channel_id configuration. Check your IDs and try again.");
return;
}
_ = Task.Run(async () =>
{
var response = await _http.PostAsync("https://paste.greemdev.net/documents", new StringContent(e.StackTrace, Encoding.UTF8, "text/plain"));
var respObj = JObject.Parse(await response.Content.ReadAsStringAsync());
var url = $"https://paste.greemdev.net/{respObj.GetValue("key")}.cs";
var embed = new EmbedBuilder()
.WithErrorColor()
.WithTitle($"Exception at {DateTimeOffset.UtcNow.FormatDate()}, {DateTimeOffset.UtcNow.FormatFullTime()} UTC")
.AddField("Exception Type", e.GetType(), true)
.AddField("Exception Message", e.Message, true)
.WithDescription($"View the full Stack Trace [here]({url}).");
await embed.SendToAsync(channel);
});
}
}
}