Added 'afk <msg>? command which sets an afk message which will trigger whenever someone pings a user.

This commit is contained in:
Toastie (DCS Team) 2024-07-18 21:54:45 +12:00
parent d07066adec
commit afa00c8d4f
Signed by: toastie_t0ast
GPG key ID: 27F3B6855AFD40A4
4 changed files with 158 additions and 95 deletions

View file

@ -2,6 +2,13 @@
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except date format. a-c-f-r-o Mostly based on [keepachangelog](https://keepachangelog.com/en/1.1.0/) except date format. a-c-f-r-o
### Added
- Added: Added a `'afk <msg>?` command which sets an afk message which will trigger whenever someone pings you
- Message will when you type a message in any channel that the bot sees, or after 8 hours, whichever comes first
- The specified message will be prefixed with "The user is afk: "
- The afk message will disappear 30 seconds after being triggered
## [5.1.4] - 15.07.2024 ## [5.1.4] - 15.07.2024
### Added ### Added

View file

@ -0,0 +1,148 @@
using EllieBot.Common.ModuleBehaviors;
namespace EllieBot.Modules.Utility;
public sealed class AfkService : IEService, IReadyExecutor
{
private readonly IBotCache _cache;
private readonly DiscordSocketClient _client;
private readonly MessageSenderService _mss;
private static readonly TimeSpan _maxAfkDuration = 8.Hours();
public AfkService(IBotCache cache, DiscordSocketClient client, MessageSenderService mss)
{
_cache = cache;
_client = client;
_mss = mss;
}
private static TypedKey<string> GetKey(ulong userId)
=> new($"afk:msg:{userId}");
public async Task<bool> SetAfkAsync(ulong userId, string text)
{
var added = await _cache.AddAsync(GetKey(userId), text, _maxAfkDuration, overwrite: true);
async Task StopAfk(SocketMessage socketMessage)
{
try
{
if (socketMessage.Author?.Id == userId)
{
await _cache.RemoveAsync(GetKey(userId));
_client.MessageReceived -= StopAfk;
// write the message saying afk status cleared
if (socketMessage.Channel is ITextChannel tc)
{
_ = Task.Run(async () =>
{
var msg = await _mss.Response(tc).Confirm("AFK message cleared!").SendAsync();
msg.DeleteAfter(5);
});
}
}
}
catch (Exception ex)
{
Log.Warning("Unexpected error occurred while trying to stop afk: {Message}", ex.Message);
}
}
_client.MessageReceived += StopAfk;
_ = Task.Run(async () =>
{
await Task.Delay(_maxAfkDuration);
_client.MessageReceived -= StopAfk;
});
return added;
}
public Task OnReadyAsync()
{
_client.MessageReceived += TryTriggerAfkMessage;
return Task.CompletedTask;
}
private Task TryTriggerAfkMessage(SocketMessage arg)
{
if (arg.Author.IsBot)
return Task.CompletedTask;
if (arg is not IUserMessage uMsg || uMsg.Channel is not ITextChannel tc)
return Task.CompletedTask;
if ((arg.MentionedUsers.Count is 0 or > 3) && uMsg.ReferencedMessage is null)
return Task.CompletedTask;
_ = Task.Run(async () =>
{
var botUser = await tc.Guild.GetCurrentUserAsync();
var perms = botUser.GetPermissions(tc);
if (!perms.SendMessages)
return;
ulong mentionedUserId = 0;
if (arg.MentionedUsers.Count <= 3)
{
foreach (var uid in uMsg.MentionedUserIds)
{
if (uid == arg.Author.Id)
continue;
if (arg.Content.StartsWith($"<@{uid}>") || arg.Content.StartsWith($"<@!{uid}>"))
{
mentionedUserId = uid;
break;
}
}
}
if (mentionedUserId == 0)
{
if (uMsg.ReferencedMessage?.Author?.Id is not ulong repliedUserId)
{
return;
}
mentionedUserId = repliedUserId;
}
try
{
var result = await _cache.GetAsync(GetKey(mentionedUserId));
if (result.TryPickT0(out var msg, out _))
{
var st = SmartText.CreateFrom(msg);
st = "The user is AFK: " + st;
var toDelete = await _mss.Response(arg.Channel)
.Message(uMsg)
.Text(st)
.Sanitize(false)
.SendAsync();
toDelete.DeleteAfter(30);
}
}
catch (HttpException ex)
{
Log.Warning("Error in afk service: {Message}", ex.Message);
}
});
return Task.CompletedTask;
}
}

View file

@ -7,7 +7,6 @@ using System.Text.Json;
using System.Text.Json.Serialization; using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.CodeAnalysis.CSharp.Scripting;
using Microsoft.CodeAnalysis.Scripting; using Microsoft.CodeAnalysis.Scripting;
using EllieBot.Common.ModuleBehaviors;
using EllieBot.Modules.Games.Hangman; using EllieBot.Modules.Games.Hangman;
using EllieBot.Modules.Searches.Common; using EllieBot.Modules.Searches.Common;
@ -702,7 +701,7 @@ public partial class Utility : EllieModule
} }
[Cmd] [Cmd]
public async Task Afk([Leftover] string text) public async Task Afk([Leftover] string text = "No reason specified.")
{ {
var succ = await _afkService.SetAfkAsync(ctx.User.Id, text); var succ = await _afkService.SetAfkAsync(ctx.User.Id, text);
@ -778,95 +777,3 @@ public partial class Utility : EllieModule
} }
} }
} }
public sealed class AfkService : IEService, IReadyExecutor
{
private readonly IBotCache _cache;
private readonly DiscordSocketClient _client;
private readonly MessageSenderService _mss;
public AfkService(IBotCache cache, DiscordSocketClient client, MessageSenderService mss)
{
_cache = cache;
_client = client;
_mss = mss;
}
private static TypedKey<string> GetKey(ulong userId)
=> new($"afk:msg:{userId}");
public async Task<bool> SetAfkAsync(ulong userId, string text)
{
var added = await _cache.AddAsync(GetKey(userId), text, TimeSpan.FromHours(8), overwrite: true);
return added;
}
public Task OnReadyAsync()
{
_client.MessageReceived += TryTriggerAfkMessage;
return Task.CompletedTask;
}
private Task TryTriggerAfkMessage(SocketMessage arg)
{
if (arg.Author.IsBot)
return Task.CompletedTask;
if (arg.MentionedUsers.Count is 0 or > 2)
return Task.CompletedTask;
if (arg is not IUserMessage uMsg || uMsg.Channel is not ITextChannel tc)
return Task.CompletedTask;
_ = Task.Run(async () =>
{
var botUser = await tc.Guild.GetCurrentUserAsync();
var perms = botUser.GetPermissions(tc);
if (!perms.SendMessages)
return;
ulong mentionedUserId = 0;
foreach (var uid in uMsg.MentionedUserIds)
{
if (uid == arg.Author.Id)
continue;
if (arg.Content.StartsWith($"<@{uid}>") || arg.Content.StartsWith($"<@!{uid}>"))
{
mentionedUserId = uid;
break;
}
}
if (mentionedUserId == 0)
return;
try
{
var result = await _cache.GetAsync(GetKey(mentionedUserId));
if (result.TryPickT0(out var msg, out _))
{
var st = SmartText.CreateFrom(msg);
var toDelete = await _mss.Response(arg.Channel)
.Message(uMsg)
.Text(st)
.Sanitize(false)
.SendAsync();
toDelete.DeleteAfter(30);
}
}
catch (HttpException ex)
{
Log.Warning("Error in afk service: {Message}", ex.Message);
}
});
return Task.CompletedTask;
}
}

View file

@ -4572,6 +4572,7 @@ coins:
afk: afk:
desc: |- desc: |-
Toggles AFK status for yourself with the specified message. Toggles AFK status for yourself with the specified message.
If you don't provide a message it default to a generic one.
Anyone @ mentioning you in any server will receive the afk message. Anyone @ mentioning you in any server will receive the afk message.
This will only work if the other user's message starts with the mention. This will only work if the other user's message starts with the mention.
ex: ex: