mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 09:18:27 -04:00
Added .stondel which makes the bot delete stream online messages after the stream goes offline
This commit is contained in:
@@ -12,6 +12,7 @@ Experimental changelog. Mostly based on [keepachangelog](https://keepachangelog.
|
||||
- Embed arrays use color hex values instead of an integer
|
||||
- Old embed format will still work
|
||||
- There shouldn't be any breaking changes
|
||||
- Added `.stondel` command which, when toggled, will make the bot delete online stream messages on the server when the stream goes offline
|
||||
|
||||
### Fixed
|
||||
|
||||
|
@@ -92,6 +92,7 @@ public class GuildConfig : DbEntity
|
||||
public List<FeedSub> FeedSubs { get; set; } = new();
|
||||
public IndexedCollection<ReactionRoleMessage> ReactionRoleMessages { get; set; } = new();
|
||||
public bool NotifyStreamOffline { get; set; }
|
||||
public bool DeleteStreamOnlineMessage { get; set; }
|
||||
public List<GroupName> SelfAssignableRoleGroupNames { get; set; }
|
||||
public int WarnExpireHours { get; set; }
|
||||
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
|
||||
|
2759
src/NadekoBot/Migrations/Sqlite/20220427200557_stondel.Designer.cs
generated
Normal file
2759
src/NadekoBot/Migrations/Sqlite/20220427200557_stondel.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
26
src/NadekoBot/Migrations/Sqlite/20220427200557_stondel.cs
Normal file
26
src/NadekoBot/Migrations/Sqlite/20220427200557_stondel.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace NadekoBot.Migrations
|
||||
{
|
||||
public partial class stondel : Migration
|
||||
{
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.AddColumn<bool>(
|
||||
name: "DeleteStreamOnlineMessage",
|
||||
table: "GuildConfigs",
|
||||
type: "INTEGER",
|
||||
nullable: false,
|
||||
defaultValue: false);
|
||||
}
|
||||
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropColumn(
|
||||
name: "DeleteStreamOnlineMessage",
|
||||
table: "GuildConfigs");
|
||||
}
|
||||
}
|
||||
}
|
@@ -809,6 +809,9 @@ namespace NadekoBot.Migrations
|
||||
b.Property<bool>("DeleteMessageOnCommand")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<bool>("DeleteStreamOnlineMessage")
|
||||
.HasColumnType("INTEGER");
|
||||
|
||||
b.Property<string>("DmGreetMessageText")
|
||||
.HasColumnType("TEXT");
|
||||
|
||||
|
@@ -121,6 +121,18 @@ public partial class Searches
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.stream_off_disabled);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.ManageMessages)]
|
||||
public async partial Task StreamOnlineDelete()
|
||||
{
|
||||
var newValue = _service.ToggleStreamOnlineDelete(ctx.Guild.Id);
|
||||
if (newValue)
|
||||
await ReplyConfirmLocalizedAsync(strs.stream_online_delete_enabled);
|
||||
else
|
||||
await ReplyConfirmLocalizedAsync(strs.stream_online_delete_disabled);
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
|
@@ -1,4 +1,6 @@
|
||||
#nullable disable
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using NadekoBot.Common.ModuleBehaviors;
|
||||
using NadekoBot.Db;
|
||||
@@ -24,6 +26,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
|
||||
private readonly Dictionary<StreamDataKey, Dictionary<ulong, HashSet<FollowedStream>>> _shardTrackedStreams;
|
||||
private readonly ConcurrentHashSet<ulong> _offlineNotificationServers;
|
||||
private readonly ConcurrentHashSet<ulong> _deleteOnOfflineServers;
|
||||
|
||||
private readonly IPubSub _pubSub;
|
||||
private readonly IEmbedBuilderService _eb;
|
||||
@@ -33,6 +36,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
|
||||
private readonly TypedKey<FollowStreamPubData> _streamFollowKey;
|
||||
private readonly TypedKey<FollowStreamPubData> _streamUnfollowKey;
|
||||
private readonly ConnectionMultiplexer _redis;
|
||||
|
||||
public StreamNotificationService(
|
||||
DbService db,
|
||||
@@ -50,6 +54,7 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
_strings = strings;
|
||||
_pubSub = pubSub;
|
||||
_eb = eb;
|
||||
_redis = redis;
|
||||
_streamTracker = new(httpFactory, creds, redis, creds.GetCreds().RedisKey(), client.ShardId == 0);
|
||||
|
||||
_streamsOnlineKey = new("streams.online");
|
||||
@@ -71,6 +76,11 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
.Where(gc => gc.NotifyStreamOffline)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
|
||||
_deleteOnOfflineServers = new(guildConfigs
|
||||
.Where(gc => gc.DeleteStreamOnlineMessage)
|
||||
.Select(x => x.GuildId)
|
||||
.ToList());
|
||||
|
||||
var followedStreams = guildConfigs.SelectMany(x => x.FollowedStreams).ToList();
|
||||
|
||||
@@ -243,6 +253,44 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
.WhenAll();
|
||||
}
|
||||
}
|
||||
|
||||
if (_client.ShardId == 0)
|
||||
{
|
||||
foreach (var stream in offlineStreams)
|
||||
{
|
||||
await DeleteOnlineMessages(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DeleteOnlineMessages(StreamData stream)
|
||||
{
|
||||
var db = _redis.GetDatabase();
|
||||
var data = await db.ListRangeAsync($"streams_online_del:{stream.CreateKey()}");
|
||||
await db.KeyDeleteAsync($"streams_online_del:{stream.CreateKey()}");
|
||||
|
||||
foreach (string pair in data)
|
||||
{
|
||||
var pairArr = pair.Split(',');
|
||||
if (pairArr.Length != 2)
|
||||
continue;
|
||||
|
||||
if (!ulong.TryParse(pairArr[0], out var chId) || !ulong.TryParse(pairArr[1], out var msgId))
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
var textChannel = await _client.GetChannelAsync(chId) as ITextChannel;
|
||||
if (textChannel is null)
|
||||
continue;
|
||||
|
||||
await textChannel.DeleteMessageAsync(msgId);
|
||||
}
|
||||
catch
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async ValueTask HandleStreamsOnline(List<StreamData> onlineStreams)
|
||||
@@ -252,13 +300,13 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
var key = stream.CreateKey();
|
||||
if (_shardTrackedStreams.TryGetValue(key, out var fss))
|
||||
{
|
||||
await fss.SelectMany(x => x.Value)
|
||||
.Select(fs =>
|
||||
var messages = await fss.SelectMany(x => x.Value)
|
||||
.Select(async fs =>
|
||||
{
|
||||
var textChannel = _client.GetGuild(fs.GuildId)?.GetTextChannel(fs.ChannelId);
|
||||
|
||||
if (textChannel is null)
|
||||
return Task.CompletedTask;
|
||||
return default;
|
||||
|
||||
var rep = new ReplacementBuilder().WithOverride("%user%", () => fs.Username)
|
||||
.WithOverride("%platform%", () => fs.Type.ToString())
|
||||
@@ -266,9 +314,38 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
|
||||
var message = string.IsNullOrWhiteSpace(fs.Message) ? "" : rep.Replace(fs.Message);
|
||||
|
||||
return textChannel.EmbedAsync(GetEmbed(fs.GuildId, stream), message);
|
||||
var msg = await textChannel.EmbedAsync(GetEmbed(fs.GuildId, stream), message);
|
||||
|
||||
// only cache the ids of channel/message pairs
|
||||
if(_deleteOnOfflineServers.Contains(fs.GuildId))
|
||||
return (textChannel.Id, msg.Id);
|
||||
else
|
||||
return default;
|
||||
})
|
||||
.WhenAll();
|
||||
|
||||
|
||||
// push online stream messages to redis
|
||||
// when streams go offline, any server which
|
||||
// has the online stream message deletion feature
|
||||
// enabled will have the online messages deleted
|
||||
try
|
||||
{
|
||||
var pairs = messages
|
||||
.Where(x => x != default)
|
||||
.Select(x => (RedisValue)$"{x.Item1},{x.Item2}")
|
||||
.ToArray();
|
||||
|
||||
if (pairs.Length > 0)
|
||||
{
|
||||
var db = _redis.GetDatabase();
|
||||
await db.ListRightPushAsync($"streams_online_del:{key}", pairs);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -484,6 +561,21 @@ public sealed class StreamNotificationService : INService, IReadyExecutor
|
||||
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public bool ToggleStreamOnlineDelete(ulong guildId)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var gc = uow.GuildConfigsForId(guildId, set => set);
|
||||
var newValue = gc.DeleteStreamOnlineMessage = !gc.DeleteStreamOnlineMessage;
|
||||
uow.SaveChanges();
|
||||
|
||||
if (newValue)
|
||||
_deleteOnOfflineServers.Add(guildId);
|
||||
else
|
||||
_deleteOnOfflineServers.TryRemove(guildId);
|
||||
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public Task<StreamData> GetStreamDataAsync(string url)
|
||||
=> _streamTracker.GetStreamDataByUrlAsync(url);
|
||||
|
@@ -518,6 +518,9 @@ streamoffline:
|
||||
- streamoffline
|
||||
- sto
|
||||
- stoff
|
||||
streamonlinedelete:
|
||||
- streamonlinedelte
|
||||
- stondel
|
||||
streammessage:
|
||||
- streammsg
|
||||
- stm
|
||||
|
@@ -912,6 +912,10 @@ streamoffline:
|
||||
desc: "Toggles whether the bot will also notify when added streams go offline."
|
||||
args:
|
||||
- ""
|
||||
streamonlinedelete:
|
||||
desc: "Toggles whether the bot will delete stream online message when the stream goes offline."
|
||||
args:
|
||||
- ""
|
||||
streammessage:
|
||||
desc: "Sets the message which will show when the stream on the specified index comes online. You can use %user% and %platform% placeholders."
|
||||
args:
|
||||
|
@@ -519,6 +519,8 @@
|
||||
"stream_no": "No such stream.",
|
||||
"stream_off_enabled": "Stream notifications will now show when a stream goes offline.",
|
||||
"stream_off_disabled": "Stream notifications will no longer show when a stream goes offline.",
|
||||
"stream_online_delete_enabled": "Online stream notifications will now be deleted when the stream goes offline.",
|
||||
"stream_online_delete_disabled": "Online stream notifications will no longer be deleted when the stream goes offline.",
|
||||
"stream_not_added": "Stream was not added. Either stream doesn't exist, that platform is unsupported, or you've reached the maximum number of streams allowed.",
|
||||
"stream_message_reset": "Announcement message for {0} stream has been reset.",
|
||||
"stream_message_set": "Announcement message when {0} stream goes online has been set.",
|
||||
|
Reference in New Issue
Block a user