Added .exprtoggleglobal / .extg which can be used to toggle usage of global expressions on the server

This commit is contained in:
Kwoth
2022-10-21 21:31:59 +02:00
parent bfec0cbcbf
commit cb98f4aa15
18 changed files with 10443 additions and 26 deletions

View File

@@ -95,6 +95,8 @@ public class GuildConfig : DbEntity
public int WarnExpireHours { get; set; } public int WarnExpireHours { get; set; }
public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear; public WarnExpireAction WarnExpireAction { get; set; } = WarnExpireAction.Clear;
public bool DisableGlobalExpressions { get; set; } = false;
#region Boost Message #region Boost Message
public bool SendBoostMessage { get; set; } public bool SendBoostMessage { get; set; }

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Migrations.Mysql
{
public partial class toggleglobalexpressions : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "disableglobalexpressions",
table: "guildconfigs",
type: "tinyint(1)",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "disableglobalexpressions",
table: "guildconfigs");
}
}
}

View File

@@ -1258,6 +1258,10 @@ namespace NadekoBot.Migrations.Mysql
.HasColumnType("tinyint(1)") .HasColumnType("tinyint(1)")
.HasColumnName("deletestreamonlinemessage"); .HasColumnName("deletestreamonlinemessage");
b.Property<bool>("DisableGlobalExpressions")
.HasColumnType("tinyint(1)")
.HasColumnName("disableglobalexpressions");
b.Property<string>("DmGreetMessageText") b.Property<string>("DmGreetMessageText")
.HasColumnType("longtext") .HasColumnType("longtext")
.HasColumnName("dmgreetmessagetext"); .HasColumnName("dmgreetmessagetext");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Migrations.PostgreSql
{
public partial class toggleglobalexpressions : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "disableglobalexpressions",
table: "guildconfigs",
type: "boolean",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "disableglobalexpressions",
table: "guildconfigs");
}
}
}

View File

@@ -1322,6 +1322,10 @@ namespace NadekoBot.Migrations.PostgreSql
.HasColumnType("boolean") .HasColumnType("boolean")
.HasColumnName("deletestreamonlinemessage"); .HasColumnName("deletestreamonlinemessage");
b.Property<bool>("DisableGlobalExpressions")
.HasColumnType("boolean")
.HasColumnName("disableglobalexpressions");
b.Property<string>("DmGreetMessageText") b.Property<string>("DmGreetMessageText")
.HasColumnType("text") .HasColumnType("text")
.HasColumnName("dmgreetmessagetext"); .HasColumnName("dmgreetmessagetext");

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
using Microsoft.EntityFrameworkCore.Migrations;
#nullable disable
namespace NadekoBot.Migrations
{
public partial class toggleglobalexpressions : Migration
{
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.AddColumn<bool>(
name: "DisableGlobalExpressions",
table: "GuildConfigs",
type: "INTEGER",
nullable: false,
defaultValue: false);
}
protected override void Down(MigrationBuilder migrationBuilder)
{
migrationBuilder.DropColumn(
name: "DisableGlobalExpressions",
table: "GuildConfigs");
}
}
}

View File

@@ -986,6 +986,9 @@ namespace NadekoBot.Migrations
b.Property<bool>("DeleteStreamOnlineMessage") b.Property<bool>("DeleteStreamOnlineMessage")
.HasColumnType("INTEGER"); .HasColumnType("INTEGER");
b.Property<bool>("DisableGlobalExpressions")
.HasColumnType("INTEGER");
b.Property<string>("DmGreetMessageText") b.Property<string>("DmGreetMessageText")
.HasColumnType("TEXT"); .HasColumnType("TEXT");

View File

@@ -41,6 +41,17 @@ public partial class NadekoExpressions : NadekoModule<NadekoExpressionsService>
message.Length > 1024 ? GetText(strs.redacted_too_long) : message)); message.Length > 1024 ? GetText(strs.redacted_too_long) : message));
} }
[Cmd]
[UserPerm(GuildPerm.Administrator)]
public async Task ExprToggleGlobal()
{
var result = await _service.ToggleGlobalExpressionsAsync(ctx.Guild.Id);
if (result)
await ReplyConfirmLocalizedAsync(strs.expr_global_disabled);
else
await ReplyConfirmLocalizedAsync(strs.expr_global_enabled);
}
[Cmd] [Cmd]
[UserPerm(GuildPerm.Administrator)] [UserPerm(GuildPerm.Administrator)]
public async Task ExprAddServer(string key, [Leftover] string message) public async Task ExprAddServer(string key, [Leftover] string message)

View File

@@ -7,6 +7,7 @@ using NadekoBot.Modules.Permissions.Common;
using NadekoBot.Modules.Permissions.Services; using NadekoBot.Modules.Permissions.Services;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using LinqToDB.EntityFrameworkCore;
using Nadeko.Common; using Nadeko.Common;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NamingConventions;
@@ -56,8 +57,8 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
// 1. expressions are almost never added (compared to how many times they are being looped through) // 1. expressions are almost never added (compared to how many times they are being looped through)
// 2. only need write locks for this as we'll rebuild+replace the array on every edit // 2. only need write locks for this as we'll rebuild+replace the array on every edit
// 3. there's never many of them (at most a thousand, usually < 100) // 3. there's never many of them (at most a thousand, usually < 100)
private NadekoExpression[] globalReactions; private NadekoExpression[] globalExpressions;
private ConcurrentDictionary<ulong, NadekoExpression[]> newGuildReactions; private ConcurrentDictionary<ulong, NadekoExpression[]> newguildExpressions;
private readonly DbService _db; private readonly DbService _db;
private readonly DiscordSocketClient _client; private readonly DiscordSocketClient _client;
@@ -72,6 +73,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
private readonly Random _rng; private readonly Random _rng;
private bool ready; private bool ready;
private ConcurrentHashSet<ulong> _disabledGlobalExpressionGuilds;
public NadekoExpressionsService( public NadekoExpressionsService(
PermissionService perms, PermissionService perms,
@@ -113,7 +115,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
.Where(x => allGuildIds.Contains(x.GuildId.Value)) .Where(x => allGuildIds.Contains(x.GuildId.Value))
.ToListAsync(); .ToListAsync();
newGuildReactions = guildItems.GroupBy(k => k.GuildId!.Value) newguildExpressions = guildItems.GroupBy(k => k.GuildId!.Value)
.ToDictionary(g => g.Key, .ToDictionary(g => g.Key,
g => g.Select(x => g => g.Select(x =>
{ {
@@ -123,6 +125,11 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
.ToArray()) .ToArray())
.ToConcurrent(); .ToConcurrent();
_disabledGlobalExpressionGuilds = new (await uow.GuildConfigs
.Where(x => x.DisableGlobalExpressions)
.Select(x => x.GuildId)
.ToListAsyncLinqToDB());
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var globalItems = uow.Expressions.AsNoTracking() var globalItems = uow.Expressions.AsNoTracking()
@@ -135,7 +142,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
}) })
.ToArray(); .ToArray();
globalReactions = globalItems; globalExpressions = globalItems;
} }
ready = true; ready = true;
@@ -151,14 +158,17 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
var content = umsg.Content.Trim().ToLowerInvariant(); var content = umsg.Content.Trim().ToLowerInvariant();
if (newGuildReactions.TryGetValue(channel.Guild.Id, out var reactions) && reactions.Length > 0) if (newguildExpressions.TryGetValue(channel.Guild.Id, out var expressions) && expressions.Length > 0)
{ {
var expr = MatchExpressions(content, reactions); var expr = MatchExpressions(content, expressions);
if (expr is not null) if (expr is not null)
return expr; return expr;
} }
var localGrs = globalReactions; if (_disabledGlobalExpressionGuilds.Contains(channel.Guild.Id))
return null;
var localGrs = globalExpressions;
return MatchExpressions(content, localGrs); return MatchExpressions(content, localGrs);
} }
@@ -345,7 +355,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
if (maybeGuildId is { } guildId) if (maybeGuildId is { } guildId)
{ {
newGuildReactions.AddOrUpdate(guildId, newguildExpressions.AddOrUpdate(guildId,
new[] { expr }, new[] { expr },
(_, old) => (_, old) =>
{ {
@@ -363,7 +373,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var exprs = globalReactions; var exprs = globalExpressions;
for (var i = 0; i < exprs.Length; i++) for (var i = 0; i < exprs.Length; i++)
{ {
if (exprs[i].Id == expr.Id) if (exprs[i].Id == expr.Id)
@@ -379,7 +389,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
expr.Trigger = expr.Trigger.Replace(MENTION_PH, _client.CurrentUser.Mention); expr.Trigger = expr.Trigger.Replace(MENTION_PH, _client.CurrentUser.Mention);
if (maybeGuildId is { } guildId) if (maybeGuildId is { } guildId)
newGuildReactions.AddOrUpdate(guildId, new[] { expr }, (_, old) => old.With(expr)); newguildExpressions.AddOrUpdate(guildId, new[] { expr }, (_, old) => old.With(expr));
else else
return _pubSub.Pub(_gexprAddedKey, expr); return _pubSub.Pub(_gexprAddedKey, expr);
@@ -390,7 +400,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
if (maybeGuildId is { } guildId) if (maybeGuildId is { } guildId)
{ {
newGuildReactions.AddOrUpdate(guildId, newguildExpressions.AddOrUpdate(guildId,
Array.Empty<NadekoExpression>(), Array.Empty<NadekoExpression>(),
(key, old) => DeleteInternal(old, id, out _)); (key, old) => DeleteInternal(old, id, out _));
@@ -399,7 +409,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var expr = Array.Find(globalReactions, item => item.Id == id); var expr = Array.Find(globalExpressions, item => item.Id == id);
if (expr is not null) if (expr is not null)
return _pubSub.Pub(_gexprDeletedkey, expr.Id); return _pubSub.Pub(_gexprDeletedkey, expr.Id);
} }
@@ -492,7 +502,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
var count = uow.Expressions.ClearFromGuild(guildId); var count = uow.Expressions.ClearFromGuild(guildId);
uow.SaveChanges(); uow.SaveChanges();
newGuildReactions.TryRemove(guildId, out _); newguildExpressions.TryRemove(guildId, out _);
return count; return count;
} }
@@ -562,10 +572,10 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var newGlobalReactions = new NadekoExpression[globalReactions.Length + 1]; var newGlobalReactions = new NadekoExpression[globalExpressions.Length + 1];
Array.Copy(globalReactions, newGlobalReactions, globalReactions.Length); Array.Copy(globalExpressions, newGlobalReactions, globalExpressions.Length);
newGlobalReactions[globalReactions.Length] = c; newGlobalReactions[globalExpressions.Length] = c;
globalReactions = newGlobalReactions; globalExpressions = newGlobalReactions;
} }
return default; return default;
@@ -575,11 +585,11 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
for (var i = 0; i < globalReactions.Length; i++) for (var i = 0; i < globalExpressions.Length; i++)
{ {
if (globalReactions[i].Id == c.Id) if (globalExpressions[i].Id == c.Id)
{ {
globalReactions[i] = c; globalExpressions[i] = c;
return default; return default;
} }
} }
@@ -596,8 +606,8 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
{ {
lock (_gexprWriteLock) lock (_gexprWriteLock)
{ {
var newGlobalReactions = DeleteInternal(globalReactions, id, out _); var newGlobalReactions = DeleteInternal(globalExpressions, id, out _);
globalReactions = newGlobalReactions; globalExpressions = newGlobalReactions;
} }
return default; return default;
@@ -612,7 +622,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
private Task OnLeftGuild(SocketGuild arg) private Task OnLeftGuild(SocketGuild arg)
{ {
newGuildReactions.TryRemove(arg.Id, out _); newguildExpressions.TryRemove(arg.Id, out _);
return Task.CompletedTask; return Task.CompletedTask;
} }
@@ -622,7 +632,7 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
await using var uow = _db.GetDbContext(); await using var uow = _db.GetDbContext();
var exprs = await uow.Expressions.AsNoTracking().Where(x => x.GuildId == gc.GuildId).ToArrayAsync(); var exprs = await uow.Expressions.AsNoTracking().Where(x => x.GuildId == gc.GuildId).ToArrayAsync();
newGuildReactions[gc.GuildId] = exprs; newguildExpressions[gc.GuildId] = exprs;
} }
#endregion #endregion
@@ -702,10 +712,25 @@ public sealed class NadekoExpressionsService : IExecOnMessage, IReadyExecutor
public NadekoExpression[] GetExpressionsFor(ulong? maybeGuildId) public NadekoExpression[] GetExpressionsFor(ulong? maybeGuildId)
{ {
if (maybeGuildId is { } guildId) if (maybeGuildId is { } guildId)
return newGuildReactions.TryGetValue(guildId, out var exprs) ? exprs : Array.Empty<NadekoExpression>(); return newguildExpressions.TryGetValue(guildId, out var exprs) ? exprs : Array.Empty<NadekoExpression>();
return globalReactions; return globalExpressions;
} }
#endregion #endregion
public async Task<bool> ToggleGlobalExpressionsAsync(ulong guildId)
{
await using var ctx = _db.GetDbContext();
var gc = ctx.GuildConfigsForId(guildId, set => set);
var toReturn = gc.DisableGlobalExpressions = !gc.DisableGlobalExpressions;
await ctx.SaveChangesAsync();
if (toReturn)
_disabledGlobalExpressionGuilds.Add(guildId);
else
_disabledGlobalExpressionGuilds.TryRemove(guildId);
return toReturn;
}
} }

View File

@@ -1274,6 +1274,9 @@ quotesimport:
showembed: showembed:
- showembed - showembed
# NadekoExpressions # NadekoExpressions
exprtoggleglobal:
- exprtoggleglobal
- extg
exprreact: exprreact:
- exreact - exreact
- exr - exr

View File

@@ -1581,6 +1581,10 @@ rategirl:
desc: "Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart." desc: "Use the universal hot-crazy wife zone matrix to determine the girl's worth. It is everything young men need to know about women. At any moment in time, any woman you have previously located on this chart can vanish from that location and appear anywhere else on the chart."
args: args:
- "@SomeGurl" - "@SomeGurl"
exprtoggleglobal:
desc: "Toggles whether global expressions are usable on this server."
args:
- ""
exprreact: exprreact:
desc: "Sets or resets reactions (up to 3) which will be added to the response message of the Expression with the specified ID. Provide no emojis to reset." desc: "Sets or resets reactions (up to 3) which will be added to the response message of the Expression with the specified ID. Provide no emojis to reset."
args: args:

View File

@@ -1,4 +1,6 @@
{ {
"expr_global_disabled": "Global expressions are now disabled on this server.",
"expr_global_enabled": "Global expressions are no longer disabled on this server.",
"expr_deleted": "Expression deleted", "expr_deleted": "Expression deleted",
"expr_insuff_perms": "Insufficient permissions. Requires Bot ownership for global expressions, and Administrator for server expressions.", "expr_insuff_perms": "Insufficient permissions. Requires Bot ownership for global expressions, and Administrator for server expressions.",
"expressions": "Expressions", "expressions": "Expressions",