mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
added: Added .afk <msg>?
command which sets an afk message which will trigger whenever someone pings a user.
This commit is contained in:
@@ -2,6 +2,13 @@
|
||||
|
||||
Mostly based on [keepachangelog](https://keepachangelog.com/en/1.0.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] - 13.07.2024
|
||||
|
||||
### Added
|
||||
|
@@ -402,11 +402,10 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
#if GLOBAL_NADEKO
|
||||
[OwnerOnly]
|
||||
#endif
|
||||
public async Task ExprsImport([Leftover] string input = null)
|
||||
{
|
||||
// todo cooldown on public bot for 1 day, limit 100
|
||||
|
||||
if (!AdminInGuildOrOwnerInDm())
|
||||
{
|
||||
await Response().Error(strs.expr_insuff_perms).SendAsync();
|
||||
|
148
src/NadekoBot/Modules/Utility/AfkService.cs
Normal file
148
src/NadekoBot/Modules/Utility/AfkService.cs
Normal file
@@ -0,0 +1,148 @@
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
|
||||
namespace NadekoBot.Modules.Utility;
|
||||
|
||||
public sealed class AfkService : INService, 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;
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
#nullable disable
|
||||
using LinqToDB.Reflection;
|
||||
using NadekoBot.Modules.Utility.Services;
|
||||
using Newtonsoft.Json;
|
||||
using System.Diagnostics;
|
||||
@@ -7,6 +7,7 @@ using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.CodeAnalysis.CSharp.Scripting;
|
||||
using Microsoft.CodeAnalysis.Scripting;
|
||||
using NadekoBot.Modules.Games.Hangman;
|
||||
using NadekoBot.Modules.Searches.Common;
|
||||
|
||||
namespace NadekoBot.Modules.Utility;
|
||||
@@ -41,6 +42,7 @@ public partial class Utility : NadekoModule
|
||||
private readonly IHttpClientFactory _httpFactory;
|
||||
private readonly VerboseErrorsService _veService;
|
||||
private readonly IServiceProvider _services;
|
||||
private readonly AfkService _afkService;
|
||||
|
||||
public Utility(
|
||||
DiscordSocketClient client,
|
||||
@@ -50,7 +52,8 @@ public partial class Utility : NadekoModule
|
||||
DownloadTracker tracker,
|
||||
IHttpClientFactory httpFactory,
|
||||
VerboseErrorsService veService,
|
||||
IServiceProvider services)
|
||||
IServiceProvider services,
|
||||
AfkService afkService)
|
||||
{
|
||||
_client = client;
|
||||
_coord = coord;
|
||||
@@ -60,6 +63,7 @@ public partial class Utility : NadekoModule
|
||||
_httpFactory = httpFactory;
|
||||
_veService = veService;
|
||||
_services = services;
|
||||
_afkService = afkService;
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
@@ -99,7 +103,7 @@ public partial class Utility : NadekoModule
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task WhosPlaying([Leftover] string game)
|
||||
public async Task WhosPlaying([Leftover] string? game)
|
||||
{
|
||||
game = game?.Trim().ToUpperInvariant();
|
||||
if (string.IsNullOrWhiteSpace(game))
|
||||
@@ -140,7 +144,7 @@ public partial class Utility : NadekoModule
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(0)]
|
||||
public async Task InRole(int page, [Leftover] IRole role = null)
|
||||
public async Task InRole(int page, [Leftover] IRole? role = null)
|
||||
{
|
||||
if (--page < 0)
|
||||
return;
|
||||
@@ -178,7 +182,7 @@ public partial class Utility : NadekoModule
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(1)]
|
||||
public Task InRole([Leftover] IRole role = null)
|
||||
public Task InRole([Leftover] IRole? role = null)
|
||||
=> InRole(1, role);
|
||||
|
||||
[Cmd]
|
||||
@@ -218,7 +222,7 @@ public partial class Utility : NadekoModule
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task UserId([Leftover] IGuildUser target = null)
|
||||
public async Task UserId([Leftover] IGuildUser? target = null)
|
||||
{
|
||||
var usr = target ?? ctx.User;
|
||||
await Response()
|
||||
@@ -248,7 +252,7 @@ public partial class Utility : NadekoModule
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task Roles(IGuildUser target, int page = 1)
|
||||
public async Task Roles(IGuildUser? target, int page = 1)
|
||||
{
|
||||
var guild = ctx.Guild;
|
||||
|
||||
@@ -301,7 +305,7 @@ public partial class Utility : NadekoModule
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task ChannelTopic([Leftover] ITextChannel channel = null)
|
||||
public async Task ChannelTopic([Leftover] ITextChannel? channel = null)
|
||||
{
|
||||
if (channel is null)
|
||||
channel = (ITextChannel)ctx.Channel;
|
||||
@@ -382,7 +386,7 @@ public partial class Utility : NadekoModule
|
||||
[BotPerm(GuildPerm.ManageEmojisAndStickers)]
|
||||
[UserPerm(GuildPerm.ManageEmojisAndStickers)]
|
||||
[Priority(0)]
|
||||
public async Task EmojiAdd(string name, string url = null)
|
||||
public async Task EmojiAdd(string name, string? url = null)
|
||||
{
|
||||
name = name.Trim(':');
|
||||
|
||||
@@ -456,10 +460,10 @@ public partial class Utility : NadekoModule
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[BotPerm(GuildPerm.ManageEmojisAndStickers)]
|
||||
[UserPerm(GuildPerm.ManageEmojisAndStickers)]
|
||||
public async Task StickerAdd(string name = null, string description = null, params string[] tags)
|
||||
public async Task StickerAdd(string? name = null, string? description = null, params string[] tags)
|
||||
{
|
||||
string format;
|
||||
Stream stream = null;
|
||||
Stream? stream = null;
|
||||
|
||||
try
|
||||
{
|
||||
@@ -696,6 +700,19 @@ public partial class Utility : NadekoModule
|
||||
await Response().Confirm(strs.verbose_errors_disabled).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
public async Task Afk([Leftover] string text = "No reason specified.")
|
||||
{
|
||||
var succ = await _afkService.SetAfkAsync(ctx.User.Id, text);
|
||||
|
||||
if (succ)
|
||||
{
|
||||
await Response()
|
||||
.Confirm(strs.afk_set)
|
||||
.SendAsync();
|
||||
}
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[NoPublicBot]
|
||||
[OwnerOnly]
|
||||
|
@@ -1411,3 +1411,5 @@ coins:
|
||||
- coins
|
||||
- crypto
|
||||
- cryptos
|
||||
afk:
|
||||
- afk
|
@@ -4578,3 +4578,14 @@ coins:
|
||||
params:
|
||||
- page:
|
||||
desc: "Page number to show. Starts at 1."
|
||||
afk:
|
||||
desc: |-
|
||||
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.
|
||||
This will only work if the other user's message starts with the mention.
|
||||
ex:
|
||||
- ''
|
||||
params:
|
||||
- msg:
|
||||
desc: "The message to send when someone pings you."
|
@@ -1104,5 +1104,6 @@
|
||||
"queue_search_results": "Type the number of the search result to queue up that track.",
|
||||
"overloads": "Overloads",
|
||||
"honeypot_on": "Honeypot enabled on this channel." ,
|
||||
"honeypot_off": "Honeypot disabled."
|
||||
"honeypot_off": "Honeypot disabled.",
|
||||
"afk_set": "AFK message set. Type a message in any channel to clear."
|
||||
}
|
||||
|
Reference in New Issue
Block a user