Files
nadekobot/src/NadekoBot/Modules/Utility/RemindCommands.cs
2021-12-20 03:02:02 +01:00

247 lines
7.7 KiB
C#

using System.Threading.Tasks;
using Discord;
using Discord.Commands;
using NadekoBot.Common.Attributes;
using NadekoBot.Services;
using NadekoBot.Services.Database.Models;
using NadekoBot.Db;
using NadekoBot.Extensions;
using NadekoBot.Modules.Administration.Services;
using NadekoBot.Modules.Utility.Services;
namespace NadekoBot.Modules.Utility;
public partial class Utility
{
[Group]
public class RemindCommands : NadekoSubmodule<RemindService>
{
private readonly DbService _db;
private readonly GuildTimezoneService _tz;
public RemindCommands(DbService db, GuildTimezoneService tz)
{
_db = db;
_tz = tz;
}
public enum MeOrHere
{
Me,
Here
}
[NadekoCommand, Aliases]
[Priority(1)]
public async Task Remind(MeOrHere meorhere, [Leftover] string remindString)
{
if (!_service.TryParseRemindMessage(remindString, out var remindData))
{
await ReplyErrorLocalizedAsync(strs.remind_invalid);
return;
}
ulong target;
target = meorhere == MeOrHere.Me ? ctx.User.Id : ctx.Channel.Id;
if (!await RemindInternal(target, meorhere == MeOrHere.Me || ctx.Guild is null, remindData.Time, remindData.What)
.ConfigureAwait(false))
{
await ReplyErrorLocalizedAsync(strs.remind_too_long).ConfigureAwait(false);
}
}
[NadekoCommand, Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.ManageMessages)]
[Priority(0)]
public async Task Remind(ITextChannel channel, [Leftover] string remindString)
{
var perms = ((IGuildUser) ctx.User).GetPermissions(channel);
if (!perms.SendMessages || !perms.ViewChannel)
{
await ReplyErrorLocalizedAsync(strs.cant_read_or_send).ConfigureAwait(false);
return;
}
if (!_service.TryParseRemindMessage(remindString, out var remindData))
{
await ReplyErrorLocalizedAsync(strs.remind_invalid);
return;
}
if (!await RemindInternal(channel.Id, false, remindData.Time, remindData.What)
.ConfigureAwait(false))
{
await ReplyErrorLocalizedAsync(strs.remind_too_long).ConfigureAwait(false);
}
}
public enum Server
{
Server = int.MinValue,
Srvr = int.MinValue,
Serv = int.MinValue,
S = int.MinValue,
}
[NadekoCommand, Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
[Priority(0)]
public Task RemindList(Server _, int page = 1)
=> RemindList(page, true);
[NadekoCommand, Aliases]
[Priority(1)]
public Task RemindList(int page = 1)
=> RemindList(page, false);
private async Task RemindList(int page, bool isServer)
{
if (--page < 0)
return;
var embed = _eb.Create()
.WithOkColor()
.WithTitle(GetText(isServer ? strs.reminder_server_list : strs.reminder_list));
List<Reminder> rems;
await using (var uow = _db.GetDbContext())
{
if (isServer)
{
rems = uow.Reminders
.RemindersForServer(ctx.Guild.Id, page)
.ToList();
}
else
{
rems = uow.Reminders
.RemindersFor(ctx.User.Id, page)
.ToList();
}
}
if (rems.Any())
{
var i = 0;
foreach (var rem in rems)
{
var when = rem.When;
var diff = when - DateTime.UtcNow;
embed.AddField(
$"#{++i + (page * 10)} {rem.When:HH:mm yyyy-MM-dd} UTC (in {(int) diff.TotalHours}h {(int) diff.Minutes}m)",
$@"`Target:` {(rem.IsPrivate ? "DM" : "Channel")}
`TargetId:` {rem.ChannelId}
`Message:` {rem.Message?.TrimTo(50)}", false);
}
}
else
{
embed.WithDescription(GetText(strs.reminders_none));
}
embed.AddPaginatedFooter(page + 1, null);
await ctx.Channel.EmbedAsync(embed).ConfigureAwait(false);
}
[NadekoCommand, Aliases]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.Administrator)]
[Priority(0)]
public Task RemindDelete(Server _, int index)
=> RemindDelete(index, true);
[NadekoCommand, Aliases]
[Priority(1)]
public Task RemindDelete(int index)
=> RemindDelete(index, false);
private async Task RemindDelete(int index, bool isServer)
{
if (--index < 0)
return;
Reminder rem = null;
await using (var uow = _db.GetDbContext())
{
var rems = isServer
? uow.Reminders
.RemindersForServer(ctx.Guild.Id, index / 10)
.ToList()
: uow.Reminders
.RemindersFor(ctx.User.Id, index / 10)
.ToList();
var pageIndex = index % 10;
if (rems.Count > pageIndex)
{
rem = rems[pageIndex];
uow.Reminders.Remove(rem);
uow.SaveChanges();
}
}
if (rem is null)
{
await ReplyErrorLocalizedAsync(strs.reminder_not_exist).ConfigureAwait(false);
}
else
{
await ReplyConfirmLocalizedAsync(strs.reminder_deleted(index + 1));
}
}
private async Task<bool> RemindInternal(ulong targetId, bool isPrivate, TimeSpan ts, string message)
{
var time = DateTime.UtcNow + ts;
if (ts > TimeSpan.FromDays(60))
return false;
if (ctx.Guild != null)
{
var perms = ((IGuildUser) ctx.User).GetPermissions((IGuildChannel) ctx.Channel);
if (!perms.MentionEveryone)
{
message = message.SanitizeAllMentions();
}
}
var rem = new Reminder
{
ChannelId = targetId,
IsPrivate = isPrivate,
When = time,
Message = message,
UserId = ctx.User.Id,
ServerId = ctx.Guild?.Id ?? 0
};
await using (var uow = _db.GetDbContext())
{
uow.Reminders.Add(rem);
await uow.SaveChangesAsync();
}
var gTime = ctx.Guild is null
? time
: TimeZoneInfo.ConvertTime(time, _tz.GetTimeZoneOrUtc(ctx.Guild.Id));
try
{
await SendConfirmAsync(
"⏰ " + GetText(strs.remind(
Format.Bold(!isPrivate ? $"<#{targetId}>" : ctx.User.Username),
Format.Bold(message),
$"{ts.Days}d {ts.Hours}h {ts.Minutes}min",
gTime, gTime))).ConfigureAwait(false);
}
catch
{
}
return true;
}
}
}