Added 'afk <msg>? command which sets an afk message which will trigger whenever someone pings a user.
This commit is contained in:
parent
d07066adec
commit
afa00c8d4f
4 changed files with 158 additions and 95 deletions
|
@ -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
|
||||||
|
|
148
src/EllieBot/Modules/Utility/AfkService.cs
Normal file
148
src/EllieBot/Modules/Utility/AfkService.cs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
|
||||||
|
@ -777,96 +776,4 @@ public partial class Utility : EllieModule
|
||||||
await Response().Error(ex.Message).SendAsync();
|
await Response().Error(ex.Message).SendAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -4571,7 +4571,8 @@ coins:
|
||||||
desc: "Page number to show. Starts at 1."
|
desc: "Page number to show. Starts at 1."
|
||||||
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:
|
||||||
|
|
Loading…
Reference in a new issue