Skip to content

Commit bbbd8b9

Browse files
committed
feat(twitch): 新增離線提醒計時器與去抖動通知
- 在 `TwitchService.cs` 中,新增 `_streamOfflineReminders` 字典以管理離線提醒的計時器,並增加三分鐘的倒數計時器邏輯,改善用戶的通知體驗。此外,調整了直播開始的通知邏輯,確保移除舊的計時器並發送新的通知。 - 在 `DebounceChannelUpdateMessage.cs` 中,新增 `DebounceChannelUpdateMessage` 類別,使用去抖動技術管理 Twitch 頻道更新通知,減少不必要的通知,提升用戶體驗。
1 parent 2a36749 commit bbbd8b9

2 files changed

Lines changed: 206 additions & 172 deletions

File tree

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Discord_Stream_Notify_Bot.Interaction;
2+
using Dorssel.Utilities;
3+
using System.Collections.Concurrent;
4+
using static Discord_Stream_Notify_Bot.SharedService.Twitch.TwitchService;
5+
6+
namespace Discord_Stream_Notify_Bot.SharedService.Twitch.Debounce
7+
{
8+
// https://blog.darkthread.net/blog/dotnet-debounce/
9+
// https://github.com/dorssel/dotnet-debounce
10+
internal class DebounceChannelUpdateMessage
11+
{
12+
private readonly Debouncer _debouncer;
13+
private readonly TwitchService _twitchService;
14+
private readonly string _twitchUserName, _twitchUserLogin, _twitchUserId;
15+
private readonly ConcurrentQueue<string> messageQueue = new();
16+
17+
public DebounceChannelUpdateMessage(TwitchService twitchService, string twitchUserName, string twitchUserLogin, string twitchUserId)
18+
{
19+
_twitchService = twitchService;
20+
_twitchUserName = twitchUserName;
21+
_twitchUserLogin = twitchUserLogin;
22+
_twitchUserId = twitchUserId;
23+
24+
_debouncer = new()
25+
{
26+
DebounceWindow = TimeSpan.FromMinutes(1),
27+
DebounceTimeout = TimeSpan.FromMinutes(3),
28+
};
29+
_debouncer.Debounced += _debouncer_Debounced;
30+
}
31+
32+
private void _debouncer_Debounced(object sender, DebouncedEventArgs e)
33+
{
34+
try
35+
{
36+
Log.Info($"{_twitchUserLogin} 發送頻道更新通知 (Debouncer 觸發數量: {e.Count})");
37+
38+
var description = string.Join("\n\n", messageQueue);
39+
40+
var embedBuilder = new EmbedBuilder()
41+
.WithOkColor()
42+
.WithTitle($"{_twitchUserName} 直播資料更新")
43+
.WithUrl($"https://twitch.tv/{_twitchUserLogin}")
44+
.WithDescription(description);
45+
46+
using var db = Bot.DbService.GetDbContext();
47+
var twitchSpider = db.TwitchSpider.AsNoTracking().FirstOrDefault((x) => x.UserId == _twitchUserId);
48+
if (twitchSpider != null)
49+
embedBuilder.WithThumbnailUrl(twitchSpider.ProfileImageUrl);
50+
51+
Task.Run(async () => { await _twitchService.SendStreamMessageAsync(_twitchUserId, embedBuilder.Build(), NoticeType.ChangeStreamData); });
52+
}
53+
catch (Exception ex)
54+
{
55+
Log.Error(ex.Demystify(), $"{_twitchUserLogin} 訊息去抖動失敗");
56+
}
57+
finally
58+
{
59+
messageQueue.Clear();
60+
_debouncer.Reset();
61+
}
62+
}
63+
64+
public void AddMessage(string message)
65+
{
66+
Log.Debug($"DebounceChannelUpdateMessage ({_twitchUserLogin}): {message}");
67+
68+
messageQueue.Enqueue(message);
69+
_debouncer.Trigger();
70+
}
71+
72+
bool isDisposed;
73+
public void Dispose()
74+
{
75+
if (!isDisposed)
76+
{
77+
_debouncer.Debounced -= _debouncer_Debounced;
78+
_debouncer.Dispose();
79+
isDisposed = true;
80+
}
81+
}
82+
}
83+
}

0 commit comments

Comments
 (0)