NadekoBot Patronage system, Search commands improvements + fixes

This commit is contained in:
Kwoth
2022-06-14 07:24:33 +00:00
parent 18b10b8c6f
commit 7b5145f116
165 changed files with 14920 additions and 1457 deletions

View File

@@ -1,8 +1,11 @@
#nullable disable
using NadekoBot.Common.ModuleBehaviors;
using NadekoBot.Db.Models;
using NadekoBot.Modules.Games.Common.ChatterBot;
using NadekoBot.Modules.Permissions;
using NadekoBot.Modules.Permissions.Common;
using NadekoBot.Modules.Permissions.Services;
using NadekoBot.Modules.Utility.Patronage;
namespace NadekoBot.Modules.Games.Services;
@@ -13,6 +16,8 @@ public class ChatterBotService : IExecOnMessage
public int Priority
=> 1;
private readonly FeatureLimitKey _flKey;
private readonly DiscordSocketClient _client;
private readonly PermissionService _perms;
private readonly CommandHandler _cmd;
@@ -20,6 +25,8 @@ public class ChatterBotService : IExecOnMessage
private readonly IBotCredentials _creds;
private readonly IEmbedBuilderService _eb;
private readonly IHttpClientFactory _httpFactory;
private readonly IPatronageService _ps;
private readonly CmdCdService _ccs;
public ChatterBotService(
DiscordSocketClient client,
@@ -29,7 +36,9 @@ public class ChatterBotService : IExecOnMessage
IBotStrings strings,
IHttpClientFactory factory,
IBotCredentials creds,
IEmbedBuilderService eb)
IEmbedBuilderService eb,
IPatronageService ps,
CmdCdService cmdCdService)
{
_client = client;
_perms = perms;
@@ -38,8 +47,17 @@ public class ChatterBotService : IExecOnMessage
_creds = creds;
_eb = eb;
_httpFactory = factory;
_ps = ps;
_ccs = cmdCdService;
ChatterBotGuilds = new(bot.AllGuildConfigs.Where(gc => gc.CleverbotEnabled)
_flKey = new FeatureLimitKey()
{
Key = CleverBotResponseStr.CLEVERBOT_RESPONSE,
PrettyName = "Cleverbot Replies"
};
ChatterBotGuilds = new(bot.AllGuildConfigs
.Where(gc => gc.CleverbotEnabled)
.ToDictionary(gc => gc.GuildId,
_ => new Lazy<IChatterBotSession>(() => CreateSession(), true)));
}
@@ -48,7 +66,9 @@ public class ChatterBotService : IExecOnMessage
{
if (!string.IsNullOrWhiteSpace(_creds.CleverbotApiKey))
return new OfficialCleverbotSession(_creds.CleverbotApiKey, _httpFactory);
return new CleverbotIoSession("GAh3wUfzDCpDpdpT", "RStKgqn7tcO9blbrv4KbXM8NDlb7H37C", _httpFactory);
Log.Information("Cleverbot will not work as the api key is missing.");
return null;
}
public string PrepareMessage(IUserMessage msg, out IChatterBotSession cleverbot)
@@ -78,27 +98,11 @@ public class ChatterBotService : IExecOnMessage
return message;
}
public async Task<bool> TryAsk(IChatterBotSession cleverbot, ITextChannel channel, string message)
{
await channel.TriggerTypingAsync();
var response = await cleverbot.Think(message);
try
{
await channel.SendConfirmAsync(_eb, response.SanitizeMentions(true));
}
catch
{
await channel.SendConfirmAsync(_eb, response.SanitizeMentions(true)); // try twice :\
}
return true;
}
public async Task<bool> ExecOnMessageAsync(IGuild guild, IUserMessage usrMsg)
{
if (guild is not SocketGuild sg)
return false;
try
{
var message = PrepareMessage(usrMsg, out var cbs);
@@ -106,7 +110,10 @@ public class ChatterBotService : IExecOnMessage
return false;
var pc = _perms.GetCacheFor(guild.Id);
if (!pc.Permissions.CheckPermissions(usrMsg, "cleverbot", "Games".ToLowerInvariant(), out var index))
if (!pc.Permissions.CheckPermissions(usrMsg,
"cleverbot",
"games",
out var index))
{
if (pc.Verbose)
{
@@ -122,24 +129,78 @@ public class ChatterBotService : IExecOnMessage
return true;
}
var cleverbotExecuted = await TryAsk(cbs, (ITextChannel)usrMsg.Channel, message);
if (cleverbotExecuted)
if (await _ccs.TryBlock(sg, usrMsg.Author, CleverBotResponseStr.CLEVERBOT_RESPONSE))
{
Log.Information(@"CleverBot Executed
return true;
}
var channel = (ITextChannel)usrMsg.Channel;
var conf = _ps.GetConfig();
if (conf.IsEnabled)
{
var quota = await _ps.TryGetFeatureLimitAsync(_flKey, sg.OwnerId, 0);
uint? daily = quota.Quota is int dVal and < 0
? (uint)-dVal
: null;
uint? monthly = quota.Quota is int mVal and >= 0
? (uint)mVal
: null;
var maybeLimit = await _ps.TryIncrementQuotaCounterAsync(sg.OwnerId,
sg.OwnerId == usrMsg.Author.Id,
FeatureType.Limit,
_flKey.Key,
null,
daily,
monthly);
if (maybeLimit.TryPickT1(out var ql, out var counters))
{
if (ql.Quota == 0)
{
await channel.SendErrorAsync(_eb,
null!,
text:
"In order to use the cleverbot feature, the owner of this server should be [Patron Tier X](https://patreon.com/join/nadekobot) on patreon.",
footer:
"You may disable the cleverbot feature, and this message via '.cleverbot' command");
return true;
}
await channel.SendErrorAsync(_eb,
null!,
$"You've reached your quota limit of **{ql.Quota}** responses {ql.QuotaPeriod.ToFullName()} for the cleverbot feature.",
footer: "You may wait for the quota reset or .");
return true;
}
}
_ = channel.TriggerTypingAsync();
var response = await cbs.Think(message);
await channel.SendConfirmAsync(_eb,
title: null,
response.SanitizeMentions(true)
// , footer: counter > 0 ? counter.ToString() : null
);
Log.Information(@"CleverBot Executed
Server: {GuildName} [{GuildId}]
Channel: {ChannelName} [{ChannelId}]
UserId: {Author} [{AuthorId}]
Message: {Content}",
guild.Name,
guild.Id,
usrMsg.Channel?.Name,
usrMsg.Channel?.Id,
usrMsg.Author,
usrMsg.Author.Id,
usrMsg.Content);
guild.Name,
guild.Id,
usrMsg.Channel?.Name,
usrMsg.Channel?.Id,
usrMsg.Author,
usrMsg.Author.Id,
usrMsg.Content);
return true;
}
return true;
}
catch (Exception ex)
{

View File

@@ -14,7 +14,6 @@ public partial class Games
public ChatterBotCommands(DbService db)
=> _db = db;
[NoPublicBot]
[Cmd]
[RequireContext(ContextType.Guild)]
[UserPerm(GuildPerm.ManageMessages)]

View File

@@ -1,34 +0,0 @@
#nullable disable
using Newtonsoft.Json;
namespace NadekoBot.Modules.Games.Common.ChatterBot;
public class ChatterBotSession : IChatterBotSession
{
private static NadekoRandom Rng { get; } = new();
private string ApiEndpoint
=> "http://api.program-o.com/v2/chatbot/"
+ $"?bot_id={_botId}&"
+ "say={0}&"
+ $"convo_id=nadekobot_{_chatterBotId}&"
+ "format=json";
private readonly string _chatterBotId;
private readonly IHttpClientFactory _httpFactory;
private readonly int _botId = 6;
public ChatterBotSession(IHttpClientFactory httpFactory)
{
_chatterBotId = Rng.Next(0, 1000000).ToString().ToBase64();
_httpFactory = httpFactory;
}
public async Task<string> Think(string message)
{
using var http = _httpFactory.CreateClient();
var res = await http.GetStringAsync(string.Format(ApiEndpoint, message));
var cbr = JsonConvert.DeserializeObject<ChatterBotResponse>(res);
return cbr.BotSay.Replace("<br/>", "\n", StringComparison.InvariantCulture);
}
}

View File

@@ -5,16 +5,4 @@ public class CleverbotResponse
{
public string Cs { get; set; }
public string Output { get; set; }
}
public class CleverbotIoCreateResponse
{
public string Status { get; set; }
public string Nick { get; set; }
}
public class CleverbotIoAskResponse
{
public string Status { get; set; }
public string Response { get; set; }
}

View File

@@ -35,57 +35,4 @@ public class OfficialCleverbotSession : IChatterBotSession
return null;
}
}
}
public class CleverbotIoSession : IChatterBotSession
{
private readonly string _key;
private readonly string _user;
private readonly IHttpClientFactory _httpFactory;
private readonly AsyncLazy<string> _nick;
private readonly string _createEndpoint = "https://cleverbot.io/1.0/create";
private readonly string _askEndpoint = "https://cleverbot.io/1.0/ask";
public CleverbotIoSession(string user, string key, IHttpClientFactory factory)
{
_key = key;
_user = user;
_httpFactory = factory;
_nick = new(GetNick);
}
private async Task<string> GetNick()
{
using var http = _httpFactory.CreateClient();
using var msg = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("user", _user), new KeyValuePair<string, string>("key", _key)
});
using var data = await http.PostAsync(_createEndpoint, msg);
var str = await data.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<CleverbotIoCreateResponse>(str);
if (obj.Status != "success")
throw new OperationCanceledException(obj.Status);
return obj.Nick;
}
public async Task<string> Think(string input)
{
using var http = _httpFactory.CreateClient();
using var msg = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("user", _user), new KeyValuePair<string, string>("key", _key),
new KeyValuePair<string, string>("nick", await _nick), new KeyValuePair<string, string>("text", input)
});
using var data = await http.PostAsync(_askEndpoint, msg);
var str = await data.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<CleverbotIoAskResponse>(str);
if (obj.Status != "success")
throw new OperationCanceledException(obj.Status);
return obj.Response;
}
}