afk added #13

Merged
toastie_t0ast merged 1 commit from refs/pull/13/head into dev 2024-07-16 12:38:45 +00:00
6 changed files with 141 additions and 16 deletions

3
.gitignore vendored
View file

@ -20,6 +20,9 @@ src/EllieBot/credentials.json
src/EllieBot/old_credentials.json src/EllieBot/old_credentials.json
src/EllieBot/credentials.json.bak src/EllieBot/credentials.json.bak
src/EllieBot/data/EllieBot.db src/EllieBot/data/EllieBot.db
build.ps1
build.sh
test.ps1
# Created by https://www.gitignore.io/api/visualstudio,visualstudiocode,windows,linux,macos # Created by https://www.gitignore.io/api/visualstudio,visualstudiocode,windows,linux,macos

View file

@ -401,11 +401,10 @@ public partial class EllieExpressions : EllieModule<EllieExpressionsService>
} }
[Cmd] [Cmd]
#if GLOBAL_ELLIE
[OwnerOnly]
#endif
public async Task ExprsImport([Leftover] string input = null) public async Task ExprsImport([Leftover] string input = null)
{ {
// todo cooldown on public bot for 1 day, limit 100
if (!AdminInGuildOrOwnerInDm()) if (!AdminInGuildOrOwnerInDm())
{ {
await Response().Error(strs.expr_insuff_perms).SendAsync(); await Response().Error(strs.expr_insuff_perms).SendAsync();

View file

@ -1,4 +1,4 @@
#nullable disable using LinqToDB.Reflection;
using EllieBot.Modules.Utility.Services; using EllieBot.Modules.Utility.Services;
using Newtonsoft.Json; using Newtonsoft.Json;
using System.Diagnostics; using System.Diagnostics;
@ -7,6 +7,8 @@ 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.Searches.Common; using EllieBot.Modules.Searches.Common;
namespace EllieBot.Modules.Utility; namespace EllieBot.Modules.Utility;
@ -41,6 +43,7 @@ public partial class Utility : EllieModule
private readonly IHttpClientFactory _httpFactory; private readonly IHttpClientFactory _httpFactory;
private readonly VerboseErrorsService _veService; private readonly VerboseErrorsService _veService;
private readonly IServiceProvider _services; private readonly IServiceProvider _services;
private readonly AfkService _afkService;
public Utility( public Utility(
DiscordSocketClient client, DiscordSocketClient client,
@ -50,7 +53,8 @@ public partial class Utility : EllieModule
DownloadTracker tracker, DownloadTracker tracker,
IHttpClientFactory httpFactory, IHttpClientFactory httpFactory,
VerboseErrorsService veService, VerboseErrorsService veService,
IServiceProvider services) IServiceProvider services,
AfkService afkService)
{ {
_client = client; _client = client;
_coord = coord; _coord = coord;
@ -60,6 +64,7 @@ public partial class Utility : EllieModule
_httpFactory = httpFactory; _httpFactory = httpFactory;
_veService = veService; _veService = veService;
_services = services; _services = services;
_afkService = afkService;
} }
[Cmd] [Cmd]
@ -99,7 +104,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task WhosPlaying([Leftover] string game) public async Task WhosPlaying([Leftover] string? game)
{ {
game = game?.Trim().ToUpperInvariant(); game = game?.Trim().ToUpperInvariant();
if (string.IsNullOrWhiteSpace(game)) if (string.IsNullOrWhiteSpace(game))
@ -140,7 +145,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(0)] [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) if (--page < 0)
return; return;
@ -178,7 +183,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[Priority(1)] [Priority(1)]
public Task InRole([Leftover] IRole role = null) public Task InRole([Leftover] IRole? role = null)
=> InRole(1, role); => InRole(1, role);
[Cmd] [Cmd]
@ -218,7 +223,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task UserId([Leftover] IGuildUser target = null) public async Task UserId([Leftover] IGuildUser? target = null)
{ {
var usr = target ?? ctx.User; var usr = target ?? ctx.User;
await Response() await Response()
@ -248,7 +253,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [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; var guild = ctx.Guild;
@ -301,7 +306,7 @@ public partial class Utility : EllieModule
[Cmd] [Cmd]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
public async Task ChannelTopic([Leftover] ITextChannel channel = null) public async Task ChannelTopic([Leftover] ITextChannel? channel = null)
{ {
if (channel is null) if (channel is null)
channel = (ITextChannel)ctx.Channel; channel = (ITextChannel)ctx.Channel;
@ -382,7 +387,7 @@ public partial class Utility : EllieModule
[BotPerm(GuildPerm.ManageEmojisAndStickers)] [BotPerm(GuildPerm.ManageEmojisAndStickers)]
[UserPerm(GuildPerm.ManageEmojisAndStickers)] [UserPerm(GuildPerm.ManageEmojisAndStickers)]
[Priority(0)] [Priority(0)]
public async Task EmojiAdd(string name, string url = null) public async Task EmojiAdd(string name, string? url = null)
{ {
name = name.Trim(':'); name = name.Trim(':');
@ -456,10 +461,10 @@ public partial class Utility : EllieModule
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[BotPerm(GuildPerm.ManageEmojisAndStickers)] [BotPerm(GuildPerm.ManageEmojisAndStickers)]
[UserPerm(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; string format;
Stream stream = null; Stream? stream = null;
try try
{ {
@ -696,6 +701,19 @@ public partial class Utility : EllieModule
await Response().Confirm(strs.verbose_errors_disabled).SendAsync(); await Response().Confirm(strs.verbose_errors_disabled).SendAsync();
} }
[Cmd]
public async Task Afk([Leftover] string text)
{
var succ = await _afkService.SetAfkAsync(ctx.User.Id, text);
if (succ)
{
await Response()
.Confirm(strs.afk_set)
.SendAsync();
}
}
[Cmd] [Cmd]
[NoPublicBot] [NoPublicBot]
[OwnerOnly] [OwnerOnly]
@ -760,3 +778,95 @@ 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

@ -1411,3 +1411,5 @@ coins:
- coins - coins
- crypto - crypto
- cryptos - cryptos
afk:
- afk

View file

@ -4569,3 +4569,13 @@ coins:
params: params:
- page: - page:
desc: "Page number to show. Starts at 1." desc: "Page number to show. Starts at 1."
afk:
desc: |-
Toggles AFK status for yourself with the specified 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.
ex:
- ''
params:
- msg:
desc: "The message to send when someone pings you."

View file

@ -1104,5 +1104,6 @@
"queue_search_results": "Type the number of the search result to queue up that track.", "queue_search_results": "Type the number of the search result to queue up that track.",
"overloads": "Overloads", "overloads": "Overloads",
"honeypot_on": "Honeypot enabled on this channel.", "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."
} }