Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 28 additions & 2 deletions src/HuaJiBot.NET.Plugin.Calendar/ClubAffairsReminder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,13 @@ internal bool SendWeeklySummary(DateTimeOffset now)
continue;
_ = Service.TrySendGroupMessageAsync(
group.GroupId,
BuildWeeklySummaryMessage(now, weekEnd, groupEvents)
new Post(
$"📢 **社团事务一周预告**({now:MM月dd日}~{weekEnd:MM月dd日})\n\n{Items(groupEvents, true)}",
BuildWeeklySummaryMessage(now, weekEnd, groupEvents)
)
{
Tags = ["日程", "周预告"],
}
);
Service.Log($"[社团事务] 已向群组 {group.GroupId} 发送每周汇总");
}
Expand Down Expand Up @@ -187,13 +193,33 @@ internal bool SendDailyReminder(DateTimeOffset now)
continue;
_ = Service.TrySendGroupMessageAsync(
group.GroupId,
BuildDailyReminderMessage(tomorrow, groupEvents)
new Post(
$"⏰ **明天截止**({tomorrow:MM月dd日})\n\n{Items(groupEvents, false)}",
BuildDailyReminderMessage(tomorrow, groupEvents)
)
{
Tags = ["日程", "临期"],
}
);
Service.Log($"[社团事务] 已向群组 {group.GroupId} 发送每日提醒");
}
return true;
}

private string Items(
List<(CalendarExtensions.Period period, CalendarEvent e)> events,
bool withDate
) =>
string.Join(
"\n",
from x in events
let responsible = ExtractResponsible(x.e)
select "- "
+ (withDate ? $"{x.period.StartTime:MM月dd日} " : "")
+ $"**{Post.Escape(x.e.Summary ?? "未命名事务")}**"
+ (string.IsNullOrEmpty(responsible) ? "" : $"(负责人:{Post.Escape(responsible)})")
);

private string BuildWeeklySummaryMessage(
DateTimeOffset weekStart,
DateTimeOffset weekEnd,
Expand Down
70 changes: 55 additions & 15 deletions src/HuaJiBot.NET.Plugin.Calendar/ReminderTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,10 +43,10 @@ public void Start()

private DateTimeOffset _scheduledTimeEnd = Utils.NetworkTime.Now; //截止到该时间点的日程已经在Task队列中列入计划了

private void SendToMatchedGroups(CalendarEvent e, string text)
private void SendToMatchedGroups(CalendarEvent e, Post post)
{
foreach (var group in Config.ReminderGroups.Where(g => g.Matches(e)))
_ = Service.TrySendGroupMessageAsync(group.GroupId, text);
_ = Service.TrySendGroupMessageAsync(group.GroupId, post);
}

[MethodImpl(MethodImplOptions.Synchronized)] //防止多线程同时更新时间节点
Expand Down Expand Up @@ -74,12 +74,18 @@ private void InvokeCheck()
ScheduleReminder(
period.StartTime.AddMinutes(-RemindBeforeStartMinutes) - now,
e,
$"""
日程提醒({period.StartTime:MM-dd HH:mm}):
{e.Summary} {e.Location}
{e.Description}
将于 {RemindBeforeStartMinutes} 分钟后开始
"""
StartPost(
period.StartTime,
e.End is null ? null : period.EndTime,
e,
RemindBeforeStartMinutes,
$"""
日程提醒({period.StartTime:MM-dd HH:mm}):
{e.Summary} {e.Location}
{e.Description}
将于 {RemindBeforeStartMinutes} 分钟后开始
"""
)
);
}

Expand All @@ -92,11 +98,15 @@ private void InvokeCheck()
ScheduleReminder(
period.EndTime.AddMinutes(-RemindBeforeEndMinutes) - now,
e,
$"""
日程提醒({period.EndTime:MM-dd HH:mm}):
{e.Summary} {e.Location}
预计于 {RemindBeforeEndMinutes} 分钟后结束
"""
EndPost(
e,
RemindBeforeEndMinutes,
$"""
日程提醒({period.EndTime:MM-dd HH:mm}):
{e.Summary} {e.Location}
预计于 {RemindBeforeEndMinutes} 分钟后结束
"""
)
);
}
}
Expand All @@ -106,15 +116,45 @@ private void InvokeCheck()
}
}

private void ScheduleReminder(TimeSpan waiting, CalendarEvent e, string text)
internal static Post StartPost(
DateTimeOffset start,
DateTimeOffset? end,
CalendarEvent e,
int minutes,
string fallback
)
{
var when = end is { } x ? $"🕘 {start:MM-dd HH:mm}–{x:HH:mm}" : $"🕘 {start:MM-dd HH:mm}";
if (!string.IsNullOrWhiteSpace(e.Location))
when += $" · 📍 {Post.Escape(e.Location)}";
var markdown = $"⏰ **{Post.Escape(e.Summary ?? "")}** {minutes} 分钟后开始\n{when}";
if (!string.IsNullOrWhiteSpace(e.Description))
markdown +=
"\n\n"
+ string.Join(
"\n",
from line in e.Description.ReplaceLineEndings("\n").Trim().Split('\n')
select "> " + Post.Escape(line)
);
return new(markdown, fallback) { Tags = ["日程"] };
}

internal static Post EndPost(CalendarEvent e, int minutes, string fallback) =>
new($"🔚 **{Post.Escape(e.Summary ?? "")}** 预计 {minutes} 分钟后结束", fallback)
{
Tags = ["日程"],
Silent = true,
};

private void ScheduleReminder(TimeSpan waiting, CalendarEvent e, Post post)
{
if (waiting < TimeSpan.Zero)
return;
Task.Delay(waiting)
.ContinueWith(_ =>
{
Service.Log($"[日程] 发送提醒:{e.Summary}");
SendToMatchedGroups(e, text);
SendToMatchedGroups(e, post);
});
Service.Log($"[日程] 计划发送提醒:{e.Summary} ({waiting.TotalMinutes:F1}分钟后发送)");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,8 @@
<ProjectReference Include="..\HuaJiBot.NET\HuaJiBot.NET.csproj" />
<ProjectReference Include="..\HuaJiBot.NET.SourceGenerator\HuaJiBot.NET.SourceGenerator.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false" />
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="HuaJiBot.NET.UnitTest" />
</ItemGroup>
</Project>
28 changes: 28 additions & 0 deletions src/HuaJiBot.NET.Plugin.MessageBridge/MinecraftPosts.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using HuaJiBot.NET.Bot;

namespace HuaJiBot.NET.Plugin.MessageBridge;

internal static class MinecraftPosts
{
internal static Post Chat(string player, string message, string fallback) =>
new($"**{Post.Escape(player)}**: {Post.Escape(message)}", fallback);

internal static Post Join(string player, string fallback) =>
new($"➕ {Post.Escape(player)} 加入了服务器", fallback) { Silent = true };

internal static Post Quit(string player, string fallback) =>
new($"➖ {Post.Escape(player)} 离开了服务器", fallback) { Silent = true };

internal static Post Death(string message, string fallback) =>
new($"💀 {Post.Escape(message)}", fallback) { Silent = true };

internal static Post Advancement(string player, string name, string? description, string fallback) =>
new(
$"🏆 **{Post.Escape(player)}** 完成了进度 **{Post.Escape(name)}**"
+ (string.IsNullOrWhiteSpace(description) ? "" : $"\n*{Post.Escape(description)}*"),
fallback
)
{
Silent = true,
};
}
17 changes: 11 additions & 6 deletions src/HuaJiBot.NET.Plugin.MessageBridge/PluginMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,21 +213,21 @@ PluginConfig.ClientInfo clientInfo
_ = SendGroupMessageAsync(
clientInfo,
ClientEventType.Chat,
$"[{senderName}] <{name}> {msg}"
MinecraftPosts.Chat(name, msg, $"[{senderName}] <{name}> {msg}")
);
break;
case PlayerJoinPacket { Data.PlayerName: var name }:
_onlinePlayers[name] = await SendGroupMessageAsync(
clientInfo,
ClientEventType.JoinLeft,
$"[{senderName}] {name} 加入了服务器"
MinecraftPosts.Join(name, $"[{senderName}] {name} 加入了服务器")
);
break;
case PlayerQuitPacket { Data.PlayerName: var name }:
_ = SendGroupMessageAsync(
clientInfo,
ClientEventType.JoinLeft,
$"[{senderName}] {name} 离开了服务器"
MinecraftPosts.Quit(name, $"[{senderName}] {name} 离开了服务器")
);
if (_onlinePlayers.TryRemove(name, out var allMsg))
{
Expand All @@ -242,7 +242,7 @@ PluginConfig.ClientInfo clientInfo
_ = SendGroupMessageAsync(
clientInfo,
ClientEventType.PlayerDeath,
$"[{senderName}] {msg}"
MinecraftPosts.Death(msg, $"[{senderName}] {msg}")
);
break;
case PlayerAchievementPacket
Expand All @@ -258,7 +258,12 @@ PluginConfig.ClientInfo clientInfo
_ = SendGroupMessageAsync(
clientInfo,
ClientEventType.PlayerAchievement,
$"[{senderName}] {name} 完成了进度 {achievementName} ({string.Join(",", criteria)}){Environment.NewLine}{description}"
MinecraftPosts.Advancement(
name,
achievementName,
description,
$"[{senderName}] {name} 完成了进度 {achievementName} ({string.Join(",", criteria)}){Environment.NewLine}{description}"
)
);
break;
case GetPlayerListRequestPacket: //do not reply
Expand All @@ -279,7 +284,7 @@ PluginConfig.ClientInfo clientInfo
private async Task<(string groupId, string[] msgId)[]> SendGroupMessageAsync(
PluginConfig.ClientInfo clientInfo,
ClientEventType eventType,
string message
Post message
)
{
List<(string, string[])> msgIds = [];
Expand Down
47 changes: 45 additions & 2 deletions src/HuaJiBot.NET.Plugin.RepairTeam/PluginMain.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using HuaJiBot.NET.Bot;
using HuaJiBot.NET.Commands;
using HuaJiBot.NET.Events;
using HuaJiBot.NET.Interfaces;
Expand Down Expand Up @@ -110,6 +111,48 @@ internal static string FormatEvent(LogEventEntity e)
return s.ToString().TrimEnd();
}

private static string? StateTag(string? action) =>
action switch
{
"create" => "新报修",
"accept" => "已接单",
"cancel" => "已取消",
"drop" => "已放弃",
"commit" or "alterCommit" => "待审核",
"reject" => "已退回",
"close" => "已结单",
"update" => "已更新",
_ => null,
};

internal static Post EventPost(LogEventEntity e)
{
var lines = new List<string> { $"🛠 **#{e.EventId} {Post.Escape(ActionText(e.Action))}**" };
var device = string.Join(
" · ",
new[] { e.Model, e.Problem }.Where(x => !string.IsNullOrWhiteSpace(x)).Select(x => Post.Escape(x!))
);
if (device.Length > 0)
lines.Add(device);
if (!string.IsNullOrWhiteSpace(e.Description))
lines.Add(
"\n"
+ string.Join(
"\n",
from line in e.Description.ReplaceLineEndings("\n").Trim().Split('\n')
select "> " + Post.Escape(line)
)
);
var time = e.GmtCreate.ToOffset(NetworkTime.LocalTimeZoneOffset).ToString("MM-dd HH:mm");
var member = string.IsNullOrWhiteSpace(e.MemberAlias) ? e.MemberId : e.MemberAlias;
lines.Add("\n" + (string.IsNullOrWhiteSpace(member) ? time : $"{Post.Escape(member)} · {time}"));
return new(string.Join("\n", lines), FormatEvent(e))
{
Tags = StateTag(e.Action) is { } tag ? ["维修", tag] : ["维修"],
Links = [new("去处理", TicketDigest.PortalUrl)],
};
}

private void OnMessageReceived(object? sender, string msg)
{
Service.Log(msg);
Expand All @@ -127,9 +170,9 @@ private void OnMessageReceived(object? sender, string msg)
Service.LogError("[RepairTeam] 无法解析维修事件", ex);
return;
}
var str = FormatEvent(e);
var post = EventPost(e);
foreach (var group in Config.PushInfoGroup)
_ = Service.TrySendGroupMessageAsync(group, str);
_ = Service.TrySendGroupMessageAsync(group, post);
}
}

Expand Down
33 changes: 28 additions & 5 deletions src/HuaJiBot.NET.Plugin.RepairTeam/TicketDigest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Text;
using HuaJiBot.NET.Bot;

namespace HuaJiBot.NET.Plugin.RepairTeam;

Expand All @@ -25,6 +26,32 @@ private static double ThresholdDays(string status, PluginConfig config) =>
public static List<Ticket> Stalled(IEnumerable<Ticket> tickets, DateTimeOffset now, PluginConfig config) =>
tickets.Where(t => (now - t.LastActivity).TotalDays > ThresholdDays(t.Status, config)).ToList();

public static Post ToPost(IReadOnlyCollection<Ticket> tickets, DateTimeOffset now, string fallback)
{
var sb = new StringBuilder($"🛠 **{tickets.Count} 张工单卡住了**");
foreach (var (status, stageTitle) in Stages)
{
var stage = tickets.Where(t => t.Status == status).OrderBy(t => t.LastActivity).ToList();
if (stage.Count == 0)
continue;
sb.Append($"\n\n**{stageTitle}**");
foreach (var t in stage)
sb.Append($"\n• #{t.Id} ").AppendJoin(" · ", Fields(t, now).Select(Post.Escape));
}
return new(sb.ToString(), fallback)
{
Tags = ["维修", "提醒"],
Links = [new("去处理", PortalUrl)],
};
}

private static IEnumerable<string> Fields(Ticket t, DateTimeOffset now)
{
var days = (int)(now - t.LastActivity).TotalDays;
var fields = new[] { t.Model, t.Problem, t.Member, days < 1 ? "不到 1 天" : $"已 {days} 天" };
return fields.Where(f => !string.IsNullOrWhiteSpace(f))!;
}

public static string Format(string title, IReadOnlyCollection<Ticket> tickets, DateTimeOffset now)
{
var sb = new StringBuilder(title).Append('\n');
Expand All @@ -35,11 +62,7 @@ public static string Format(string title, IReadOnlyCollection<Ticket> tickets, D
continue;
sb.Append(stageTitle).Append(":\n");
foreach (var t in stage)
{
var days = (int)(now - t.LastActivity).TotalDays;
var fields = new[] { t.Model, t.Problem, t.Member, days < 1 ? "不到 1 天" : $"已 {days} 天" };
sb.Append($" #{t.Id} ").AppendJoin(" · ", fields.Where(f => !string.IsNullOrWhiteSpace(f))).Append('\n');
}
sb.Append($" #{t.Id} ").AppendJoin(" · ", Fields(t, now)).Append('\n');
}
return sb.Append($"去处理:{PortalUrl}").ToString();
}
Expand Down
8 changes: 6 additions & 2 deletions src/HuaJiBot.NET.Plugin.RepairTeam/TicketReminder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,13 @@ public async Task<bool> SendDigestAsync(DateTimeOffset now)
var stalled = TicketDigest.Stalled(tickets, now, _config);
if (stalled.Count == 0)
return true;
var text = TicketDigest.Format($"【维修工单提醒】{stalled.Count} 张工单卡住了", stalled, now);
var post = TicketDigest.ToPost(
stalled,
now,
TicketDigest.Format($"【维修工单提醒】{stalled.Count} 张工单卡住了", stalled, now)
);
foreach (var group in _config.RemindGroups)
await _service.TrySendGroupMessageAsync(group, text);
await _service.TrySendGroupMessageAsync(group, post);
return true;
}

Expand Down
Loading
Loading