mirror of
https://gitlab.com/Kwoth/nadekobot.git
synced 2025-09-10 17:28:27 -04:00
Added .exprtoggleglobal / .extg which can be used to toggle usage of global expressions on the server
This commit is contained in:
@@ -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; }
|
||||||
|
3616
src/NadekoBot/Migrations/Mysql/20221021192758_toggle-global-expressions.Designer.cs
generated
Normal file
3616
src/NadekoBot/Migrations/Mysql/20221021192758_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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");
|
||||||
|
3764
src/NadekoBot/Migrations/PostgreSql/20221021192807_toggle-global-expressions.Designer.cs
generated
Normal file
3764
src/NadekoBot/Migrations/PostgreSql/20221021192807_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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");
|
||||||
|
2901
src/NadekoBot/Migrations/Sqlite/20221021192121_toggle-global-expressions.Designer.cs
generated
Normal file
2901
src/NadekoBot/Migrations/Sqlite/20221021192121_toggle-global-expressions.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -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");
|
||||||
|
|
||||||
|
@@ -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)
|
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1274,6 +1274,9 @@ quotesimport:
|
|||||||
showembed:
|
showembed:
|
||||||
- showembed
|
- showembed
|
||||||
# NadekoExpressions
|
# NadekoExpressions
|
||||||
|
exprtoggleglobal:
|
||||||
|
- exprtoggleglobal
|
||||||
|
- extg
|
||||||
exprreact:
|
exprreact:
|
||||||
- exreact
|
- exreact
|
||||||
- exr
|
- exr
|
||||||
|
@@ -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:
|
||||||
|
@@ -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",
|
||||||
|
Reference in New Issue
Block a user