Split Geekbot.net into src/Bot, src/Core, and src/Web

This commit is contained in:
runebaas 2020-08-08 22:24:01 +02:00
parent 7b6dd2d2f9
commit fc0af492ad
No known key found for this signature in database
GPG key ID: 2677AF508D0300D6
197 changed files with 542 additions and 498 deletions

View file

@ -0,0 +1,126 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using Discord.Rest;
using Discord.WebSocket;
using Geekbot.Core.Database;
using Geekbot.Core.Database.Models;
using Geekbot.Core.GuildSettingsManager;
using Geekbot.Core.Logger;
namespace Geekbot.Bot.Handlers
{
public class CommandHandler
{
private readonly IDiscordClient _client;
private readonly IGeekbotLogger _logger;
private readonly IServiceProvider _servicesProvider;
private readonly CommandService _commands;
private readonly RestApplication _applicationInfo;
private readonly IGuildSettingsManager _guildSettingsManager;
private readonly List<ulong> _ignoredServers;
private readonly DatabaseContext _database;
public CommandHandler(DatabaseContext database, IDiscordClient client, IGeekbotLogger logger, IServiceProvider servicesProvider, CommandService commands, RestApplication applicationInfo,
IGuildSettingsManager guildSettingsManager)
{
_database = database;
_client = client;
_logger = logger;
_servicesProvider = servicesProvider;
_commands = commands;
_applicationInfo = applicationInfo;
_guildSettingsManager = guildSettingsManager;
// Some guilds only want very specific functionally without any of the commands, a quick hack that solves that "short term"
// ToDo: create a clean solution for this...
_ignoredServers = new List<ulong>
{
228623803201224704, // SwitzerLAN
169844523181015040, // EEvent
248531441548263425, // MYI
110373943822540800 // Discord Bots
};
}
public Task RunCommand(SocketMessage messageParam)
{
try
{
if (!(messageParam is SocketUserMessage message)) return Task.CompletedTask;
if (message.Author.IsBot) return Task.CompletedTask;
ulong guildId = message.Author switch
{
SocketGuildUser user => user.Guild.Id,
_ => 0 // DM Channel
};
if (IsIgnoredGuild(guildId, message.Author.Id)) return Task.CompletedTask;
var lowCaseMsg = message.ToString().ToLower();
if (ShouldHui(lowCaseMsg, guildId))
{
message.Channel.SendMessageAsync("hui!!!");
return Task.CompletedTask;
}
if (ShouldPong(lowCaseMsg, guildId))
{
message.Channel.SendMessageAsync("pong");
return Task.CompletedTask;
}
var argPos = 0;
if (!IsCommand(message, ref argPos)) return Task.CompletedTask;
ExecuteCommand(message, argPos);
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Failed to Process Message", e);
}
return Task.CompletedTask;
}
private void ExecuteCommand(IUserMessage message, int argPos)
{
var context = new CommandContext(_client, message);
_commands.ExecuteAsync(context, argPos, _servicesProvider);
_logger.Information(LogSource.Command, context.Message.Content.Split(" ")[0].Replace("!", ""), SimpleConextConverter.ConvertContext(context));
}
private bool IsIgnoredGuild(ulong guildId, ulong authorId)
{
if (!_ignoredServers.Contains(guildId)) return false;
return authorId == _applicationInfo.Owner.Id;
}
private bool IsCommand(IUserMessage message, ref int argPos)
{
return message.HasCharPrefix('!', ref argPos) || message.HasMentionPrefix(_client.CurrentUser, ref argPos);
}
private bool ShouldPong(string lowerCaseMessage, ulong guildId)
{
if (!lowerCaseMessage.StartsWith("ping ") && !lowerCaseMessage.Equals("ping")) return false;
if (guildId == 0) return true;
return GetGuildSettings(guildId)?.Ping ?? false;
}
private bool ShouldHui(string lowerCaseMessage, ulong guildId)
{
if (!lowerCaseMessage.StartsWith("hui")) return false;
if (guildId == 0) return true;
return GetGuildSettings(guildId)?.Hui ?? false;
}
private GuildSettingsModel GetGuildSettings(ulong guildId)
{
return _guildSettingsManager.GetSettings(guildId, false);
}
}
}

View file

@ -0,0 +1,55 @@
using System;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using Geekbot.Core.Database;
using Geekbot.Core.Extensions;
using Geekbot.Core.Logger;
namespace Geekbot.Bot.Handlers
{
public class MessageDeletedHandler
{
private readonly DatabaseContext _database;
private readonly IGeekbotLogger _logger;
private readonly IDiscordClient _client;
public MessageDeletedHandler(DatabaseContext database, IGeekbotLogger logger, IDiscordClient client)
{
_database = database;
_logger = logger;
_client = client;
}
public async Task HandleMessageDeleted(Cacheable<IMessage, ulong> message, ISocketMessageChannel channel)
{
try
{
var guildSocketData = ((IGuildChannel) channel).Guild;
var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(guildSocketData.Id.AsLong()));
if ((guild?.ShowDelete ?? false) && guild?.ModChannel != 0)
{
var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong());
var sb = new StringBuilder();
if (message.Value != null)
{
sb.AppendLine($"The following message from {message.Value.Author.Username}#{message.Value.Author.Discriminator} was deleted in <#{channel.Id}>");
sb.AppendLine(message.Value.Content);
}
else
{
sb.AppendLine("Someone deleted a message, the message was not cached...");
}
await modChannelSocket.SendMessageAsync(sb.ToString());
}
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Failed to send delete message...", e);
}
}
}
}

View file

@ -0,0 +1,33 @@
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using Geekbot.Core.ReactionListener;
namespace Geekbot.Bot.Handlers
{
public class ReactionHandler
{
private readonly IReactionListener _reactionListener;
public ReactionHandler(IReactionListener reactionListener)
{
_reactionListener = reactionListener;
}
public Task Added(Cacheable<IUserMessage, ulong> cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction)
{
if (reaction.User.Value.IsBot) return Task.CompletedTask;
if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask;
_reactionListener.GiveRole(socketMessageChannel, reaction);
return Task.CompletedTask;
}
public Task Removed(Cacheable<IUserMessage, ulong> cacheable, ISocketMessageChannel socketMessageChannel, SocketReaction reaction)
{
if (reaction.User.Value.IsBot) return Task.CompletedTask;
if (!_reactionListener.IsListener(reaction.MessageId)) return Task.CompletedTask;
_reactionListener.RemoveRole(socketMessageChannel, reaction);
return Task.CompletedTask;
}
}
}

View file

@ -0,0 +1,62 @@
using System;
using System.Threading.Tasks;
using Discord.WebSocket;
using Geekbot.Core.Database;
using Geekbot.Core.Database.Models;
using Geekbot.Core.Extensions;
using Geekbot.Core.Logger;
using Microsoft.EntityFrameworkCore;
namespace Geekbot.Bot.Handlers
{
public class StatsHandler
{
private readonly IGeekbotLogger _logger;
private readonly DatabaseContext _database;
public StatsHandler(IGeekbotLogger logger, DatabaseContext database)
{
_logger = logger;
_database = database;
}
public async Task UpdateStats(SocketMessage message)
{
try
{
if (message == null) return;
if (message.Channel.Name.StartsWith('@'))
{
_logger.Information(LogSource.Message, $"[DM-Channel] {message.Content}", SimpleConextConverter.ConvertSocketMessage(message, true));
return;
}
var channel = (SocketGuildChannel) message.Channel;
var rowId = await _database.Database.ExecuteSqlRawAsync(
"UPDATE \"Messages\" SET \"MessageCount\" = \"MessageCount\" + 1 WHERE \"GuildId\" = {0} AND \"UserId\" = {1}",
channel.Guild.Id.AsLong(),
message.Author.Id.AsLong()
);
if (rowId == 0)
{
await _database.Messages.AddAsync(new MessagesModel
{
UserId = message.Author.Id.AsLong(),
GuildId = channel.Guild.Id.AsLong(),
MessageCount = 1
});
await _database.SaveChangesAsync();
}
if (message.Author.IsBot) return;
_logger.Information(LogSource.Message, message.Content, SimpleConextConverter.ConvertSocketMessage(message));
}
catch (Exception e)
{
_logger.Error(LogSource.Message, "Could not process message stats", e);
}
}
}
}

View file

@ -0,0 +1,96 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using Discord;
using Discord.Rest;
using Discord.WebSocket;
using Geekbot.Core.Database;
using Geekbot.Core.Extensions;
using Geekbot.Core.Logger;
using Geekbot.Core.UserRepository;
namespace Geekbot.Bot.Handlers
{
public class UserHandler
{
private readonly IUserRepository _userRepository;
private readonly IGeekbotLogger _logger;
private readonly DatabaseContext _database;
private readonly IDiscordClient _client;
public UserHandler(IUserRepository userRepository, IGeekbotLogger logger, DatabaseContext database, IDiscordClient client)
{
_userRepository = userRepository;
_logger = logger;
_database = database;
_client = client;
}
public async Task Joined(SocketGuildUser user)
{
try
{
var userRepoUpdate = _userRepository.Update(user);
_logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})");
if (!user.IsBot)
{
var guildSettings = _database.GuildSettings.FirstOrDefault(guild => guild.GuildId == user.Guild.Id.AsLong());
var message = guildSettings?.WelcomeMessage;
if (string.IsNullOrEmpty(message)) return;
message = message.Replace("$user", user.Mention);
var fallbackSender = new Func<Task<RestUserMessage>>(() => user.Guild.DefaultChannel.SendMessageAsync(message));
if (guildSettings.WelcomeChannel != 0)
{
try
{
var target = await _client.GetChannelAsync(guildSettings.WelcomeChannel.AsUlong());
var channel = target as ISocketMessageChannel;
await channel.SendMessageAsync(message);
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Failed to send welcome message to user defined welcome channel", e);
await fallbackSender();
}
}
else
{
await fallbackSender();
}
}
await userRepoUpdate;
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Failed to send welcome message", e);
}
}
public async Task Updated(SocketUser oldUser, SocketUser newUser)
{
await _userRepository.Update(newUser);
}
public async Task Left(SocketGuildUser user)
{
try
{
var guild = _database.GuildSettings.FirstOrDefault(g => g.GuildId.Equals(user.Guild.Id.AsLong()));
if (guild?.ShowLeave ?? false)
{
var modChannelSocket = (ISocketMessageChannel) await _client.GetChannelAsync(guild.ModChannel.AsUlong());
await modChannelSocket.SendMessageAsync($"{user.Username}#{user.Discriminator} left the server");
}
}
catch (Exception e)
{
_logger.Error(LogSource.Geekbot, "Failed to send leave message", e);
}
_logger.Information(LogSource.Geekbot, $"{user.Username} ({user.Id}) joined {user.Guild.Name} ({user.Guild.Id})");
}
}
}