added quote api
This commit is contained in:
parent
a59168da0b
commit
43f20cbbc2
6 changed files with 161 additions and 10 deletions
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
option csharp_namespace = "EllieBot.GrpcApi";
|
option csharp_namespace = "EllieBot.GrpcApi";
|
||||||
|
|
||||||
import "google/protobuf/empty.proto";
|
import "google/protobuf/empty.proto";
|
||||||
|
|
||||||
package exprs;
|
package exprs;
|
||||||
|
|
||||||
|
@ -10,6 +10,10 @@ service GrpcExprs {
|
||||||
rpc GetExprs(GetExprsRequest) returns (GetExprsReply);
|
rpc GetExprs(GetExprsRequest) returns (GetExprsReply);
|
||||||
rpc AddExpr(AddExprRequest) returns (AddExprReply);
|
rpc AddExpr(AddExprRequest) returns (AddExprReply);
|
||||||
rpc DeleteExpr(DeleteExprRequest) returns (google.protobuf.Empty);
|
rpc DeleteExpr(DeleteExprRequest) returns (google.protobuf.Empty);
|
||||||
|
|
||||||
|
rpc GetQuotes(GetQuotesRequest) returns (GetQuotesReply);
|
||||||
|
rpc AddQuote(AddQuoteRequest) returns (AddQuoteReply);
|
||||||
|
rpc DeleteQuote(DeleteQuoteRequest) returns (google.protobuf.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
message DeleteExprRequest {
|
message DeleteExprRequest {
|
||||||
|
@ -48,3 +52,38 @@ message AddExprReply {
|
||||||
string id = 1;
|
string id = 1;
|
||||||
bool success = 2;
|
bool success = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message GetQuotesRequest {
|
||||||
|
uint64 guildId = 1;
|
||||||
|
string query = 2;
|
||||||
|
int32 page = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetQuotesReply {
|
||||||
|
repeated QuoteDto quotes = 1;
|
||||||
|
int32 totalCount = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message QuoteDto {
|
||||||
|
string id = 1;
|
||||||
|
string trigger = 2;
|
||||||
|
string response = 3;
|
||||||
|
|
||||||
|
uint64 authorId = 4;
|
||||||
|
string authorName = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddQuoteRequest {
|
||||||
|
uint64 guildId = 1;
|
||||||
|
QuoteDto quote = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AddQuoteReply {
|
||||||
|
string id = 1;
|
||||||
|
bool success = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message DeleteQuoteRequest {
|
||||||
|
string id = 1;
|
||||||
|
uint64 guildId = 2;
|
||||||
|
}
|
|
@ -1,4 +1,3 @@
|
||||||
#nullable disable
|
|
||||||
using LinqToDB;
|
using LinqToDB;
|
||||||
using LinqToDB.EntityFrameworkCore;
|
using LinqToDB.EntityFrameworkCore;
|
||||||
using EllieBot.Common.ModuleBehaviors;
|
using EllieBot.Common.ModuleBehaviors;
|
||||||
|
@ -11,7 +10,7 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
private readonly DbService _db;
|
private readonly DbService _db;
|
||||||
private readonly DiscordSocketClient _client;
|
private readonly DiscordSocketClient _client;
|
||||||
private readonly IBotCredsProvider _creds;
|
private readonly IBotCredsProvider _creds;
|
||||||
private ConcurrentDictionary<ulong, ulong> _enabled;
|
private ConcurrentDictionary<ulong, ulong> _enabled = new();
|
||||||
|
|
||||||
public AutoPublishService(DbService db, DiscordSocketClient client, IBotCredsProvider creds)
|
public AutoPublishService(DbService db, DiscordSocketClient client, IBotCredsProvider creds)
|
||||||
{
|
{
|
||||||
|
@ -20,7 +19,7 @@ public class AutoPublishService : IExecNoCommand, IReadyExecutor, IEService
|
||||||
_creds = creds;
|
_creds = creds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task ExecOnNoCommandAsync(IGuild guild, IUserMessage msg)
|
public async Task ExecOnNoCommandAsync(IGuild? guild, IUserMessage msg)
|
||||||
{
|
{
|
||||||
if (guild is null)
|
if (guild is null)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -67,7 +67,6 @@ public sealed class EllieExpressionsService : IExecOnMessage, IReadyExecutor
|
||||||
// private readonly GlobalPermissionService _gperm;
|
// private readonly GlobalPermissionService _gperm;
|
||||||
// private readonly CmdCdService _cmdCds;
|
// private readonly CmdCdService _cmdCds;
|
||||||
private readonly IPermissionChecker _permChecker;
|
private readonly IPermissionChecker _permChecker;
|
||||||
private readonly ICommandHandler _cmd;
|
|
||||||
private readonly IBotStrings _strings;
|
private readonly IBotStrings _strings;
|
||||||
private readonly IBot _bot;
|
private readonly IBot _bot;
|
||||||
private readonly IPubSub _pubSub;
|
private readonly IPubSub _pubSub;
|
||||||
|
@ -84,7 +83,6 @@ public sealed class EllieExpressionsService : IExecOnMessage, IReadyExecutor
|
||||||
IBotStrings strings,
|
IBotStrings strings,
|
||||||
IBot bot,
|
IBot bot,
|
||||||
DiscordSocketClient client,
|
DiscordSocketClient client,
|
||||||
ICommandHandler cmd,
|
|
||||||
IPubSub pubSub,
|
IPubSub pubSub,
|
||||||
IMessageSenderService sender,
|
IMessageSenderService sender,
|
||||||
IReplacementService repSvc,
|
IReplacementService repSvc,
|
||||||
|
@ -93,7 +91,6 @@ public sealed class EllieExpressionsService : IExecOnMessage, IReadyExecutor
|
||||||
{
|
{
|
||||||
_db = db;
|
_db = db;
|
||||||
_client = client;
|
_client = client;
|
||||||
_cmd = cmd;
|
|
||||||
_strings = strings;
|
_strings = strings;
|
||||||
_bot = bot;
|
_bot = bot;
|
||||||
_pubSub = pubSub;
|
_pubSub = pubSub;
|
||||||
|
|
|
@ -27,6 +27,8 @@ public interface IQuoteService
|
||||||
string? keyword,
|
string? keyword,
|
||||||
string text);
|
string text);
|
||||||
|
|
||||||
|
Task<(IReadOnlyCollection<Quote> quotes, int totalCount)> FindQuotesAsync(ulong guildId, string query, int page);
|
||||||
|
|
||||||
Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId);
|
Task<IReadOnlyCollection<Quote>> GetGuildQuotesAsync(ulong guildId);
|
||||||
Task<int> RemoveAllByKeyword(ulong guildId, string keyword);
|
Task<int> RemoveAllByKeyword(ulong guildId, string keyword);
|
||||||
Task<Quote?> GetQuoteByIdAsync(ulong guildId, int quoteId);
|
Task<Quote?> GetQuoteByIdAsync(ulong guildId, int quoteId);
|
||||||
|
@ -39,6 +41,7 @@ public interface IQuoteService
|
||||||
string text);
|
string text);
|
||||||
|
|
||||||
Task<Quote?> EditQuoteAsync(ulong authorId, int quoteId, string text);
|
Task<Quote?> EditQuoteAsync(ulong authorId, int quoteId, string text);
|
||||||
|
Task<Quote?> EditQuoteAsync(ulong guildId, int quoteId, string keyword, string text);
|
||||||
|
|
||||||
Task<bool> DeleteQuoteAsync(
|
Task<bool> DeleteQuoteAsync(
|
||||||
ulong guildId,
|
ulong guildId,
|
||||||
|
|
|
@ -169,6 +169,23 @@ public sealed class QuoteService : IQuoteService, IEService
|
||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<Quote?> EditQuoteAsync(
|
||||||
|
ulong guildId,
|
||||||
|
int quoteId,
|
||||||
|
string keyword,
|
||||||
|
string text)
|
||||||
|
{
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
var result = await uow.GetTable<Quote>()
|
||||||
|
.Where(x => x.Id == quoteId && x.GuildId == guildId)
|
||||||
|
.Set(x => x.Keyword, keyword)
|
||||||
|
.Set(x => x.Text, text)
|
||||||
|
.UpdateWithOutputAsync((del, ins) => ins);
|
||||||
|
|
||||||
|
var q = result.FirstOrDefault();
|
||||||
|
return q;
|
||||||
|
}
|
||||||
|
|
||||||
public async Task<bool> DeleteQuoteAsync(
|
public async Task<bool> DeleteQuoteAsync(
|
||||||
ulong guildId,
|
ulong guildId,
|
||||||
ulong authorId,
|
ulong authorId,
|
||||||
|
@ -219,4 +236,24 @@ public sealed class QuoteService : IQuoteService, IEService
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<(IReadOnlyCollection<Quote> quotes, int totalCount)> FindQuotesAsync(
|
||||||
|
ulong guildId,
|
||||||
|
string query,
|
||||||
|
int page)
|
||||||
|
{
|
||||||
|
await using var uow = _db.GetDbContext();
|
||||||
|
|
||||||
|
var baseQuery = uow.GetTable<Quote>()
|
||||||
|
.Where(x => x.GuildId == guildId)
|
||||||
|
.Where(x => x.Keyword.Contains(query) || x.Text.Contains(query));
|
||||||
|
|
||||||
|
var quotes = await baseQuery
|
||||||
|
.OrderBy(x => x.Id)
|
||||||
|
.Skip((page - 1) * 10)
|
||||||
|
.Take(10)
|
||||||
|
.ToListAsyncLinqToDB();
|
||||||
|
|
||||||
|
return (quotes, await baseQuery.CountAsyncLinqToDB());
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -2,20 +2,31 @@
|
||||||
using Grpc.Core;
|
using Grpc.Core;
|
||||||
using EllieBot.Db.Models;
|
using EllieBot.Db.Models;
|
||||||
using EllieBot.Modules.EllieExpressions;
|
using EllieBot.Modules.EllieExpressions;
|
||||||
|
using EllieBot.Modules.Utility;
|
||||||
|
|
||||||
namespace EllieBot.GrpcApi;
|
namespace EllieBot.GrpcApi;
|
||||||
|
|
||||||
public class ExprsSvc : GrpcExprs.GrpcExprsBase, IEService
|
public class ExprsSvc : GrpcExprs.GrpcExprsBase, IEService
|
||||||
{
|
{
|
||||||
private readonly EllieExpressionsService _svc;
|
private readonly EllieExpressionsService _svc;
|
||||||
|
private readonly IQuoteService _qs;
|
||||||
|
private readonly DiscordSocketClient _client;
|
||||||
|
|
||||||
public ExprsSvc(EllieExpressionsService svc)
|
public ExprsSvc(EllieExpressionsService svc, IQuoteService qs, DiscordSocketClient client)
|
||||||
{
|
{
|
||||||
_svc = svc;
|
_svc = svc;
|
||||||
|
_qs = qs;
|
||||||
|
_client = client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private ulong GetUserId(Metadata meta)
|
||||||
|
=> ulong.Parse(meta.FirstOrDefault(x => x.Key == "userid")!.Value);
|
||||||
|
|
||||||
public override async Task<AddExprReply> AddExpr(AddExprRequest request, ServerCallContext context)
|
public override async Task<AddExprReply> AddExpr(AddExprRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Expr.Trigger) || string.IsNullOrWhiteSpace(request.Expr.Response))
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument, "Trigger and response are required"));
|
||||||
|
|
||||||
EllieExpression expr;
|
EllieExpression expr;
|
||||||
if (!string.IsNullOrWhiteSpace(request.Expr.Id))
|
if (!string.IsNullOrWhiteSpace(request.Expr.Id))
|
||||||
{
|
{
|
||||||
|
@ -66,8 +77,73 @@ public class ExprsSvc : GrpcExprs.GrpcExprsBase, IEService
|
||||||
|
|
||||||
public override async Task<Empty> DeleteExpr(DeleteExprRequest request, ServerCallContext context)
|
public override async Task<Empty> DeleteExpr(DeleteExprRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
await _svc.DeleteAsync(request.GuildId, new kwum(request.Id));
|
if (kwum.TryParse(request.Id, out var id))
|
||||||
|
await _svc.DeleteAsync(request.GuildId, id);
|
||||||
|
|
||||||
return new Empty();
|
return new Empty();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
public override async Task<GetQuotesReply> GetQuotes(GetQuotesRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
if (request.Page < 0)
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument, "Page must be >= 0"));
|
||||||
|
|
||||||
|
var (quotes, totalCount) = await _qs.FindQuotesAsync(request.GuildId, request.Query, request.Page);
|
||||||
|
|
||||||
|
var reply = new GetQuotesReply();
|
||||||
|
reply.TotalCount = totalCount;
|
||||||
|
reply.Quotes.AddRange(quotes.Select(x => new QuoteDto()
|
||||||
|
{
|
||||||
|
Id = new kwum(x.Id).ToString(),
|
||||||
|
Trigger = x.Keyword,
|
||||||
|
Response = x.Text,
|
||||||
|
AuthorId = x.AuthorId,
|
||||||
|
AuthorName = x.AuthorName
|
||||||
|
}));
|
||||||
|
|
||||||
|
return reply;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task<AddQuoteReply> AddQuote(AddQuoteRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
var userId = GetUserId(context.RequestHeaders);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Quote.Trigger) || string.IsNullOrWhiteSpace(request.Quote.Response))
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument, "Trigger and response are required"));
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(request.Quote.Id))
|
||||||
|
{
|
||||||
|
var q = await _qs.AddQuoteAsync(request.GuildId,
|
||||||
|
userId,
|
||||||
|
(await _client.GetUserAsync(userId))?.Username ?? userId.ToString(),
|
||||||
|
request.Quote.Trigger,
|
||||||
|
request.Quote.Response);
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Id = new kwum(q.Id).ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kwum.TryParse(request.Quote.Id, out var qid))
|
||||||
|
throw new RpcException(new Status(StatusCode.InvalidArgument, "Invalid quote id"));
|
||||||
|
|
||||||
|
await _qs.EditQuoteAsync(
|
||||||
|
request.GuildId,
|
||||||
|
new kwum(request.Quote.Id),
|
||||||
|
request.Quote.Trigger,
|
||||||
|
request.Quote.Response);
|
||||||
|
|
||||||
|
return new()
|
||||||
|
{
|
||||||
|
Id = new kwum(qid).ToString()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override async Task<Empty> DeleteQuote(DeleteQuoteRequest request, ServerCallContext context)
|
||||||
|
{
|
||||||
|
await _qs.DeleteQuoteAsync(request.GuildId, GetUserId(context.RequestHeaders), true, new kwum(request.Id));
|
||||||
|
return new Empty();
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue