more localization, fixes, etc, no idea exactly what, rategirl is commented out until i fix the last bug

This commit is contained in:
Kwoth 2017-02-20 23:46:34 +01:00
parent 8b703294f1
commit 06cafa1296
32 changed files with 393 additions and 158 deletions

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
namespace NadekoBot.DataStructures
{
public class AsyncLazy<T> : Lazy<Task<T>>
{
public AsyncLazy(Func<T> valueFactory) :
base(() => Task.Factory.StartNew(valueFactory))
{ }
public AsyncLazy(Func<Task<T>> taskFactory) :
base(() => Task.Factory.StartNew(taskFactory).Unwrap())
{ }
public TaskAwaiter<T> GetAwaiter() { return Value.GetAwaiter(); }
}
}

View File

@ -16,7 +16,7 @@ using NLog;
namespace NadekoBot.Modules.Administration namespace NadekoBot.Modules.Administration
{ {
[NadekoModule("Administration", ".")] [NadekoModule("Administration", ".")]
public partial class Administration : NadekoModule public partial class Administration : NadekoTopLevelModule
{ {
private static ConcurrentHashSet<ulong> deleteMessagesOnCommand { get; } private static ConcurrentHashSet<ulong> deleteMessagesOnCommand { get; }

View File

@ -1068,7 +1068,7 @@ namespace NadekoBot.Modules.Administration
public static class GuildExtensions public static class GuildExtensions
{ {
public static string GetLogText(this IGuild guild, string key, params object[] replacements) public static string GetLogText(this IGuild guild, string key, params object[] replacements)
=> NadekoModule.GetTextStatic(key, => NadekoTopLevelModule.GetTextStatic(key,
NadekoBot.Localization.GetCultureInfo(guild), NadekoBot.Localization.GetCultureInfo(guild),
typeof(Administration).Name.ToLowerInvariant(), typeof(Administration).Name.ToLowerInvariant(),
replacements); replacements);

View File

@ -17,7 +17,7 @@ using NLog;
namespace NadekoBot.Modules.ClashOfClans namespace NadekoBot.Modules.ClashOfClans
{ {
[NadekoModule("ClashOfClans", ",")] [NadekoModule("ClashOfClans", ",")]
public class ClashOfClans : NadekoModule public class ClashOfClans : NadekoTopLevelModule
{ {
public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>(); public static ConcurrentDictionary<ulong, List<ClashWar>> ClashWars { get; set; } = new ConcurrentDictionary<ulong, List<ClashWar>>();

View File

@ -135,7 +135,7 @@ namespace NadekoBot.Modules.ClashOfClans
public static string Localize(this ClashWar cw, string key) public static string Localize(this ClashWar cw, string key)
{ {
return NadekoModule.GetTextStatic(key, return NadekoTopLevelModule.GetTextStatic(key,
NadekoBot.Localization.GetCultureInfo(cw.Channel?.GuildId), NadekoBot.Localization.GetCultureInfo(cw.Channel?.GuildId),
typeof(ClashOfClans).Name.ToLowerInvariant()); typeof(ClashOfClans).Name.ToLowerInvariant());
} }

View File

@ -17,7 +17,7 @@ using NadekoBot.DataStructures;
namespace NadekoBot.Modules.CustomReactions namespace NadekoBot.Modules.CustomReactions
{ {
[NadekoModule("CustomReactions", ".")] [NadekoModule("CustomReactions", ".")]
public class CustomReactions : NadekoModule public class CustomReactions : NadekoTopLevelModule
{ {
private static CustomReaction[] _globalReactions = new CustomReaction[] { }; private static CustomReaction[] _globalReactions = new CustomReaction[] { };
public static CustomReaction[] GlobalReactions => _globalReactions; public static CustomReaction[] GlobalReactions => _globalReactions;

View File

@ -272,12 +272,12 @@ namespace NadekoBot.Modules.Gambling
} }
private string GetText(string text) private string GetText(string text)
=> NadekoModule.GetTextStatic(text, => NadekoTopLevelModule.GetTextStatic(text,
NadekoBot.Localization.GetCultureInfo(_raceChannel.Guild), NadekoBot.Localization.GetCultureInfo(_raceChannel.Guild),
typeof(Gambling).Name.ToLowerInvariant()); typeof(Gambling).Name.ToLowerInvariant());
private string GetText(string text, params object[] replacements) private string GetText(string text, params object[] replacements)
=> NadekoModule.GetTextStatic(text, => NadekoTopLevelModule.GetTextStatic(text,
NadekoBot.Localization.GetCultureInfo(_raceChannel.Guild), NadekoBot.Localization.GetCultureInfo(_raceChannel.Guild),
typeof(Gambling).Name.ToLowerInvariant(), typeof(Gambling).Name.ToLowerInvariant(),
replacements); replacements);

View File

@ -10,6 +10,7 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
using ImageSharp.Formats;
using Image = ImageSharp.Image; using Image = ImageSharp.Image;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
@ -35,7 +36,7 @@ namespace NadekoBot.Modules.Gambling
var imageStream = await Task.Run(() => var imageStream = await Task.Run(() =>
{ {
var ms = new MemoryStream(); var ms = new MemoryStream();
new[] { GetDice(num1), GetDice(num2) }.Merge().SaveAsPng(ms); new[] { GetDice(num1), GetDice(num2) }.Merge().Save(ms);
ms.Position = 0; ms.Position = 0;
return ms; return ms;
}).ConfigureAwait(false); }).ConfigureAwait(false);
@ -120,7 +121,7 @@ namespace NadekoBot.Modules.Gambling
var bitmap = dice.Merge(); var bitmap = dice.Merge();
var ms = new MemoryStream(); var ms = new MemoryStream();
bitmap.SaveAsPng(ms); bitmap.Save(ms);
ms.Position = 0; ms.Position = 0;
await Context.Channel.SendFileAsync(ms, "dice.png", await Context.Channel.SendFileAsync(ms, "dice.png",
Context.User.Mention + Context.User.Mention +

View File

@ -49,7 +49,7 @@ namespace NadekoBot.Modules.Gambling
images.Add(new Image(stream)); images.Add(new Image(stream));
} }
MemoryStream bitmapStream = new MemoryStream(); MemoryStream bitmapStream = new MemoryStream();
images.Merge().SaveAsPng(bitmapStream); images.Merge().Save(bitmapStream);
bitmapStream.Position = 0; bitmapStream.Position = 0;
var toSend = $"{Context.User.Mention}"; var toSend = $"{Context.User.Mention}";
if (cardObjects.Count == 5) if (cardObjects.Count == 5)

View File

@ -52,17 +52,22 @@ namespace NadekoBot.Modules.Gambling
return; return;
} }
var imgs = new Image[count]; var imgs = new Image[count];
using (var heads = _images.Heads.ToStream()) for (var i = 0; i < count; i++)
using(var tails = _images.Tails.ToStream())
{ {
for (var i = 0; i < count; i++) using (var heads = _images.Heads.ToStream())
using (var tails = _images.Tails.ToStream())
{ {
imgs[i] = rng.Next(0, 10) < 5 ? if (rng.Next(0, 10) < 5)
new Image(heads) : {
new Image(tails); imgs[i] = new Image(heads);
}
else
{
imgs[i] = new Image(tails);
}
} }
await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
} }
await Context.Channel.SendFileAsync(imgs.Merge().ToStream(), $"{count} coins.png").ConfigureAwait(false);
} }
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]

View File

@ -1,5 +1,6 @@
using Discord; using Discord;
using Discord.Commands; using Discord.Commands;
using ImageSharp;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Services; using NadekoBot.Services;
@ -163,83 +164,43 @@ namespace NadekoBot.Modules.Gambling
var result = SlotMachine.Pull(); var result = SlotMachine.Pull();
int[] numbers = result.Numbers; int[] numbers = result.Numbers;
using (var bgPixels = bgImage.Lock())
for (int i = 0; i < 3; i++)
{ {
for (int i = 0; i < 3; i++) using (var file = _images.SlotEmojis[numbers[i]].ToStream())
using (var randomImage = new ImageSharp.Image(file))
{ {
using (var file = _images.SlotEmojis[numbers[i]].ToStream()) bgImage.DrawImage(randomImage, 100, default(Size), new Point(95 + 142 * i, 330));
{
var randomImage = new ImageSharp.Image(file);
using (var toAdd = randomImage.Lock())
{
for (int j = 0; j < toAdd.Width; j++)
{
for (int k = 0; k < toAdd.Height; k++)
{
var x = 95 + 142 * i + j;
int y = 330 + k;
var toSet = toAdd[j, k];
if (toSet.A < _alphaCutOut)
continue;
bgPixels[x, y] = toAdd[j, k];
}
}
}
}
} }
var won = amount * result.Multiplier;
var printWon = won;
var n = 0;
do
{
var digit = printWon % 10;
using (var fs = NadekoBot.Images.SlotNumbers[digit].ToStream())
{
var img = new ImageSharp.Image(fs);
using (var pixels = img.Lock())
{
for (int i = 0; i < pixels.Width; i++)
{
for (int j = 0; j < pixels.Height; j++)
{
if (pixels[i, j].A < _alphaCutOut)
continue;
var x = 230 - n * 16 + i;
bgPixels[x, 462 + j] = pixels[i, j];
}
}
}
}
n++;
} while ((printWon /= 10) != 0);
var printAmount = amount;
n = 0;
do
{
var digit = printAmount % 10;
using (var fs = _images.SlotNumbers[digit].ToStream())
{
var img = new ImageSharp.Image(fs);
using (var pixels = img.Lock())
{
for (int i = 0; i < pixels.Width; i++)
{
for (int j = 0; j < pixels.Height; j++)
{
if (pixels[i, j].A < _alphaCutOut)
continue;
var x = 395 - n * 16 + i;
bgPixels[x, 462 + j] = pixels[i, j];
}
}
}
}
n++;
} while ((printAmount /= 10) != 0);
} }
var won = amount * result.Multiplier;
var printWon = won;
var n = 0;
do
{
var digit = printWon % 10;
using (var fs = NadekoBot.Images.SlotNumbers[digit].ToStream())
using (var img = new ImageSharp.Image(fs))
{
bgImage.DrawImage(img, 100, default(Size), new Point(230 - n * 16, 462));
}
n++;
} while ((printWon /= 10) != 0);
var printAmount = amount;
n = 0;
do
{
var digit = printAmount % 10;
using (var fs = _images.SlotNumbers[digit].ToStream())
using (var img = new ImageSharp.Image(fs))
{
bgImage.DrawImage(img, 100, default(Size), new Point(395 - n * 16, 462));
}
n++;
} while ((printAmount /= 10) != 0);
var msg = GetText("better_luck"); var msg = GetText("better_luck");
if (result.Multiplier != 0) if (result.Multiplier != 0)
{ {

View File

@ -12,7 +12,7 @@ using System.Collections.Generic;
namespace NadekoBot.Modules.Gambling namespace NadekoBot.Modules.Gambling
{ {
[NadekoModule("Gambling", "$")] [NadekoModule("Gambling", "$")]
public partial class Gambling : NadekoModule public partial class Gambling : NadekoTopLevelModule
{ {
public static string CurrencyName { get; set; } public static string CurrencyName { get; set; }
public static string CurrencyPluralName { get; set; } public static string CurrencyPluralName { get; set; }

View File

@ -299,7 +299,7 @@ $@"--
} }
private string GetText(string key, params object[] replacements) private string GetText(string key, params object[] replacements)
=> NadekoModule.GetTextStatic(key, => NadekoTopLevelModule.GetTextStatic(key,
NadekoBot.Localization.GetCultureInfo(_channel.Guild), NadekoBot.Localization.GetCultureInfo(_channel.Guild),
typeof(Games).Name.ToLowerInvariant()); typeof(Games).Name.ToLowerInvariant());
} }

View File

@ -4,18 +4,33 @@ using NadekoBot.Services;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Attributes; using NadekoBot.Attributes;
using System; using System;
using System.Collections.Concurrent;
using System.Linq; using System.Linq;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.IO;
using System.Threading;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Net.Http;
using ImageSharp;
using NadekoBot.DataStructures;
using NLog;
using ImageSharp.Drawing.Pens;
using SixLabors.Shapes;
namespace NadekoBot.Modules.Games namespace NadekoBot.Modules.Games
{ {
[NadekoModule("Games", ">")] [NadekoModule("Games", ">")]
public partial class Games : NadekoModule public partial class Games : NadekoTopLevelModule
{ {
private static readonly ImmutableArray<string> _8BallResponses = NadekoBot.BotConfig.EightBallResponses.Select(ebr => ebr.Text).ToImmutableArray(); private static readonly ImmutableArray<string> _8BallResponses = NadekoBot.BotConfig.EightBallResponses.Select(ebr => ebr.Text).ToImmutableArray();
private static readonly Timer _t = new Timer((_) =>
{
_girlRatings.Clear();
}, null, TimeSpan.FromDays(1), TimeSpan.FromDays(1));
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Choose([Remainder] string list = null) public async Task Choose([Remainder] string list = null)
{ {
@ -91,6 +106,155 @@ namespace NadekoBot.Modules.Games
await Context.Channel.SendConfirmAsync(msg).ConfigureAwait(false); await Context.Channel.SendConfirmAsync(msg).ConfigureAwait(false);
} }
private static readonly ConcurrentDictionary<ulong, GirlRating> _girlRatings = new ConcurrentDictionary<ulong, GirlRating>();
public class GirlRating
{
private static Logger _log = LogManager.GetCurrentClassLogger();
public double Crazy { get; }
public double Hot { get; }
public int Roll { get; }
public string Advice { get; }
public AsyncLazy<string> Url { get; }
public GirlRating(double crazy, double hot, int roll, string advice)
{
Crazy = crazy;
Hot = hot;
Roll = roll;
Advice = advice; // convenient to have it here, even though atm there are only few different ones.
Url = new AsyncLazy<string>(async () =>
{
try
{
using (var ms = new MemoryStream(NadekoBot.Images.WifeMatrix.ToArray(), false))
using (var img = new ImageSharp.Image(ms))
{
var clr = new ImageSharp.Color(0x0000ff);
const int minx = 35;
const int miny = 385;
const int length = 345;
var pointx = (int)(minx + length * (Hot / 10));
var pointy = (int)(miny - length * ((Crazy - 4) / 6));
var p = new Pen(ImageSharp.Color.Red, 5);
img.Draw(p, new SixLabors.Shapes.Ellipse(200, 200, 5, 5));
string url;
using (var http = new HttpClient())
using (var imgStream = new MemoryStream())
{
img.Save(imgStream);
var byteContent = new ByteArrayContent(imgStream.ToArray());
http.AddFakeHeaders();
var reponse = await http.PutAsync("https://transfer.sh/img.png", byteContent);
url = await reponse.Content.ReadAsStringAsync();
}
return url;
}
}
catch (Exception ex)
{
_log.Warn(ex);
return null;
}
});
}
}
//[NadekoCommand, Usage, Description, Aliases]
//[RequireContext(ContextType.Guild)]
//public async Task RateGirl(IGuildUser usr)
//{
// var gr = _girlRatings.GetOrAdd(usr.Id, GetGirl);
// var img = await gr.Url;
// await Context.Channel.EmbedAsync(new EmbedBuilder().WithOkColor()
// .WithTitle("Girl Rating For " + usr)
// .AddField(efb => efb.WithName("Hot").WithValue(gr.Hot.ToString("F2")).WithIsInline(true))
// .AddField(efb => efb.WithName("Crazy").WithValue(gr.Crazy.ToString("F2")).WithIsInline(true))
// .AddField(efb => efb.WithName("Advice").WithValue(gr.Advice).WithIsInline(false))
// .WithImageUrl(img)).ConfigureAwait(false);
//}
private double NextDouble(double x, double y)
{
var rng = new Random();
return rng.NextDouble() * (y - x) + x;
}
private GirlRating GetGirl(ulong uid)
{
var rng = new NadekoRandom();
var roll = rng.Next(1, 1001);
double hot;
double crazy;
string advice;
if (roll < 500)
{
hot = NextDouble(0, 5);
crazy = NextDouble(4, 10);
advice =
"This is your NO-GO ZONE. We do not hang around, and date, and marry women who are atleast, in our mind, a 5. " +
"So, this is your no-go zone. You don't go here. You just rule this out. Life is better this way, that's the way it is.";
}
else if (roll < 750)
{
hot = NextDouble(5, 8);
crazy = NextDouble(4, .6 * hot + 4);
advice = "Above a 5, and to about an 8, and below the crazy line - this is your FUN ZONE. You can " +
"hang around here, and meet these girls and spend time with them. Keep in mind, while you're " +
"in the fun zone, you want to move OUT of the fun zone to a more permanent location. " +
"These girls are most of the time not crazy.";
}
else if (roll < 900)
{
hot = NextDouble(5, 10);
crazy = NextDouble(.61 * hot + 4, 10);
advice = "Above the crazy line - it's the DANGER ZONE. This is redheads, strippers, anyone named Tiffany, " +
"hairdressers... This is where your car gets keyed, you get bunny in the pot, your tires get slashed, " +
"and you wind up in jail.";
}
else if (roll < 951)
{
hot = NextDouble(8, 10);
crazy = NextDouble(4, 10);
advice = "Below the crazy line, above an 8 hot, but still about 7 crazy. This is your DATE ZONE. " +
"You can stay in the date zone indefinitely. These are the girls you introduce to your friends and your family. " +
"They're good looking, and they're reasonably not crazy most of the time. You can stay here indefinitely.";
}
else if (roll < 990)
{
hot = NextDouble(8, 10);
crazy = NextDouble(5, 7);
advice = "Above an 8 hot, and between about 7 and a 5 crazy - this is WIFE ZONE. You you meet this girl, you should consider long-term " +
"relationship. Rare.";
}
else if (roll < 999)
{
hot = NextDouble(8, 10);
crazy = NextDouble(2, 3.99d);
advice = "You've met a girl she's above 8 hot, and not crazy at all (below 4)... totally cool?" +
" You should be careful. That's a dude. It's a tranny.";
}
else
{
hot = NextDouble(8, 10);
crazy = NextDouble(4, 5);
advice = "Below 5 crazy, and above 8 hot, this is the UNICORN ZONE, these things don't exist." +
"If you find a unicorn, please capture it safely, keep it alive, we'd like to study it, " +
"and maybe look at how to replicate that.";
}
return new GirlRating(crazy, hot, roll, advice);
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Linux(string guhnoo, string loonix) public async Task Linux(string guhnoo, string loonix)
{ {

View File

@ -13,7 +13,7 @@ using System.Collections.Generic;
namespace NadekoBot.Modules.Help namespace NadekoBot.Modules.Help
{ {
[NadekoModule("Help", "-")] [NadekoModule("Help", "-")]
public class Help : NadekoModule public class Help : NadekoTopLevelModule
{ {
private static string helpString { get; } = NadekoBot.BotConfig.HelpString; private static string helpString { get; } = NadekoBot.BotConfig.HelpString;
public static string HelpString => String.Format(helpString, NadekoBot.Credentials.ClientId, NadekoBot.ModulePrefixes[typeof(Help).Name]); public static string HelpString => String.Format(helpString, NadekoBot.Credentials.ClientId, NadekoBot.ModulePrefixes[typeof(Help).Name]);

View File

@ -20,7 +20,7 @@ namespace NadekoBot.Modules.Music
{ {
[NadekoModule("Music", "!!")] [NadekoModule("Music", "!!")]
[DontAutoLoad] [DontAutoLoad]
public partial class Music : NadekoModule public partial class Music : NadekoTopLevelModule
{ {
public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>(); public static ConcurrentDictionary<ulong, MusicPlayer> MusicPlayers { get; } = new ConcurrentDictionary<ulong, MusicPlayer>();

View File

@ -17,7 +17,7 @@ using System.Collections.Concurrent;
namespace NadekoBot.Modules.NSFW namespace NadekoBot.Modules.NSFW
{ {
[NadekoModule("NSFW", "~")] [NadekoModule("NSFW", "~")]
public class NSFW : NadekoModule public class NSFW : NadekoTopLevelModule
{ {
private static readonly ConcurrentDictionary<ulong, Timer> AutoHentaiTimers = new ConcurrentDictionary<ulong, Timer>(); private static readonly ConcurrentDictionary<ulong, Timer> AutoHentaiTimers = new ConcurrentDictionary<ulong, Timer>();

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace NadekoBot.Modules namespace NadekoBot.Modules
{ {
public abstract class NadekoModule : ModuleBase public abstract class NadekoTopLevelModule : ModuleBase
{ {
protected readonly Logger _log; protected readonly Logger _log;
protected CultureInfo _cultureInfo; protected CultureInfo _cultureInfo;
@ -17,7 +17,7 @@ namespace NadekoBot.Modules
public readonly string ModuleTypeName; public readonly string ModuleTypeName;
public readonly string LowerModuleTypeName; public readonly string LowerModuleTypeName;
protected NadekoModule(bool isTopLevelModule = true) protected NadekoTopLevelModule(bool isTopLevelModule = true)
{ {
//if it's top level module //if it's top level module
ModuleTypeName = isTopLevelModule ? this.GetType().Name : this.GetType().DeclaringType.Name; ModuleTypeName = isTopLevelModule ? this.GetType().Name : this.GetType().DeclaringType.Name;
@ -120,7 +120,7 @@ namespace NadekoBot.Modules
} }
} }
public abstract class NadekoSubmodule : NadekoModule public abstract class NadekoSubmodule : NadekoTopLevelModule
{ {
protected NadekoSubmodule() : base(false) protected NadekoSubmodule() : base(false)
{ {

View File

@ -15,7 +15,7 @@ using NLog;
namespace NadekoBot.Modules.Permissions namespace NadekoBot.Modules.Permissions
{ {
[NadekoModule("Permissions", ";")] [NadekoModule("Permissions", ";")]
public partial class Permissions : NadekoModule public partial class Permissions : NadekoTopLevelModule
{ {
public class PermissionCache public class PermissionCache
{ {

View File

@ -16,7 +16,7 @@ using System.Collections.Concurrent;
namespace NadekoBot.Modules.Pokemon namespace NadekoBot.Modules.Pokemon
{ {
[NadekoModule("Pokemon", ">")] [NadekoModule("Pokemon", ">")]
public class Pokemon : NadekoModule public class Pokemon : NadekoTopLevelModule
{ {
private static readonly List<PokemonType> _pokemonTypes = new List<PokemonType>(); private static readonly List<PokemonType> _pokemonTypes = new List<PokemonType>();
private static readonly ConcurrentDictionary<ulong, PokeStats> _stats = new ConcurrentDictionary<ulong, PokeStats>(); private static readonly ConcurrentDictionary<ulong, PokeStats> _stats = new ConcurrentDictionary<ulong, PokeStats>();

View File

@ -1,5 +1,4 @@
using Discord; using Discord;
using Discord.Commands;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using System; using System;
@ -8,27 +7,25 @@ using System.Text;
using System.Net.Http; using System.Net.Http;
using NadekoBot.Services; using NadekoBot.Services;
using System.Threading.Tasks; using System.Threading.Tasks;
using NadekoBot.Attributes;
using System.Text.RegularExpressions;
using System.Net; using System.Net;
using NadekoBot.Modules.Searches.Models; using NadekoBot.Modules.Searches.Models;
using System.Collections.Generic; using System.Collections.Generic;
using ImageSharp;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.IO; using System.IO;
using NadekoBot.Modules.Searches.Commands.OMDB; using NadekoBot.Modules.Searches.Commands.OMDB;
using NadekoBot.Modules.Searches.Commands.Models; using NadekoBot.Modules.Searches.Commands.Models;
using AngleSharp.Parser.Html;
using AngleSharp; using AngleSharp;
using AngleSharp.Dom.Html; using AngleSharp.Dom.Html;
using AngleSharp.Dom; using AngleSharp.Dom;
using System.Xml; using System.Xml;
using System.Xml.Linq; using Configuration = AngleSharp.Configuration;
using NadekoBot.Attributes;
using Discord.Commands;
namespace NadekoBot.Modules.Searches namespace NadekoBot.Modules.Searches
{ {
[NadekoModule("Searches", "~")] [NadekoModule("Searches", "~")]
public partial class Searches : NadekoModule public partial class Searches : NadekoTopLevelModule
{ {
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
public async Task Weather([Remainder] string query) public async Task Weather([Remainder] string query)
@ -396,7 +393,7 @@ namespace NadekoBot.Modules.Searches
msg = "⚠ Found over 4 images. Showing random 4."; msg = "⚠ Found over 4 images. Showing random 4.";
} }
var ms = new MemoryStream(); var ms = new MemoryStream();
await Task.Run(() => images.AsEnumerable().Merge().SaveAsPng(ms)); await Task.Run(() => images.AsEnumerable().Merge().Save(ms));
ms.Position = 0; ms.Position = 0;
await Context.Channel.SendFileAsync(ms, arg + ".png", msg).ConfigureAwait(false); await Context.Channel.SendFileAsync(ms, arg + ".png", msg).ConfigureAwait(false);
} }
@ -625,7 +622,7 @@ namespace NadekoBot.Modules.Searches
return; return;
var img = new ImageSharp.Image(50, 50); var img = new ImageSharp.Image(50, 50);
img.BackgroundColor(new ImageSharp.Color(color)); //img.FillPolygon(new ImageSharp, new ImageSharp.Color(color));
await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png").ConfigureAwait(false); ; await Context.Channel.SendFileAsync(img.ToStream(), $"{color}.png").ConfigureAwait(false); ;
} }

View File

@ -6,7 +6,6 @@ using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Text; using System.Text;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using System.Text.RegularExpressions;
using System.Reflection; using System.Reflection;
using NadekoBot.Services.Impl; using NadekoBot.Services.Impl;
using System.Net.Http; using System.Net.Http;
@ -21,7 +20,7 @@ using NadekoBot.Services;
namespace NadekoBot.Modules.Utility namespace NadekoBot.Modules.Utility
{ {
[NadekoModule("Utility", ".")] [NadekoModule("Utility", ".")]
public partial class Utility : NadekoModule public partial class Utility : NadekoTopLevelModule
{ {
private static ConcurrentDictionary<ulong, Timer> rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>(); private static ConcurrentDictionary<ulong, Timer> rotatingRoleColors = new ConcurrentDictionary<ulong, Timer>();
@ -122,10 +121,10 @@ namespace NadekoBot.Modules.Utility
} }
return; return;
} }
var hexColors = hexes.Select(hex => var hexColors = hexes.Select(hex =>
{ {
try { return (ImageSharp.Color?)new ImageSharp.Color(hex.Replace("#", "")); } catch { return null; } try { return (ImageSharp.Color?)ImageSharp.Color.FromHex(hex.Replace("#", "")); } catch { return null; }
}) })
.Where(c => c != null) .Where(c => c != null)
.Select(c => c.Value) .Select(c => c.Value)

View File

@ -60,6 +60,9 @@ namespace NadekoBot
OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16)); OkColor = new Color(Convert.ToUInt32(BotConfig.OkColor, 16));
ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16)); ErrorColor = new Color(Convert.ToUInt32(BotConfig.ErrorColor, 16));
} }
//ImageSharp.Configuration.Default.AddImageFormat(new ImageSharp.Formats.PngFormat());
//ImageSharp.Configuration.Default.AddImageFormat(new ImageSharp.Formats.JpegFormat());
} }
public async Task RunAsync(params string[] args) public async Task RunAsync(params string[] args)

View File

@ -2381,33 +2381,6 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to qsearch.
/// </summary>
public static string searchquote_cmd {
get {
return ResourceManager.GetString("searchquote_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a random quote for a keyword that contains any text specified in the search..
/// </summary>
public static string searchquote_desc {
get {
return ResourceManager.GetString("searchquote_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}qsearch keyword text`.
/// </summary>
public static string searchquote_usage {
get {
return ResourceManager.GetString("searchquote_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to delmsgoncmd. /// Looks up a localized string similar to delmsgoncmd.
/// </summary> /// </summary>
@ -5756,6 +5729,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to rategirl.
/// </summary>
public static string rategirl_cmd {
get {
return ResourceManager.GetString("rategirl_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Use the universal hot-crazy wife zone matrix to determine the girl&apos;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..
/// </summary>
public static string rategirl_desc {
get {
return ResourceManager.GetString("rategirl_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}rategirl @SomeGurl`.
/// </summary>
public static string rategirl_usage {
get {
return ResourceManager.GetString("rategirl_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to reloadimages. /// Looks up a localized string similar to reloadimages.
/// </summary> /// </summary>
@ -6701,6 +6701,33 @@ namespace NadekoBot.Resources {
} }
} }
/// <summary>
/// Looks up a localized string similar to qsearch.
/// </summary>
public static string searchquote_cmd {
get {
return ResourceManager.GetString("searchquote_cmd", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Shows a random quote for a keyword that contains any text specified in the search..
/// </summary>
public static string searchquote_desc {
get {
return ResourceManager.GetString("searchquote_desc", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to `{0}qsearch keyword text`.
/// </summary>
public static string searchquote_usage {
get {
return ResourceManager.GetString("searchquote_usage", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to send. /// Looks up a localized string similar to send.
/// </summary> /// </summary>

View File

@ -1151,7 +1151,7 @@
</data> </data>
<data name="searchquote_usage" xml:space="preserve"> <data name="searchquote_usage" xml:space="preserve">
<value>`{0}qsearch keyword text`</value> <value>`{0}qsearch keyword text`</value>
</data> </data>
<data name="deletequote_cmd" xml:space="preserve"> <data name="deletequote_cmd" xml:space="preserve">
<value>deletequote delq</value> <value>deletequote delq</value>
</data> </data>
@ -3141,4 +3141,13 @@
<data name="languageslist_usage" xml:space="preserve"> <data name="languageslist_usage" xml:space="preserve">
<value>`{0}langli`</value> <value>`{0}langli`</value>
</data> </data>
</root> <data name="rategirl_cmd" xml:space="preserve">
<value>rategirl</value>
</data>
<data name="rategirl_desc" xml:space="preserve">
<value>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.</value>
</data>
<data name="rategirl_usage" xml:space="preserve">
<value>`{0}rategirl @SomeGurl`</value>
</data>
</root>

View File

@ -1170,9 +1170,42 @@ Don't forget to leave your discord name or id in the message.
<data name="games_8ball" xml:space="preserve"> <data name="games_8ball" xml:space="preserve">
<value>8ball</value> <value>8ball</value>
</data> </data>
<data name="games_acrophobia" xml:space="preserve">
<value>Acrophobia</value>
</data>
<data name="games_acro_ended_no_sub" xml:space="preserve">
<value>Game ended with no submissions.</value>
</data>
<data name="games_acro_no_votes_cast" xml:space="preserve">
<value>No votes cast. Game ended with no winner.</value>
</data>
<data name="games_acro_nym_was" xml:space="preserve">
<value>Acronym was {0}.</value>
</data>
<data name="games_acro_running" xml:space="preserve"> <data name="games_acro_running" xml:space="preserve">
<value>Acrophobia game is already running in this channel.</value> <value>Acrophobia game is already running in this channel.</value>
</data> </data>
<data name="games_acro_started" xml:space="preserve">
<value>Game started. Create a sentence with the following acronym: {0}.</value>
</data>
<data name="games_acro_started_footer" xml:space="preserve">
<value>You have {0} seconds to make a submission.</value>
</data>
<data name="games_acro_submit" xml:space="preserve">
<value>{0} submitted their sentence. ({1} total)</value>
</data>
<data name="games_acro_vote" xml:space="preserve">
<value>Vote by typing a number of the submission</value>
</data>
<data name="games_acro_vote_cast" xml:space="preserve">
<value>{0} cast their vote!</value>
</data>
<data name="games_acro_winner" xml:space="preserve">
<value>Winner is {0} with {1} points.</value>
</data>
<data name="games_acro_winner_only" xml:space="preserve">
<value>{0} is the winner for being the only user who made a submission!</value>
</data>
<data name="games_question" xml:space="preserve"> <data name="games_question" xml:space="preserve">
<value>Question</value> <value>Question</value>
</data> </data>
@ -1182,4 +1215,7 @@ Don't forget to leave your discord name or id in the message.
<data name="games_rps_win" xml:space="preserve"> <data name="games_rps_win" xml:space="preserve">
<value>{0} won! {1} beats {2}</value> <value>{0} won! {1} beats {2}</value>
</data> </data>
<data name="games_submissions_closed" xml:space="preserve">
<value>Submissions Closed</value>
</data>
</root> </root>

View File

@ -21,6 +21,8 @@ namespace NadekoBot.Services
ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; } ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; }
ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; } ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; }
ImmutableArray<byte> WifeMatrix { get; }
Task<TimeSpan> Reload(); Task<TimeSpan> Reload();
} }
} }

View File

@ -28,6 +28,8 @@ namespace NadekoBot.Services.Impl
private const string slotNumbersPath = basePath + "slots/numbers/"; private const string slotNumbersPath = basePath + "slots/numbers/";
private const string slotEmojisPath = basePath + "slots/emojis/"; private const string slotEmojisPath = basePath + "slots/emojis/";
private const string _wifeMatrixPath = basePath + "wifematrix.png";
public ImmutableArray<byte> Heads { get; private set; } public ImmutableArray<byte> Heads { get; private set; }
public ImmutableArray<byte> Tails { get; private set; } public ImmutableArray<byte> Tails { get; private set; }
@ -41,6 +43,8 @@ namespace NadekoBot.Services.Impl
public ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; private set; } public ImmutableArray<ImmutableArray<byte>> SlotNumbers { get; private set; }
public ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; private set; } public ImmutableArray<ImmutableArray<byte>> SlotEmojis { get; private set; }
public ImmutableArray<byte> WifeMatrix { get; private set; }
private ImagesService() private ImagesService()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
@ -86,6 +90,8 @@ namespace NadekoBot.Services.Impl
.Select(x => File.ReadAllBytes(x).ToImmutableArray()) .Select(x => File.ReadAllBytes(x).ToImmutableArray())
.ToImmutableArray(); .ToImmutableArray();
WifeMatrix = File.ReadAllBytes(_wifeMatrixPath).ToImmutableArray();
sw.Stop(); sw.Stop();
_log.Info($"Images loaded after {sw.Elapsed.TotalSeconds:F2}s!"); _log.Info($"Images loaded after {sw.Elapsed.TotalSeconds:F2}s!");
return sw.Elapsed; return sw.Elapsed;

View File

@ -22,7 +22,11 @@ namespace NadekoBot.Extensions
private const string arrow_right = "➡"; private const string arrow_right = "➡";
public static Stream ToStream(this IEnumerable<byte> bytes, bool canWrite = false) public static Stream ToStream(this IEnumerable<byte> bytes, bool canWrite = false)
=> new MemoryStream(bytes as byte[] ?? bytes.ToArray(), canWrite); {
var ms = new MemoryStream(bytes as byte[] ?? bytes.ToArray(), canWrite);
ms.Seek(0, SeekOrigin.Begin);
return ms;
}
/// <summary> /// <summary>
/// danny kamisama /// danny kamisama
@ -398,22 +402,15 @@ namespace NadekoBot.Extensions
public static ImageSharp.Image Merge(this IEnumerable<ImageSharp.Image> images) public static ImageSharp.Image Merge(this IEnumerable<ImageSharp.Image> images)
{ {
var imgList = images.ToList(); var imgs = images.ToArray();
var canvas = new ImageSharp.Image(imgList.Sum(img => img.Width), imgList.Max(img => img.Height)); var canvas = new ImageSharp.Image(imgs.Sum(img => img.Width), imgs.Max(img => img.Height));
var canvasPixels = canvas.Lock(); var xOffset = 0;
int offsetX = 0; for (int i = 0; i < imgs.Length; i++)
foreach (var img in imgList.Select(img => img.Lock()))
{ {
for (int i = 0; i < img.Width; i++) canvas.DrawImage(imgs[i], 100, default(Size), new Point(xOffset, 0));
{ xOffset += imgs[i].Bounds.Width;
for (int j = 0; j < img.Height; j++)
{
canvasPixels[i + offsetX, j] = img[i, j];
}
}
offsetX += img.Width;
} }
return canvas; return canvas;
@ -422,7 +419,7 @@ namespace NadekoBot.Extensions
public static Stream ToStream(this ImageSharp.Image img) public static Stream ToStream(this ImageSharp.Image img)
{ {
var imageStream = new MemoryStream(); var imageStream = new MemoryStream();
img.SaveAsPng(imageStream); img.Save(imageStream);
imageStream.Position = 0; imageStream.Position = 0;
return imageStream; return imageStream;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

View File

@ -23,7 +23,12 @@
"Google.Apis.Urlshortener.v1": "1.19.0.138", "Google.Apis.Urlshortener.v1": "1.19.0.138",
"Google.Apis.YouTube.v3": "1.20.0.701", "Google.Apis.YouTube.v3": "1.20.0.701",
"Google.Apis.Customsearch.v1": "1.20.0.466", "Google.Apis.Customsearch.v1": "1.20.0.466",
"ImageSharp": "1.0.0-alpha-000079", "ImageSharp": "1.0.0-alpha2-00090",
"ImageSharp.Processing": "1.0.0-alpha2-00078",
"ImageSharp.Formats.Png": "1.0.0-alpha2-00086",
"ImageSharp.Drawing": "1.0.0-alpha2-00090",
"ImageSharp.Drawing.Paths": "1.0.0-alpha2-00040",
//"ImageSharp.Formats.Jpeg": "1.0.0-alpha2-00090",
"Microsoft.EntityFrameworkCore": "1.1.0", "Microsoft.EntityFrameworkCore": "1.1.0",
"Microsoft.EntityFrameworkCore.Design": "1.1.0", "Microsoft.EntityFrameworkCore.Design": "1.1.0",
"Microsoft.EntityFrameworkCore.Sqlite": "1.1.0", "Microsoft.EntityFrameworkCore.Sqlite": "1.1.0",