PluralKit/PluralKit.Bot/Commands/SystemFront.cs

145 lines
5.3 KiB
C#
Raw Normal View History

2021-01-31 15:02:34 +00:00
using System.Text;
2020-02-01 12:03:02 +00:00
using NodaTime;
using PluralKit.Core;
2020-02-01 12:03:02 +00:00
namespace PluralKit.Bot;
2021-08-27 15:03:47 +00:00
public class SystemFront
{
private readonly IDatabase _db;
private readonly EmbedService _embeds;
private readonly ModelRepository _repo;
2020-02-01 12:03:02 +00:00
public SystemFront(EmbedService embeds, IDatabase db, ModelRepository repo)
{
_embeds = embeds;
_db = db;
_repo = repo;
}
2020-02-01 12:03:02 +00:00
public async Task SystemFronter(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontPrivacy);
2020-08-29 11:46:27 +00:00
var sw = await _repo.GetLatestSwitch(system.Id);
if (sw == null) throw Errors.NoRegisteredSwitches;
2021-08-27 15:03:47 +00:00
await ctx.Reply(embed: await _embeds.CreateFronterEmbed(sw, ctx.Zone, ctx.LookupContextFor(system.Id)));
}
2020-02-01 12:03:02 +00:00
public async Task SystemFrontHistory(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy);
var totalSwitches = await _repo.GetSwitchCount(system.Id);
if (totalSwitches == 0) throw Errors.NoRegisteredSwitches;
var sws = _repo.GetSwitches(system.Id)
.Scan(new FrontHistoryEntry(null, null),
(lastEntry, newSwitch) => new FrontHistoryEntry(lastEntry.ThisSwitch?.Timestamp, newSwitch));
var embedTitle = system.Name != null
? $"Front history of {system.Name} (`{system.Hid}`)"
: $"Front history of `{system.Hid}`";
await ctx.Paginate(
sws,
totalSwitches,
10,
embedTitle,
system.Color,
async (builder, switches) =>
{
var sb = new StringBuilder();
foreach (var entry in switches)
{
var lastSw = entry.LastTime;
2020-02-01 12:03:02 +00:00
var sw = entry.ThisSwitch;
2021-08-27 15:03:47 +00:00
// Fetch member list and format
2020-08-29 11:46:27 +00:00
var members = await _db.Execute(c => _repo.GetSwitchMembers(c, sw.Id)).ToListAsync();
var membersStr = members.Any()
? string.Join(", ", members.Select(m => m.NameFor(ctx)))
: "no fronter";
2020-08-29 11:46:27 +00:00
var switchSince = SystemClock.Instance.GetCurrentInstant() - sw.Timestamp;
2020-02-01 12:03:02 +00:00
// If this isn't the latest switch, we also show duration
string stringToAdd;
if (lastSw != null)
{
// Calculate the time between the last switch (that we iterated - ie. the next one on the timeline) and the current one
var switchDuration = lastSw.Value - sw.Timestamp;
stringToAdd =
2021-11-30 02:35:21 +00:00
$"**{membersStr}** ({sw.Timestamp.FormatZoned(ctx.Zone)}, {switchSince.FormatDuration()} ago, for {switchDuration.FormatDuration()})\n";
}
else
2020-02-01 12:03:02 +00:00
{
stringToAdd =
2021-11-30 02:35:21 +00:00
$"**{membersStr}** ({sw.Timestamp.FormatZoned(ctx.Zone)}, {switchSince.FormatDuration()} ago)\n";
2020-02-01 12:03:02 +00:00
}
2021-01-31 15:02:34 +00:00
if (sb.Length + stringToAdd.Length >= 4096)
break;
sb.Append(stringToAdd);
2020-02-01 12:03:02 +00:00
}
builder.Description(sb.ToString());
}
);
}
2020-02-01 12:03:02 +00:00
public async Task SystemFrontPercent(Context ctx, PKSystem system)
{
if (system == null) throw Errors.NoSystemError;
ctx.CheckSystemPrivacy(system, system.FrontHistoryPrivacy);
var totalSwitches = await _repo.GetSwitchCount(system.Id);
if (totalSwitches == 0) throw Errors.NoRegisteredSwitches;
var durationStr = ctx.RemainderOrNull() ?? "30d";
// Picked the UNIX epoch as a random date
// even though we don't store switch timestamps in UNIX time
// I assume most people won't have switches logged previously to that (?)
if (durationStr == "full")
durationStr = "1970-01-01";
var now = SystemClock.Instance.GetCurrentInstant();
2021-11-30 02:35:21 +00:00
var rangeStart = DateUtils.ParseDateTime(durationStr, true, ctx.Zone);
if (rangeStart == null) throw Errors.InvalidDateTime(durationStr);
if (rangeStart.Value.ToInstant() > now) throw Errors.FrontPercentTimeInFuture;
var title = new StringBuilder("Frontpercent of ");
if (system.Name != null)
title.Append($"{system.Name} (`{system.Hid}`)");
else
title.Append($"`{system.Hid}`");
var ignoreNoFronters = ctx.MatchFlag("fo", "fronters-only");
var showFlat = ctx.MatchFlag("flat");
var frontpercent = await _db.Execute(c =>
_repo.GetFrontBreakdown(c, system.Id, null, rangeStart.Value.ToInstant(), now));
2021-11-30 02:35:21 +00:00
await ctx.Reply(embed: await _embeds.CreateFrontPercentEmbed(frontpercent, system, null, ctx.Zone,
ctx.LookupContextFor(system.Id), title.ToString(), ignoreNoFronters, showFlat));
}
2020-08-29 11:46:27 +00:00
private struct FrontHistoryEntry
{
public readonly Instant? LastTime;
public readonly PKSwitch ThisSwitch;
public FrontHistoryEntry(Instant? lastTime, PKSwitch thisSwitch)
{
LastTime = lastTime;
ThisSwitch = thisSwitch;
2020-02-01 12:03:02 +00:00
}
}
}