Skip to content

Feat: Misc Fixes & Recruitment Service #260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Aug 3, 2023
5 changes: 4 additions & 1 deletion DiscordBot/Extensions/UserExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,10 @@ public static bool HasRoleGroup(this IUser user, SocketRole role)
}
public static bool HasRoleGroup(this IUser user, ulong roleId)
{
return user is SocketGuildUser guildUser && guildUser.Roles.Any(x => x.Id == roleId);
var guildUser = user as IGuildUser;
if (guildUser == null)
return false;
return guildUser.RoleIds.Any(x => x == roleId);
}

// Returns the users DisplayName (nickname) if it exists, otherwise returns the username
Expand Down
3 changes: 2 additions & 1 deletion DiscordBot/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public class Program
private IServiceProvider _services;

private UnityHelpService _unityHelpService;
private RecruitService _recruitService;

public static void Main(string[] args) =>
new Program().MainAsync().GetAwaiter().GetResult();
Expand Down Expand Up @@ -68,7 +69,7 @@ private async Task MainAsync()
_isInitialized = true;

_unityHelpService = _services.GetRequiredService<UnityHelpService>();
_services.GetRequiredService<RecruitService>();
_recruitService = _services.GetRequiredService<RecruitService>();
}
return Task.CompletedTask;
};
Expand Down
20 changes: 10 additions & 10 deletions DiscordBot/Services/FeedService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ namespace DiscordBot.Services;

public class FeedService
{
private const string ServiceName = "FeedService";
private readonly DiscordSocketClient _client;

private readonly BotSettings _settings;
Expand Down Expand Up @@ -72,13 +73,12 @@ private async Task<SyndicationFeed> GetFeedData(string url)
var client = new HttpClient();
var response = await client.GetStringAsync(url);
response = Utils.Utils.SanitizeXml(response);
XmlReader reader = new XmlTextReader(new StringReader(response));
var reader = XmlReader.Create(new StringReader(response));
feed = SyndicationFeed.Load(reader);
}
catch (Exception e)
{
LoggingService.LogToConsole(e.ToString(), LogSeverity.Error);
await _logging.LogAction($"Feed Service Error: {e.ToString()}", true, true);
LoggingService.LogToConsole( $"[{ServiceName} Feed failure: {e.ToString()}", ExtendedLogSeverity.LowWarning);
}

// Return the feed, empty feed if null to prevent additional checks for null on return
Expand All @@ -97,8 +97,8 @@ private async Task HandleFeed(FeedData feedData, ForumNewsFeed newsFeed, ulong c
var channel = _client.GetChannel(channelId) as IForumChannel;
if (channel == null)
{
await _logging.LogAction($"Feed Service Error: Channel {channelId} not found", true, true);
LoggingService.LogToConsole($"Feed Service Error: Channel {channelId} not found", LogSeverity.Error);
await _logging.LogAction($"[{ServiceName}] Error: Channel {channelId} not found", true, true);
LoggingService.LogToConsole($"[{ServiceName}] Error: Channel {channelId} not found", LogSeverity.Error);
return;
}
foreach (var item in feed.Items.Take(MaximumCheck))
Expand All @@ -110,7 +110,7 @@ private async Task HandleFeed(FeedData feedData, ForumNewsFeed newsFeed, ulong c
// Title
var newsTitle = string.Format(newsFeed.TitleFormat, item.Title.Text);
if (newsTitle.Length > 90)
newsTitle = newsTitle.Substring(0, 95) + "...";
newsTitle = newsTitle[..90] + "...";

// Confirm we haven't posted this title before
if (_postedFeeds.Contains(newsTitle))
Expand All @@ -126,8 +126,8 @@ private async Task HandleFeed(FeedData feedData, ForumNewsFeed newsFeed, ulong c
var summary = Utils.Utils.RemoveHtmlTags(item.Summary.Text);
newsContent = "**__Summary__**\n" + summary;
// Unlikely to be over, but we need space for extra local info
if (newsContent.Length > Constants.MaxLengthChannelMessage - 100)
newsContent = newsContent.Substring(0, Constants.MaxLengthChannelMessage - 100) + "...";
if (newsContent.Length > Constants.MaxLengthChannelMessage - 400)
newsContent = newsContent[..(Constants.MaxLengthChannelMessage - 400)] + "...";
}
// If a role is provided we add to end of title to ping the role
var role = _client.GetGuild(_settings.GuildId).GetRole(roleId ?? 0);
Expand All @@ -140,7 +140,7 @@ private async Task HandleFeed(FeedData feedData, ForumNewsFeed newsFeed, ulong c
// The Post
var post = await channel.CreatePostAsync(newsTitle, ForumArchiveDuration, null, newsContent, null, null, AllowedMentions.All);
// If any tags, include them
if (newsFeed.IncludeTags != null && newsFeed.IncludeTags.Count > 0)
if (newsFeed.IncludeTags is { Count: > 0 })
{
var includedTags = new List<ulong>();
foreach (var tag in newsFeed.IncludeTags)
Expand All @@ -157,7 +157,7 @@ private async Task HandleFeed(FeedData feedData, ForumNewsFeed newsFeed, ulong c
catch (Exception e)
{
LoggingService.LogToConsole(e.ToString(), LogSeverity.Error);
await _logging.LogAction($"Feed Service Error: {e.ToString()}", true, true);
await _logging.LogAction($"[{ServiceName}] Error: {e.ToString()}", true, true);
}
}

Expand Down
37 changes: 34 additions & 3 deletions DiscordBot/Services/Recruitment/RecruitService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public class RecruitService
private Color WarningMessageColor => new (255, 255, 100);
private Color EditedMessageColor => new (100, 255, 100);

private const int TimeBeforeDeletingForumInSec = 30;
private const int TimeBeforeDeletingForumInSec = 60;
private const string _messageToBeDeleted = "Your thread will be deleted in %s because it did not follow the expected guidelines. Try again after the slow mode period has passed.";

private const int MinimumLengthMessage = 120;
Expand Down Expand Up @@ -97,6 +97,7 @@ public RecruitService(DiscordSocketClient client, ILoggingService logging, BotSe

// Subscribe to events
_client.ThreadCreated += GatewayOnThreadCreated;
_client.MessageReceived += GatewayOnMessageReceived;

ConstructEmbeds();

Expand Down Expand Up @@ -138,7 +139,7 @@ private async Task GatewayOnThreadCreated(SocketThreadChannel thread)

Task.Run(async () =>
{
if (thread.AppliedTags.Count == 0)
if (!DoesThreadHaveAValidTag(thread))
{
await ThreadHandleNoTags(thread);
return;
Expand Down Expand Up @@ -191,6 +192,27 @@ private async Task GatewayOnThreadCreated(SocketThreadChannel thread)
}
});
}

private async Task GatewayOnMessageReceived(SocketMessage message)
{
var thread = message.Channel as SocketThreadChannel;
// check if channel is a thread in a forum
if (thread == null)
return;

if (!thread.IsThreadInChannel(_recruitChannel.Id))
return;
if (message.Author.IsUserBotOrWebhook())
return;
if (message.Author.HasRoleGroup(ModeratorRole))
return;

// Sanity process, delete any new messages that aren't written from the thread owner, moderators or bots.
if (message.Author.Id != thread.Owner.Id)
{
await message.DeleteAsync();
}
}

#endregion // Thread Creation

Expand Down Expand Up @@ -241,8 +263,11 @@ private async Task GrantEditPermissions(SocketThreadChannel thread)
await parentChannel.AddPermissionOverwriteAsync(thread.Owner, new OverwritePermissions(sendMessages: PermValue.Allow));

// We give them a bit of time to edit their post, then remove the permission
await message.DeleteAfterSeconds((_editTimePermissionInMin * 60) + 5);
await message.DeleteAfterSeconds((_editTimePermissionInMin * 60) + 2);
await parentChannel.RemovePermissionOverwriteAsync(thread.Owner);

// Lock the thread so anyone else can't post even when they have edit permissions
await thread.ModifyAsync(x => x.Locked = true);
}

#endregion // Basic Handlers for posts
Expand Down Expand Up @@ -347,6 +372,12 @@ private bool IsThreadUsingMoreThanOneTag(SocketThreadChannel thread)

return clashingTagCount > 1;
}

private bool DoesThreadHaveAValidTag(SocketThreadChannel thread)
{
var tags = thread.AppliedTags;
return tags.Contains(_tagIsHiring.Id) || tags.Contains(_tagWantsWork.Id) || tags.Contains(_tagUnpaidCollab.Id);
}

private async Task DeleteThread(SocketThreadChannel thread)
{
Expand Down
8 changes: 5 additions & 3 deletions DiscordBot/Services/ReminderService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ public class ReminderService
private readonly BotCommandsChannel _botCommandsChannel;
private bool _hasChangedSinceLastSave = false;

private int _maxUserReminders = 5;
private const int _maxUserReminders = 10;

public ReminderService(DiscordSocketClient client, ILoggingService loggingService, BotSettings settings)
{
_client = client;
Expand Down Expand Up @@ -160,7 +160,9 @@ private async Task CheckReminders()
// If channel is null we get the bot command channel, and send the message there
channel ??= _client.GetChannel(_botCommandsChannel.Id) as SocketTextChannel;
var user = _client.GetUser(reminder.UserId);
if (user != null)
if (user == null) continue;

if (channel != null)
await channel.SendMessageAsync(
$"{user.Mention} reminder: \"{reminder.Message}\"");
}
Expand Down
2 changes: 1 addition & 1 deletion DiscordBot/Utils/StringUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace DiscordBot.Utils;
public static class StringUtil
{
private static readonly Regex CurrencyRegex =
new (@"(?:\$\s*\d+|\d+\s*\$|\d*\s*(?:USD|£|pounds|€|EUR|euro|euros|GBP))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
new (@"(?:\$\s*\d+|\d+\s*\$|\d*\s*(?:USD|£|pounds|€|EUR|euro|euros|GBP|円|YEN))", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));
private static readonly Regex RevShareRegex = new (@"\b(?:rev-share|revshare|rev share)\b", RegexOptions.IgnoreCase, TimeSpan.FromMilliseconds(250));

// a string extension that checks if the contents of the string contains a limited selection of currency symbols/words
Expand Down