added %img:YOUR_TAG% custom reactions placeholder to pull imgur images with that tag.

This commit is contained in:
Master Kwoth 2017-06-17 15:23:13 +02:00
parent 838da3d827
commit abd2937708
2 changed files with 68 additions and 20 deletions

View File

@ -1,10 +1,13 @@
using Discord; using AngleSharp;
using AngleSharp.Dom.Html;
using Discord;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.DataStructures; using NadekoBot.DataStructures;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services.Database.Models; using NadekoBot.Services.Database.Models;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -14,13 +17,7 @@ namespace NadekoBot.Services.CustomReactions
{ {
public static Dictionary<string, Func<IUserMessage, string, string>> responsePlaceholders = new Dictionary<string, Func<IUserMessage, string, string>>() public static Dictionary<string, Func<IUserMessage, string, string>> responsePlaceholders = new Dictionary<string, Func<IUserMessage, string, string>>()
{ {
{"%target%", (ctx, trigger) => { return ctx.Content.Substring(trigger.Length).Trim().SanitizeMentions(); } } {"%target%", (ctx, trigger) => { return ctx.Content.Substring(trigger.Length).Trim().SanitizeMentions(); } },
};
public static Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>> placeholders = new Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>>()
{
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
{"%user%", (ctx, client) => { return ctx.Author.Mention; } },
{"%rnduser%", (ctx, client) => { {"%rnduser%", (ctx, client) => {
//var ch = ctx.Channel as ITextChannel; //var ch = ctx.Channel as ITextChannel;
//if(ch == null) //if(ch == null)
@ -40,15 +37,22 @@ namespace NadekoBot.Services.CustomReactions
//var users = g.Users.ToArray(); //var users = g.Users.ToArray();
//return users[new NadekoRandom().Next(0, users.Length-1)].Mention; //return users[new NadekoRandom().Next(0, users.Length-1)].Mention;
} } } },
};
public static Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>> placeholders = new Dictionary<string, Func<IUserMessage, DiscordShardedClient, string>>()
{
{"%mention%", (ctx, client) => { return $"<@{client.CurrentUser.Id}>"; } },
{"%user%", (ctx, client) => { return ctx.Author.Mention; } },
//{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } } //{"%rng%", (ctx) => { return new NadekoRandom().Next(0,10).ToString(); } }
}; };
private static readonly Regex rngRegex = new Regex("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%", RegexOptions.Compiled); private static readonly Regex rngRegex = new Regex("%rng(?:(?<from>(?:-)?\\d+)-(?<to>(?:-)?\\d+))?%", RegexOptions.Compiled);
private static readonly Regex imgRegex = new Regex("%(img|image):(?<tag>.*?)%", RegexOptions.Compiled);
private static readonly NadekoRandom rng = new NadekoRandom(); private static readonly NadekoRandom rng = new NadekoRandom();
public static Dictionary<Regex, MatchEvaluator> regexPlaceholders = new Dictionary<Regex, MatchEvaluator>() public static Dictionary<Regex, Func<Match, Task<string>>> regexPlaceholders = new Dictionary<Regex, Func<Match, Task<string>>>()
{ {
{ rngRegex, (match) => { { rngRegex, (match) => {
int from = 0; int from = 0;
@ -59,13 +63,34 @@ namespace NadekoBot.Services.CustomReactions
if(from == 0 && to == 0) if(from == 0 && to == 0)
{ {
return rng.Next(0, 11).ToString(); return Task.FromResult(rng.Next(0, 11).ToString());
} }
if(from >= to) if(from >= to)
return Task.FromResult(string.Empty);
return Task.FromResult(rng.Next(from,to+1).ToString());
} },
{ imgRegex, async (match) => {
var tag = match.Groups["tag"].ToString();
if(string.IsNullOrWhiteSpace(tag))
return ""; return "";
return rng.Next(from,to+1).ToString(); var fullQueryLink = $"http://imgur.com/search?q={ tag }";
var config = Configuration.Default.WithDefaultLoader();
var document = await BrowsingContext.New(config).OpenAsync(fullQueryLink);
var elems = document.QuerySelectorAll("a.image-list-link").ToArray();
if (!elems.Any())
return "";
var img = (elems.ElementAtOrDefault(new NadekoRandom().Next(0, elems.Length))?.Children?.FirstOrDefault() as IHtmlImageElement);
if (img?.Source == null)
return "";
return " "+img.Source.Replace("b.", ".") + " ";
} } } }
}; };
@ -73,26 +98,31 @@ namespace NadekoBot.Services.CustomReactions
{ {
foreach (var ph in placeholders) foreach (var ph in placeholders)
{ {
if (str.Contains(ph.Key))
str = str.ToLowerInvariant().Replace(ph.Key, ph.Value(ctx, client)); str = str.ToLowerInvariant().Replace(ph.Key, ph.Value(ctx, client));
} }
return str; return str;
} }
private static string ResolveResponseString(this string str, IUserMessage ctx, DiscordShardedClient client, string resolvedTrigger) private static async Task<string> ResolveResponseStringAsync(this string str, IUserMessage ctx, DiscordShardedClient client, string resolvedTrigger)
{ {
foreach (var ph in placeholders) foreach (var ph in placeholders)
{ {
str = str.Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, client)); var lowerKey = ph.Key.ToLowerInvariant();
if (str.Contains(lowerKey))
str = str.Replace(lowerKey, ph.Value(ctx, client));
} }
foreach (var ph in responsePlaceholders) foreach (var ph in responsePlaceholders)
{ {
str = str.Replace(ph.Key.ToLowerInvariant(), ph.Value(ctx, resolvedTrigger)); var lowerKey = ph.Key.ToLowerInvariant();
if (str.Contains(lowerKey))
str = str.Replace(lowerKey, ph.Value(ctx, resolvedTrigger));
} }
foreach (var ph in regexPlaceholders) foreach (var ph in regexPlaceholders)
{ {
str = ph.Key.Replace(str, ph.Value); str = await ph.Key.ReplaceAsync(str, ph.Value);
} }
return str; return str;
} }
@ -100,8 +130,8 @@ namespace NadekoBot.Services.CustomReactions
public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client) public static string TriggerWithContext(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client)
=> cr.Trigger.ResolveTriggerString(ctx, client); => cr.Trigger.ResolveTriggerString(ctx, client);
public static string ResponseWithContext(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client) public static Task<string > ResponseWithContextAsync(this CustomReaction cr, IUserMessage ctx, DiscordShardedClient client)
=> cr.Response.ResolveResponseString(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client)); => cr.Response.ResolveResponseStringAsync(ctx, client, cr.Trigger.ResolveTriggerString(ctx, client));
public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context, DiscordShardedClient client, CustomReactionsService crs) public static async Task<IUserMessage> Send(this CustomReaction cr, IUserMessage context, DiscordShardedClient client, CustomReactionsService crs)
{ {
@ -113,7 +143,7 @@ namespace NadekoBot.Services.CustomReactions
{ {
return await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? ""); return await channel.EmbedAsync(crembed.ToEmbed(), crembed.PlainText ?? "");
} }
return await channel.SendMessageAsync(cr.ResponseWithContext(context, client).SanitizeMentions()); return await channel.SendMessageAsync((await cr.ResponseWithContextAsync(context, client)).SanitizeMentions());
} }
} }
} }

View File

@ -11,6 +11,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -18,6 +19,23 @@ namespace NadekoBot.Extensions
{ {
public static class Extensions public static class Extensions
{ {
public static async Task<string> ReplaceAsync(this Regex regex, string input, Func<Match, Task<string>> replacementFn)
{
var sb = new StringBuilder();
var lastIndex = 0;
foreach (Match match in regex.Matches(input))
{
sb.Append(input, lastIndex, match.Index - lastIndex)
.Append(await replacementFn(match).ConfigureAwait(false));
lastIndex = match.Index + match.Length;
}
sb.Append(input, lastIndex, input.Length - lastIndex);
return sb.ToString();
}
public static void ThrowIfNull<T>(this T obj, string name) where T : class public static void ThrowIfNull<T>(this T obj, string name) where T : class
{ {
if (obj == null) if (obj == null)