Quote commands slightly changed and some of them renamed. Added a lot of new aliases. Notable rename is .liqu to .qli
Quotes now follow the same naming pattern as Expression commands Code vastly improved
This commit is contained in:
parent
2e541eebac
commit
3a25433ec8
6 changed files with 222 additions and 146 deletions
|
@ -1,6 +1,50 @@
|
|||
namespace EllieBot.Modules.Utility;
|
||||
using EllieBot.Db.Models;
|
||||
|
||||
namespace EllieBot.Modules.Utility;
|
||||
|
||||
public interface IQuoteService
|
||||
{
|
||||
/// <summary>
|
||||
/// Delete all quotes created by the author in a guild
|
||||
/// </summary>
|
||||
/// <param name="guildId">ID of the guild</param>
|
||||
/// <param name="userId">ID of the user</param>
|
||||
/// <returns>Number of deleted qutoes</returns>
|
||||
Task<int> DeleteAllAuthorQuotesAsync(ulong guildId, ulong userId);
|
||||
|
||||
/// <summary>
|
||||
/// Delete all quotes in a guild
|
||||
/// </summary>
|
||||
/// <param name="guildId">ID of the guild</param>
|
||||
/// <returns>Number of deleted qutoes</returns>
|
||||
Task<int> DeleteAllQuotesAsync(ulong guildId);
|
||||
|
||||
Task<IReadOnlyCollection<Quote>> GetAllQuotesAsync(ulong guildId, int page, OrderType order);
|
||||
Task<Quote?> GetQuoteByKeywordAsync(ulong guildId, string keyword);
|
||||
|
||||
Task<IReadOnlyCollection<Quote>> SearchQuoteKeywordTextAsync(
|
||||
ulong guildId,
|
||||
string? keyword,
|
||||
string text);
|
||||
|
||||
Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId);
|
||||
Task<int> RemoveAllByKeyword(ulong guildId, string keyword);
|
||||
Task<Quote?> GetQuoteByIdAsync(ulong guildId, kwum quoteId);
|
||||
|
||||
Task<Quote> AddQuoteAsync(
|
||||
ulong guildId,
|
||||
ulong authorId,
|
||||
string authorName,
|
||||
string keyword,
|
||||
string text);
|
||||
|
||||
Task<Quote?> EditQuoteAsync(ulong authorId, int quoteId, string text);
|
||||
|
||||
Task<bool> DeleteQuoteAsync(
|
||||
ulong guildId,
|
||||
ulong authorId,
|
||||
bool isQuoteManager,
|
||||
int quoteId);
|
||||
|
||||
Task<bool> ImportQuotesAsync(ulong guildId, string input);
|
||||
}
|
|
@ -1,6 +1,4 @@
|
|||
#nullable disable warnings
|
||||
using LinqToDB;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using EllieBot.Common.Yml;
|
||||
using EllieBot.Db.Models;
|
||||
using YamlDotNet.Serialization;
|
||||
|
@ -11,7 +9,7 @@ namespace EllieBot.Modules.Utility;
|
|||
public partial class Utility
|
||||
{
|
||||
[Group]
|
||||
public partial class QuoteCommands : EllieModule<QuoteService>
|
||||
public partial class QuoteCommands : EllieModule
|
||||
{
|
||||
private const string PREPEND_EXPORT =
|
||||
"""
|
||||
|
@ -48,19 +46,19 @@ public partial class Utility
|
|||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(1)]
|
||||
public Task ListQuotes(OrderType order = OrderType.Keyword)
|
||||
=> ListQuotes(1, order);
|
||||
public Task QuoteList(OrderType order = OrderType.Keyword)
|
||||
=> QuoteList(1, order);
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
[Priority(0)]
|
||||
public async Task ListQuotes(int page = 1, OrderType order = OrderType.Keyword)
|
||||
public async Task QuoteList(int page = 1, OrderType order = OrderType.Keyword)
|
||||
{
|
||||
page -= 1;
|
||||
if (page < 0)
|
||||
return;
|
||||
|
||||
var quotes = await _service.GetAllQuotesAsync(ctx.Guild.Id, page, order);
|
||||
var quotes = await _qs.GetAllQuotesAsync(ctx.Guild.Id, page, order);
|
||||
|
||||
if (quotes.Count == 0)
|
||||
{
|
||||
|
@ -85,7 +83,7 @@ public partial class Utility
|
|||
|
||||
keyword = keyword.ToUpperInvariant();
|
||||
|
||||
var quote = await _service.GetQuoteByKeywordAsync(ctx.Guild.Id, keyword);
|
||||
var quote = await _qs.GetQuoteByKeywordAsync(ctx.Guild.Id, keyword);
|
||||
|
||||
if (quote is null)
|
||||
return;
|
||||
|
@ -97,7 +95,6 @@ public partial class Utility
|
|||
|
||||
await Response()
|
||||
.Text($"`{new kwum(quote.Id)}` 📣 " + text)
|
||||
.Sanitize()
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
|
@ -106,7 +103,7 @@ public partial class Utility
|
|||
[RequireContext(ContextType.Guild)]
|
||||
public async Task QuoteShow(kwum quoteId)
|
||||
{
|
||||
var quote = await _service.GetQuoteByIdAsync(ctx.Guild.Id, quoteId);
|
||||
var quote = await _qs.GetQuoteByIdAsync(ctx.Guild.Id, quoteId);
|
||||
|
||||
if (quote is null)
|
||||
{
|
||||
|
@ -179,7 +176,7 @@ public partial class Utility
|
|||
|
||||
keyword = keyword?.ToUpperInvariant();
|
||||
|
||||
var quotes = await _service.SearchQuoteKeywordTextAsync(ctx.Guild.Id, keyword, textOrAuthor);
|
||||
var quotes = await _qs.SearchQuoteKeywordTextAsync(ctx.Guild.Id, keyword, textOrAuthor);
|
||||
|
||||
await Response()
|
||||
.Paginated()
|
||||
|
@ -218,7 +215,7 @@ public partial class Utility
|
|||
if (quoteId < 0)
|
||||
return;
|
||||
|
||||
var quote = await _service.GetQuoteByIdAsync(ctx.Guild.Id, quoteId);
|
||||
var quote = await _qs.GetQuoteByIdAsync(ctx.Guild.Id, quoteId);
|
||||
|
||||
if (quote is null)
|
||||
{
|
||||
|
@ -226,8 +223,8 @@ public partial class Utility
|
|||
return;
|
||||
}
|
||||
|
||||
var infoText = $"*`{new kwum(quote.Id)}` added by {quote.AuthorName.SanitizeAllMentions()}* 🗯️ "
|
||||
+ quote.Keyword.ToLowerInvariant().SanitizeAllMentions()
|
||||
var infoText = $"*`{new kwum(quote.Id)}` added by {quote.AuthorName}* 🗯️ "
|
||||
+ quote.Keyword.ToLowerInvariant()
|
||||
+ ":\n";
|
||||
|
||||
|
||||
|
@ -236,7 +233,6 @@ public partial class Utility
|
|||
text = await repSvc.ReplaceAsync(text, repCtx);
|
||||
await Response()
|
||||
.Text(infoText + text)
|
||||
.Sanitize()
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
|
@ -248,26 +244,14 @@ public partial class Utility
|
|||
if (string.IsNullOrWhiteSpace(keyword) || string.IsNullOrWhiteSpace(text))
|
||||
return;
|
||||
|
||||
keyword = keyword.ToUpperInvariant();
|
||||
var quote = await _qs.AddQuoteAsync(ctx.Guild.Id, ctx.User.Id, ctx.User.Username, keyword, text);
|
||||
|
||||
Quote q;
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
uow.Set<Quote>()
|
||||
.Add(q = new()
|
||||
{
|
||||
AuthorId = ctx.Message.Author.Id,
|
||||
AuthorName = ctx.Message.Author.Username,
|
||||
GuildId = ctx.Guild.Id,
|
||||
Keyword = keyword,
|
||||
Text = text
|
||||
});
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await Response().Confirm(strs.quote_added_new(Format.Code(new kwum(q.Id).ToString()))).SendAsync();
|
||||
await Response()
|
||||
.Confirm(strs.quote_added_new(Format.Code(new kwum(quote.Id).ToString())))
|
||||
.SendAsync();
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task QuoteEdit(kwum quoteId, [Leftover] string text)
|
||||
|
@ -277,19 +261,7 @@ public partial class Utility
|
|||
return;
|
||||
}
|
||||
|
||||
Quote q;
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var intId = (int)quoteId;
|
||||
var result = await uow.GetTable<Quote>()
|
||||
.Where(x => x.Id == intId && x.AuthorId == ctx.User.Id)
|
||||
.Set(x => x.Text, text)
|
||||
.UpdateWithOutputAsync((del, ins) => ins);
|
||||
|
||||
q = result.FirstOrDefault();
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
var q = await _qs.EditQuoteAsync(ctx.User.Id, quoteId, text);
|
||||
|
||||
if (q is not null)
|
||||
{
|
||||
|
@ -309,33 +281,19 @@ public partial class Utility
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
[Cmd]
|
||||
[RequireContext(ContextType.Guild)]
|
||||
public async Task QuoteDelete(kwum quoteId)
|
||||
{
|
||||
var hasManageMessages = ((IGuildUser)ctx.Message.Author).GuildPermissions.ManageMessages;
|
||||
|
||||
var success = false;
|
||||
string response;
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
var q = uow.Set<Quote>().GetById(quoteId);
|
||||
|
||||
if (q?.GuildId != ctx.Guild.Id || (!hasManageMessages && q.AuthorId != ctx.Message.Author.Id))
|
||||
response = GetText(strs.quotes_remove_none);
|
||||
else
|
||||
{
|
||||
uow.Set<Quote>().Remove(q);
|
||||
await uow.SaveChangesAsync();
|
||||
success = true;
|
||||
response = GetText(strs.quote_deleted(new kwum(quoteId)));
|
||||
}
|
||||
}
|
||||
var success = await _qs.DeleteQuoteAsync(ctx.Guild.Id, ctx.User.Id, hasManageMessages, quoteId);
|
||||
|
||||
if (success)
|
||||
await Response().Confirm(response).SendAsync();
|
||||
await Response().Confirm(strs.quote_deleted(quoteId)).SendAsync();
|
||||
else
|
||||
await Response().Error(response).SendAsync();
|
||||
await Response().Error(strs.quotes_remove_none).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@ -368,16 +326,9 @@ public partial class Utility
|
|||
if (string.IsNullOrWhiteSpace(keyword))
|
||||
return;
|
||||
|
||||
keyword = keyword.ToUpperInvariant();
|
||||
await _qs.RemoveAllByKeyword(ctx.Guild.Id, keyword.ToUpperInvariant());
|
||||
|
||||
await using (var uow = _db.GetDbContext())
|
||||
{
|
||||
await _service.RemoveAllByKeyword(ctx.Guild.Id, keyword.ToUpperInvariant());
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
}
|
||||
|
||||
await Response().Confirm(strs.quotes_deleted(Format.Bold(keyword.SanitizeAllMentions()))).SendAsync();
|
||||
await Response().Confirm(strs.quotes_deleted(Format.Bold(keyword))).SendAsync();
|
||||
}
|
||||
|
||||
[Cmd]
|
||||
|
@ -385,7 +336,7 @@ public partial class Utility
|
|||
[UserPerm(GuildPerm.Administrator)]
|
||||
public async Task QuotesExport()
|
||||
{
|
||||
var quotes = _service.GetForGuild(ctx.Guild.Id).ToList();
|
||||
var quotes = await _qs.GetGuildQuotesAsync(ctx.Guild.Id);
|
||||
|
||||
var exprsDict = quotes.GroupBy(x => x.Keyword)
|
||||
.ToDictionary(x => x.Key, x => x.Select(ExportedQuote.FromModel));
|
||||
|
@ -400,7 +351,7 @@ public partial class Utility
|
|||
[RequireContext(ContextType.Guild)]
|
||||
[UserPerm(GuildPerm.Administrator)]
|
||||
[Ratelimit(300)]
|
||||
#if GLOBAL_ELLIE
|
||||
#if GLOBAL_NADEKO
|
||||
[OwnerOnly]
|
||||
#endif
|
||||
public async Task QuotesImport([Leftover] string? input = null)
|
||||
|
@ -428,7 +379,7 @@ public partial class Utility
|
|||
}
|
||||
}
|
||||
|
||||
var succ = await ImportExprsAsync(ctx.Guild.Id, input);
|
||||
var succ = await _qs.ImportQuotesAsync(ctx.Guild.Id, input);
|
||||
if (!succ)
|
||||
{
|
||||
await Response().Error(strs.expr_import_invalid_data).SendAsync();
|
||||
|
@ -437,56 +388,5 @@ public partial class Utility
|
|||
|
||||
await ctx.OkAsync();
|
||||
}
|
||||
|
||||
private async Task<bool> ImportExprsAsync(ulong guildId, string input)
|
||||
{
|
||||
Dictionary<string, List<ExportedQuote>> data;
|
||||
try
|
||||
{
|
||||
data = Yaml.Deserializer.Deserialize<Dictionary<string, List<ExportedQuote>>>(input);
|
||||
if (data.Sum(x => x.Value.Count) == 0)
|
||||
return false;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
foreach (var entry in data)
|
||||
{
|
||||
var keyword = entry.Key;
|
||||
await uow.Set<Quote>()
|
||||
.AddRangeAsync(entry.Value.Where(quote => !string.IsNullOrWhiteSpace(quote.Txt))
|
||||
.Select(quote => new Quote
|
||||
{
|
||||
GuildId = guildId,
|
||||
Keyword = keyword,
|
||||
Text = quote.Txt,
|
||||
AuthorId = quote.Aid,
|
||||
AuthorName = quote.An
|
||||
}));
|
||||
}
|
||||
|
||||
await uow.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
|
||||
public class ExportedQuote
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string An { get; set; }
|
||||
public ulong Aid { get; set; }
|
||||
public string Txt { get; set; }
|
||||
|
||||
public static ExportedQuote FromModel(Quote quote)
|
||||
=> new()
|
||||
{
|
||||
Id = ((kwum)quote.Id).ToString(),
|
||||
An = quote.AuthorName,
|
||||
Aid = quote.AuthorId,
|
||||
Txt = quote.Text
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
#nullable disable warnings
|
||||
using LinqToDB;
|
||||
using LinqToDB.Data;
|
||||
using LinqToDB.EntityFrameworkCore;
|
||||
using EllieBot.Common.Yml;
|
||||
using EllieBot.Db.Models;
|
||||
|
||||
namespace EllieBot.Modules.Utility;
|
||||
|
@ -45,19 +47,19 @@ public sealed class QuoteService : IQuoteService, IEService
|
|||
return deleted;
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyList<Quote>> GetAllQuotesAsync(ulong guildId, int page, OrderType order)
|
||||
public async Task<IReadOnlyCollection<Quote>> GetAllQuotesAsync(ulong guildId, int page, OrderType order)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var q = uow.Set<Quote>()
|
||||
.ToLinqToDBTable()
|
||||
.Where(x => x.GuildId == guildId);
|
||||
|
||||
|
||||
if (order == OrderType.Keyword)
|
||||
q = q.OrderBy(x => x.Keyword);
|
||||
else
|
||||
q = q.OrderBy(x => x.Id);
|
||||
|
||||
return await q.Skip(15 * page).Take(15).ToArrayAsync();
|
||||
|
||||
return await q.Skip(15 * page).Take(15).ToArrayAsyncLinqToDB();
|
||||
}
|
||||
|
||||
public async Task<Quote?> GetQuoteByKeywordAsync(ulong guildId, string keyword)
|
||||
|
@ -97,11 +99,12 @@ public sealed class QuoteService : IQuoteService, IEService
|
|||
return toReturn;
|
||||
}
|
||||
|
||||
public IEnumerable<Quote> GetForGuild(ulong guildId)
|
||||
public async Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId)
|
||||
{
|
||||
using var uow = _db.GetDbContext();
|
||||
var quotes = uow.GetTable<Quote>()
|
||||
.Where(x => x.GuildId == guildId);
|
||||
await using var uow = _db.GetDbContext();
|
||||
var quotes = await uow.GetTable<Quote>()
|
||||
.Where(x => x.GuildId == guildId)
|
||||
.ToListAsyncLinqToDB();
|
||||
return quotes;
|
||||
}
|
||||
|
||||
|
@ -124,7 +127,96 @@ public sealed class QuoteService : IQuoteService, IEService
|
|||
|
||||
var quote = await uow.GetTable<Quote>()
|
||||
.Where(x => x.Id == quoteId && x.GuildId == guildId)
|
||||
.FirstAsyncLinqToDB();
|
||||
.FirstOrDefaultAsyncLinqToDB();
|
||||
|
||||
return quote;
|
||||
}
|
||||
|
||||
public async Task<Quote> AddQuoteAsync(
|
||||
ulong guildId,
|
||||
ulong authorId,
|
||||
string authorName,
|
||||
string keyword,
|
||||
string text)
|
||||
{
|
||||
keyword = keyword.ToUpperInvariant();
|
||||
|
||||
Quote q;
|
||||
await using var uow = _db.GetDbContext();
|
||||
uow.Set<Quote>()
|
||||
.Add(q = new()
|
||||
{
|
||||
AuthorId = authorId,
|
||||
AuthorName = authorName,
|
||||
GuildId = guildId,
|
||||
Keyword = keyword,
|
||||
Text = text
|
||||
});
|
||||
await uow.SaveChangesAsync();
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
public async Task<Quote?> EditQuoteAsync(ulong authorId, int quoteId, string text)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var result = await uow.GetTable<Quote>()
|
||||
.Where(x => x.Id == quoteId && x.AuthorId == authorId)
|
||||
.Set(x => x.Text, text)
|
||||
.UpdateWithOutputAsync((del, ins) => ins);
|
||||
|
||||
var q = result.FirstOrDefault();
|
||||
return q;
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteQuoteAsync(
|
||||
ulong guildId,
|
||||
ulong authorId,
|
||||
bool isQuoteManager,
|
||||
int quoteId)
|
||||
{
|
||||
await using var uow = _db.GetDbContext();
|
||||
var q = uow.Set<Quote>().GetById(quoteId);
|
||||
|
||||
|
||||
var count = await uow.GetTable<Quote>()
|
||||
.Where(x => x.GuildId == guildId && x.Id == quoteId)
|
||||
.Where(x => isQuoteManager || (x.AuthorId == authorId))
|
||||
.DeleteAsync();
|
||||
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> ImportQuotesAsync(ulong guildId, string input)
|
||||
{
|
||||
Dictionary<string?, List<ExportedQuote?>> data;
|
||||
try
|
||||
{
|
||||
data = Yaml.Deserializer.Deserialize<Dictionary<string?, List<ExportedQuote?>>>(input);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(ex, "Quote import failed: {Message}", ex.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
var toImport = data.SelectMany(x => x.Value.Select(v => (Key: x.Key, Value: v)))
|
||||
.Where(x => !string.IsNullOrWhiteSpace(x.Key) && !string.IsNullOrWhiteSpace(x.Value?.Txt));
|
||||
|
||||
await using var uow = _db.GetDbContext();
|
||||
await uow.GetTable<Quote>()
|
||||
.BulkCopyAsync(toImport
|
||||
.Select(q => new Quote
|
||||
{
|
||||
GuildId = guildId,
|
||||
Keyword = q.Key,
|
||||
Text = q.Value.Txt,
|
||||
AuthorId = q.Value.Aid,
|
||||
AuthorName = q.Value.An
|
||||
}));
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
20
src/EllieBot/Modules/Utility/Quote/_common/ExportedQuote.cs
Normal file
20
src/EllieBot/Modules/Utility/Quote/_common/ExportedQuote.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using EllieBot.Db.Models;
|
||||
|
||||
namespace EllieBot.Modules.Utility;
|
||||
|
||||
public class ExportedQuote
|
||||
{
|
||||
public required string Id { get; init; }
|
||||
public required string An { get; init; }
|
||||
public required ulong Aid { get; init; }
|
||||
public required string Txt { get; init; }
|
||||
|
||||
public static ExportedQuote FromModel(Quote quote)
|
||||
=> new()
|
||||
{
|
||||
Id = ((kwum)quote.Id).ToString(),
|
||||
An = quote.AuthorName,
|
||||
Aid = quote.AuthorId,
|
||||
Txt = quote.Text
|
||||
};
|
||||
}
|
|
@ -343,28 +343,57 @@ allcmdcooldowns:
|
|||
- cmdcds
|
||||
quoteadd:
|
||||
- quoteadd
|
||||
- qa
|
||||
- qadd
|
||||
- quadd
|
||||
- .
|
||||
quoteedit:
|
||||
- quoteedit
|
||||
- qe
|
||||
- que
|
||||
- qedit
|
||||
quoteprint:
|
||||
- quoteprint
|
||||
- qp
|
||||
- qup
|
||||
- ..
|
||||
- qprint
|
||||
quoteshow:
|
||||
- quoteshow
|
||||
- qsh
|
||||
- qshow
|
||||
- qushow
|
||||
quotesearch:
|
||||
- quotesearch
|
||||
- qs
|
||||
- qse
|
||||
- qsearch
|
||||
quoteid:
|
||||
- quoteid
|
||||
- qid
|
||||
quotedelete:
|
||||
- quotedelete
|
||||
- qd
|
||||
- qdel
|
||||
- qdelete
|
||||
quotedeleteauthor:
|
||||
- quotedeleteauthor
|
||||
- qda
|
||||
- qdelauth
|
||||
quotesexport:
|
||||
- quotesexport
|
||||
- qex
|
||||
- qexport
|
||||
quotesimport:
|
||||
- quotesimport
|
||||
- qim
|
||||
- qimp
|
||||
- qimport
|
||||
quotelist:
|
||||
- quotelist
|
||||
- qli
|
||||
- quli
|
||||
- qulist
|
||||
draw:
|
||||
- draw
|
||||
drawnew:
|
||||
|
@ -761,9 +790,6 @@ autotranslate:
|
|||
- autotranslate
|
||||
- at
|
||||
- autotrans
|
||||
listquotes:
|
||||
- listquotes
|
||||
- liqu
|
||||
typedel:
|
||||
- typedel
|
||||
typelist:
|
||||
|
@ -1210,12 +1236,6 @@ linkonlychannel:
|
|||
- linkssonly
|
||||
coordreload:
|
||||
- coordreload
|
||||
quotesexport:
|
||||
- quotesexport
|
||||
- qexport
|
||||
quotesimport:
|
||||
- quotesimport
|
||||
- qimport
|
||||
showembed:
|
||||
- showembed
|
||||
# EllieExpressions
|
||||
|
|
|
@ -2502,7 +2502,7 @@ autotranslate:
|
|||
params:
|
||||
- autoDelete:
|
||||
desc: "The option to automatically remove translated messages from the chat."
|
||||
listquotes:
|
||||
quotelist:
|
||||
desc: Lists all quotes on the server ordered alphabetically or by ID. 15 Per page.
|
||||
ex:
|
||||
- 3
|
||||
|
|
Loading…
Reference in a new issue