Added .rip command again :^)

This commit is contained in:
Master Kwoth 2017-10-15 11:48:29 +02:00
parent febbb8e36b
commit 099ae62c0b
10 changed files with 229 additions and 114 deletions

View File

@ -6,6 +6,8 @@ using Discord;
using Discord.Commands; using Discord.Commands;
using Discord.WebSocket; using Discord.WebSocket;
using NadekoBot.Extensions; using NadekoBot.Extensions;
using NadekoBot.Modules.Music.Services;
using NadekoBot.Modules.Administration.Services;
namespace NadekoBot.Common.Replacements namespace NadekoBot.Common.Replacements
{ {
@ -44,19 +46,19 @@ namespace NadekoBot.Common.Replacements
_reps.TryAdd("%sid%", () => g == null ? "DM" : g.Id.ToString()); _reps.TryAdd("%sid%", () => g == null ? "DM" : g.Id.ToString());
_reps.TryAdd("%server%", () => g == null ? "DM" : g.Name); _reps.TryAdd("%server%", () => g == null ? "DM" : g.Name);
//_reps.TryAdd("%server_time%", () => _reps.TryAdd("%server_time%", () =>
//{ {
// TimeZoneInfo to = TimeZoneInfo.Local; TimeZoneInfo to = TimeZoneInfo.Local;
// if (g != null) if (g != null)
// { {
// if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz)) if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz))
// to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local; to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local;
// } }
// return TimeZoneInfo.ConvertTime(DateTime.UtcNow, return TimeZoneInfo.ConvertTime(DateTime.UtcNow,
// TimeZoneInfo.Utc, TimeZoneInfo.Utc,
// to).ToString("HH:mm ") + to.StandardName.GetInitials(); to).ToString("HH:mm ") + to.StandardName.GetInitials();
//}); });
return this; return this;
} }
@ -86,26 +88,26 @@ namespace NadekoBot.Common.Replacements
return this; return this;
} }
//public ReplacementBuilder WithMusic(MusicService ms) public ReplacementBuilder WithMusic(MusicService ms)
//{ {
// _reps.TryAdd("%playing%", () => _reps.TryAdd("%playing%", () =>
// { {
// var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.Current.Current != null); var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.Current.Current != null);
// if (cnt != 1) return cnt.ToString(); if (cnt != 1) return cnt.ToString();
// try try
// { {
// var mp = ms.MusicPlayers.FirstOrDefault(); var mp = ms.MusicPlayers.FirstOrDefault();
// var title = mp.Value?.Current.Current?.Title; var title = mp.Value?.Current.Current?.Title;
// return title ?? "No songs"; return title ?? "No songs";
// } }
// catch catch
// { {
// return "error"; return "error";
// } }
// }); });
// _reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.QueueArray().Songs.Length).ToString()); _reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.QueueArray().Songs.Length).ToString());
// return this; return this;
//} }
public ReplacementBuilder WithRngRegex() public ReplacementBuilder WithRngRegex()
{ {

View File

@ -6,6 +6,7 @@ using NadekoBot.Common.Replacements;
using NadekoBot.Core.Services; using NadekoBot.Core.Services;
using NadekoBot.Core.Services.Database.Models; using NadekoBot.Core.Services.Database.Models;
using NLog; using NLog;
using NadekoBot.Modules.Music.Services;
namespace NadekoBot.Modules.Administration.Services namespace NadekoBot.Modules.Administration.Services
{ {
@ -27,7 +28,7 @@ namespace NadekoBot.Modules.Administration.Services
} }
public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp,
DbService db, IDataCache cache, NadekoBot bot) DbService db, IDataCache cache, NadekoBot bot, MusicService music)
{ {
_client = client; _client = client;
_bcp = bcp; _bcp = bcp;
@ -41,8 +42,7 @@ namespace NadekoBot.Modules.Administration.Services
_rep = new ReplacementBuilder() _rep = new ReplacementBuilder()
.WithClient(client) .WithClient(client)
.WithStats(client) .WithStats(client)
//todo how to add music to replacement builder? .WithMusic(music)
//.WithMusic(music)
.Build(); .Build();
_t = new Timer(async (objState) => _t = new Timer(async (objState) =>

View File

@ -36,6 +36,22 @@ namespace NadekoBot.Modules.Searches
_google = google; _google = google;
} }
//for anonymasen :^)
[NadekoCommand, Usage, Description, Aliases]
public async Task Rip([Remainder]IGuildUser usr)
{
using (var pic = await _service.GetRipPictureAsync(usr.Nickname ?? usr.Username, usr.RealAvatarUrl()))
using (var picStream = pic.ToStream())
{
await Context.Channel.SendFileAsync(
picStream,
"rip.png",
$"Rip {Format.Bold(usr.ToString())} \n\t- " +
Format.Italics(Context.User.ToString()))
.ConfigureAwait(false);
}
}
[NadekoCommand, Usage, Description, Aliases] [NadekoCommand, Usage, Description, Aliases]
[RequireContext(ContextType.Guild)] [RequireContext(ContextType.Guild)]
[RequireUserPermission(GuildPermission.ManageMessages)] [RequireUserPermission(GuildPermission.ManageMessages)]

View File

@ -18,6 +18,11 @@ using Newtonsoft.Json.Linq;
using AngleSharp; using AngleSharp;
using System.Threading; using System.Threading;
using NadekoBot.Modules.Searches.Exceptions; using NadekoBot.Modules.Searches.Exceptions;
using ImageSharp;
using Image = ImageSharp.Image;
using SixLabors.Primitives;
using SixLabors.Fonts;
using NadekoBot.Core.Services.Impl;
namespace NadekoBot.Modules.Searches.Services namespace NadekoBot.Modules.Searches.Services
{ {
@ -29,11 +34,16 @@ namespace NadekoBot.Modules.Searches.Services
private readonly IGoogleApiService _google; private readonly IGoogleApiService _google;
private readonly DbService _db; private readonly DbService _db;
private readonly Logger _log; private readonly Logger _log;
private readonly IImagesService _imgs;
private readonly IDataCache _cache;
private readonly FontProvider _fonts;
private readonly HttpClient http;
public ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>(); public ConcurrentDictionary<ulong, bool> TranslatedChannels { get; } = new ConcurrentDictionary<ulong, bool>();
public ConcurrentDictionary<UserChannelPair, string> UserLanguages { get; } = new ConcurrentDictionary<UserChannelPair, string>(); public ConcurrentDictionary<UserChannelPair, string> UserLanguages { get; } = new ConcurrentDictionary<UserChannelPair, string>();
public readonly string PokemonAbilitiesFile = "data/pokemon/pokemon_abilities7.json"; public readonly string PokemonAbilitiesFile = "data/pokemon/pokemon_abilities7.json";
public readonly string PokemonListFile = "data/pokemon/pokemon_list7.json"; public readonly string PokemonListFile = "data/pokemon/pokemon_list7.json";
public Dictionary<string, SearchPokemon> Pokemons { get; } = new Dictionary<string, SearchPokemon>(); public Dictionary<string, SearchPokemon> Pokemons { get; } = new Dictionary<string, SearchPokemon>();
public Dictionary<string, SearchPokemonAbility> PokemonAbilities { get; } = new Dictionary<string, SearchPokemonAbility>(); public Dictionary<string, SearchPokemonAbility> PokemonAbilities { get; } = new Dictionary<string, SearchPokemonAbility>();
@ -50,7 +60,8 @@ namespace NadekoBot.Modules.Searches.Services
private readonly ConcurrentDictionary<ulong, HashSet<string>> _blacklistedTags = new ConcurrentDictionary<ulong, HashSet<string>>(); private readonly ConcurrentDictionary<ulong, HashSet<string>> _blacklistedTags = new ConcurrentDictionary<ulong, HashSet<string>>();
public SearchesService(DiscordSocketClient client, IGoogleApiService google, public SearchesService(DiscordSocketClient client, IGoogleApiService google,
DbService db, NadekoBot bot) DbService db, NadekoBot bot, IImagesService imgs, IDataCache cache,
FontProvider fonts)
{ {
Http = new HttpClient(); Http = new HttpClient();
Http.AddFakeHeaders(); Http.AddFakeHeaders();
@ -58,6 +69,10 @@ namespace NadekoBot.Modules.Searches.Services
_google = google; _google = google;
_db = db; _db = db;
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_imgs = imgs;
_cache = cache;
_fonts = fonts;
http = new HttpClient();
_blacklistedTags = new ConcurrentDictionary<ulong, HashSet<string>>( _blacklistedTags = new ConcurrentDictionary<ulong, HashSet<string>>(
bot.AllGuildConfigs.ToDictionary( bot.AllGuildConfigs.ToDictionary(
@ -126,6 +141,61 @@ namespace NadekoBot.Modules.Searches.Services
_log.Warn("data/magicitems.json is missing. Magic items are not loaded."); _log.Warn("data/magicitems.json is missing. Magic items are not loaded.");
} }
public async Task<Image<Rgba32>> GetRipPictureAsync(string text, string imgUrl)
{
var (succ, data) = await _cache.TryGetImageDataAsync(imgUrl);
if (!succ)
{
using (var temp = await http.GetAsync(imgUrl, HttpCompletionOption.ResponseHeadersRead))
{
if (temp.Content.Headers.ContentType.MediaType != "image/png"
&& temp.Content.Headers.ContentType.MediaType != "image/jpeg"
&& temp.Content.Headers.ContentType.MediaType != "image/gif")
data = null;
else
{
using (var tempDraw = ImageSharp.Image.Load(await temp.Content.ReadAsStreamAsync()).Resize(69, 70))
{
tempDraw.ApplyRoundedCorners(35);
data = tempDraw.ToStream().ToArray();
}
}
}
await _cache.SetImageDataAsync(imgUrl, data);
}
var bg = ImageSharp.Image.Load(_imgs.Rip.ToArray());
//avatar 82, 139
if (data != null)
{
var avatar = Image.Load(data).Resize(85, 85);
bg.DrawImage(avatar,
default,
new Point(82, 139),
GraphicsOptions.Default);
}
//text 63, 241
bg.DrawText(text,
_fonts.RipNameFont,
Rgba32.Black,
new PointF(25, 225),
new ImageSharp.Drawing.TextGraphicsOptions()
{
HorizontalAlignment = HorizontalAlignment.Center,
WrapTextWidth = 190,
});
//flowa
var flowers = Image.Load(_imgs.FlowerCircle.ToArray());
bg.DrawImage(flowers,
default,
new Point(0, 0),
GraphicsOptions.Default);
return bg;
}
public async Task<string> Translate(string langs, string text = null) public async Task<string> Translate(string langs, string text = null)
{ {
var langarr = langs.ToLowerInvariant().Split('>'); var langarr = langs.ToLowerInvariant().Split('>');
@ -212,7 +282,7 @@ namespace NadekoBot.Modules.Searches.Services
public async Task<(string Text, string BaseUri)> GetRandomJoke() public async Task<(string Text, string BaseUri)> GetRandomJoke()
{ {
var config = Configuration.Default.WithDefaultLoader(); var config = AngleSharp.Configuration.Default.WithDefaultLoader();
var document = await BrowsingContext.New(config).OpenAsync("http://www.goodbadjokes.com/random"); var document = await BrowsingContext.New(config).OpenAsync("http://www.goodbadjokes.com/random");
var html = document.QuerySelector(".post > .joke-content"); var html = document.QuerySelector(".post > .joke-content");

View File

@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Xp.Services
private readonly Logger _log; private readonly Logger _log;
private readonly NadekoStrings _strings; private readonly NadekoStrings _strings;
private readonly IDataCache _cache; private readonly IDataCache _cache;
private readonly FontCollection _fonts = new FontCollection(); private readonly FontProvider _fonts;
public const int XP_REQUIRED_LVL_1 = 36; public const int XP_REQUIRED_LVL_1 = 36;
private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles
@ -59,17 +59,11 @@ namespace NadekoBot.Modules.Xp.Services
private readonly CancellationTokenSource _clearRewardTimerTokenSource; private readonly CancellationTokenSource _clearRewardTimerTokenSource;
private readonly Task _clearRewardTimer; private readonly Task _clearRewardTimer;
private readonly HttpClient http = new HttpClient(); private readonly HttpClient http = new HttpClient();
private FontFamily _usernameFontFamily;
private FontFamily _clubFontFamily;
private Font _levelFont;
private Font _xpFont;
private Font _awardedFont;
private Font _rankFont;
private Font _timeFont;
public XpService(CommandHandler cmd, IBotConfigProvider bc, public XpService(CommandHandler cmd, IBotConfigProvider bc,
NadekoBot bot, IImagesService images, NadekoBot bot, IImagesService images,
DbService db, NadekoStrings strings, IDataCache cache) DbService db, NadekoStrings strings, IDataCache cache,
FontProvider fonts)
{ {
_db = db; _db = db;
_cmd = cmd; _cmd = cmd;
@ -78,6 +72,7 @@ namespace NadekoBot.Modules.Xp.Services
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
_strings = strings; _strings = strings;
_cache = cache; _cache = cache;
_fonts = fonts;
//load settings //load settings
var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null);
@ -105,16 +100,6 @@ namespace NadekoBot.Modules.Xp.Services
allGuildConfigs.Where(x => x.XpSettings.ServerExcluded) allGuildConfigs.Where(x => x.XpSettings.ServerExcluded)
.Select(x => x.GuildId)); .Select(x => x.GuildId));
//todo 60 move to font provider or somethign
_fonts = new FontCollection();
if (Directory.Exists("data/fonts"))
foreach (var file in Directory.GetFiles("data/fonts"))
{
_fonts.Install(file);
}
InitializeFonts();
_cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger; _cmd.OnMessageNoTrigger += _cmd_OnMessageNoTrigger;
_updateXpTimer = new Timer(async _ => _updateXpTimer = new Timer(async _ =>
@ -547,16 +532,6 @@ namespace NadekoBot.Modules.Xp.Services
return GenerateImageAsync(GetUserStats(user)); return GenerateImageAsync(GetUserStats(user));
} }
private void InitializeFonts()
{
_usernameFontFamily = _fonts.Find("Whitney-Bold");
_clubFontFamily = _fonts.Find("Whitney-Bold");
_levelFont = _fonts.Find("Whitney-Bold").CreateFont(45);
_xpFont = _fonts.Find("Whitney-Bold").CreateFont(50);
_awardedFont = _fonts.Find("Whitney-Bold").CreateFont(25);
_rankFont = _fonts.Find("Uni Sans Thin CAPS").CreateFont(30);
_timeFont = _fonts.Find("Whitney-Bold").CreateFont(20);
}
public Task<MemoryStream> GenerateImageAsync(FullUserStats stats) => Task.Run(async () => public Task<MemoryStream> GenerateImageAsync(FullUserStats stats) => Task.Run(async () =>
{ {
@ -564,7 +539,7 @@ namespace NadekoBot.Modules.Xp.Services
{ {
var username = stats.User.ToString(); var username = stats.User.ToString();
var usernameFont = _usernameFontFamily var usernameFont = _fonts.UsernameFontFamily
.CreateFont(username.Length <= 6 .CreateFont(username.Length <= 6
? 50 ? 50
: 50 - username.Length); : 50 - username.Length);
@ -574,17 +549,17 @@ namespace NadekoBot.Modules.Xp.Services
// level // level
img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White, img.DrawText(stats.Global.Level.ToString(), _fonts.LevelFont, Rgba32.White,
new PointF(47, 137)); new PointF(47, 137));
img.DrawText(stats.Guild.Level.ToString(), _levelFont, Rgba32.White, img.DrawText(stats.Guild.Level.ToString(), _fonts.LevelFont, Rgba32.White,
new PointF(47, 285)); new PointF(47, 285));
//club name //club name
var clubName = stats.User.Club?.ToString() ?? "-"; var clubName = stats.User.Club?.ToString() ?? "-";
var clubFont = _clubFontFamily var clubFont = _fonts.ClubFontFamily
.CreateFont(clubName.Length <= 8 .CreateFont(clubName.Length <= 8
? 35 ? 35
: 35 - (clubName.Length / 2)); : 35 - (clubName.Length / 2));
@ -607,7 +582,7 @@ namespace NadekoBot.Modules.Xp.Services
new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235), new PointF(286 + (450 * (global.LevelXp / (float)global.RequiredXp)), 235),
new PointF(286, 235), new PointF(286, 235),
}); });
img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen, img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _fonts.XpFont, brush, pen,
new PointF(430, 130)); new PointF(430, 130));
img.FillPolygon(xpBgBrush, new[] { img.FillPolygon(xpBgBrush, new[] {
@ -616,7 +591,7 @@ namespace NadekoBot.Modules.Xp.Services
new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379), new PointF(247 + (450 * (guild.LevelXp / (float)guild.RequiredXp)), 379),
new PointF(247, 379), new PointF(247, 379),
}); });
img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen, img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _fonts.XpFont, brush, pen,
new PointF(400, 270)); new PointF(400, 270));
if (stats.FullGuildStats.AwardedXp != 0) if (stats.FullGuildStats.AwardedXp != 0)
@ -624,16 +599,16 @@ namespace NadekoBot.Modules.Xp.Services
var sign = stats.FullGuildStats.AwardedXp > 0 var sign = stats.FullGuildStats.AwardedXp > 0
? "+ " ? "+ "
: ""; : "";
img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _awardedFont, brush, pen, img.DrawText($"({sign}{stats.FullGuildStats.AwardedXp})", _fonts.AwardedFont, brush, pen,
new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335)); new PointF(445 - (Math.Max(0, (stats.FullGuildStats.AwardedXp.ToString().Length - 2)) * 5), 335));
} }
//ranking //ranking
img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White, img.DrawText(stats.GlobalRanking.ToString(), _fonts.RankFont, Rgba32.White,
new PointF(148, 170)); new PointF(148, 170));
img.DrawText(stats.GuildRanking.ToString(), _rankFont, Rgba32.White, img.DrawText(stats.GuildRanking.ToString(), _fonts.RankFont, Rgba32.White,
new PointF(148, 317)); new PointF(148, 317));
//time on this level //time on this level
@ -644,10 +619,10 @@ namespace NadekoBot.Modules.Xp.Services
return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m"; return $"{offset.Days}d{offset.Hours}h{offset.Minutes}m";
} }
img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _timeFont, Rgba32.White, img.DrawText(GetTimeSpent(stats.User.LastLevelUp), _fonts.TimeFont, Rgba32.White,
new PointF(50, 197)); new PointF(50, 197));
img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White, img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _fonts.TimeFont, Rgba32.White,
new PointF(50, 344)); new PointF(50, 344));
//avatar //avatar
@ -664,7 +639,7 @@ namespace NadekoBot.Modules.Xp.Services
using (var temp = await http.GetStreamAsync(avatarUrl)) using (var temp = await http.GetStreamAsync(avatarUrl))
using (var tempDraw = Image.Load(temp).Resize(69, 70)) using (var tempDraw = Image.Load(temp).Resize(69, 70))
{ {
ApplyRoundedCorners(tempDraw, 35); tempDraw.ApplyRoundedCorners(35);
data = tempDraw.ToStream().ToArray(); data = tempDraw.ToStream().ToArray();
} }
@ -710,7 +685,7 @@ namespace NadekoBot.Modules.Xp.Services
return; return;
using (var tempDraw = Image.Load(await temp.Content.ReadAsStreamAsync()).Resize(45, 45)) using (var tempDraw = Image.Load(await temp.Content.ReadAsStreamAsync()).Resize(45, 45))
{ {
ApplyRoundedCorners(tempDraw, 22.5f); tempDraw.ApplyRoundedCorners(22.5f);
data = tempDraw.ToStream().ToArray(); data = tempDraw.ToStream().ToArray();
} }
} }
@ -731,40 +706,6 @@ namespace NadekoBot.Modules.Xp.Services
} }
} }
// https://github.com/SixLabors/ImageSharp/tree/master/samples/AvatarWithRoundedCorner
public static void ApplyRoundedCorners(Image<Rgba32> img, float cornerRadius)
{
var corners = BuildCorners(img.Width, img.Height, cornerRadius);
// now we have our corners time to draw them
img.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true)
{
BlenderMode = ImageSharp.PixelFormats.PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background
});
}
public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
// first create a square
var rect = new RectangularePolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
// then cut out of the square a circle so we are left with a corner
var cornerToptLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
// corner is now a corner shape positions top left
//lets make 3 more positioned correctly, we can do that by translating the orgional around the center of the image
var center = new Vector2(imageWidth / 2, imageHeight / 2);
float rightPos = imageWidth - cornerToptLeft.Bounds.Width + 1;
float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1;
// move it across the width of the image - the width of the shape
var cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0);
var cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos);
var cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos);
return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
public Task Unload() public Task Unload()
{ {
_cmd.OnMessageNoTrigger -= _cmd_OnMessageNoTrigger; _cmd.OnMessageNoTrigger -= _cmd_OnMessageNoTrigger;

View File

@ -19,6 +19,9 @@ namespace NadekoBot.Core.Services
ImmutableArray<byte> XpCard { get; } ImmutableArray<byte> XpCard { get; }
ImmutableArray<byte> Rip { get; }
ImmutableArray<byte> FlowerCircle { get; }
void Reload(); void Reload();
} }
} }

View File

@ -0,0 +1,38 @@
using SixLabors.Fonts;
using System.IO;
namespace NadekoBot.Core.Services.Impl
{
public class FontProvider : INService
{
private readonly FontCollection _fonts;
public FontProvider()
{
_fonts = new FontCollection();
if (Directory.Exists("data/fonts"))
foreach (var file in Directory.GetFiles("data/fonts"))
{
_fonts.Install(file);
}
UsernameFontFamily = _fonts.Find("Whitney-Bold");
ClubFontFamily = _fonts.Find("Whitney-Bold");
LevelFont = _fonts.Find("Whitney-Bold").CreateFont(45);
XpFont = _fonts.Find("Whitney-Bold").CreateFont(50);
AwardedFont = _fonts.Find("Whitney-Bold").CreateFont(25);
RankFont = _fonts.Find("Uni Sans Thin CAPS").CreateFont(30);
TimeFont = _fonts.Find("Whitney-Bold").CreateFont(20);
RipNameFont = _fonts.Find("Whitney-Bold").CreateFont(20);
}
public Font LevelFont { get; }
public Font XpFont { get; }
public Font AwardedFont { get; }
public Font RankFont { get; }
public Font TimeFont { get; }
public FontFamily UsernameFontFamily { get; }
public FontFamily ClubFontFamily { get; }
public Font RipNameFont { get; }
}
}

View File

@ -27,6 +27,9 @@ namespace NadekoBot.Core.Services.Impl
private const string _xpCardPath = _basePath + "xp/xp.png"; private const string _xpCardPath = _basePath + "xp/xp.png";
private const string _ripPath = _basePath + "rip/rip.png";
private const string _ripFlowersPath = _basePath + "rip/rose_overlay.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; }
@ -44,6 +47,9 @@ namespace NadekoBot.Core.Services.Impl
public ImmutableArray<byte> XpCard { get; private set; } public ImmutableArray<byte> XpCard { get; private set; }
public ImmutableArray<byte> Rip { get; private set; }
public ImmutableArray<byte> FlowerCircle { get; private set; }
public ImagesService() public ImagesService()
{ {
_log = LogManager.GetCurrentClassLogger(); _log = LogManager.GetCurrentClassLogger();
@ -82,6 +88,9 @@ namespace NadekoBot.Core.Services.Impl
RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray(); RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray();
XpCard = File.ReadAllBytes(_xpCardPath).ToImmutableArray(); XpCard = File.ReadAllBytes(_xpCardPath).ToImmutableArray();
Rip = File.ReadAllBytes(_ripPath).ToImmutableArray();
FlowerCircle = File.ReadAllBytes(_ripFlowersPath).ToImmutableArray();
} }
catch (Exception ex) catch (Exception ex)
{ {

View File

@ -17,11 +17,47 @@ using NadekoBot.Common.Collections;
using SixLabors.Primitives; using SixLabors.Primitives;
using NadekoBot.Common; using NadekoBot.Common;
using NadekoBot.Core.Services; using NadekoBot.Core.Services;
using SixLabors.Shapes;
using System.Numerics;
namespace NadekoBot.Extensions namespace NadekoBot.Extensions
{ {
public static class Extensions public static class Extensions
{ {
// https://github.com/SixLabors/ImageSharp/tree/master/samples/AvatarWithRoundedCorner
public static void ApplyRoundedCorners(this Image<Rgba32> img, float cornerRadius)
{
var corners = BuildCorners(img.Width, img.Height, cornerRadius);
// now we have our corners time to draw them
img.Fill(Rgba32.Transparent, corners, new GraphicsOptions(true)
{
BlenderMode = ImageSharp.PixelFormats.PixelBlenderMode.Src // enforces that any part of this shape that has color is punched out of the background
});
}
public static IPathCollection BuildCorners(int imageWidth, int imageHeight, float cornerRadius)
{
// first create a square
var rect = new RectangularePolygon(-0.5f, -0.5f, cornerRadius, cornerRadius);
// then cut out of the square a circle so we are left with a corner
var cornerToptLeft = rect.Clip(new EllipsePolygon(cornerRadius - 0.5f, cornerRadius - 0.5f, cornerRadius));
// corner is now a corner shape positions top left
//lets make 3 more positioned correctly, we can do that by translating the orgional around the center of the image
var center = new Vector2(imageWidth / 2, imageHeight / 2);
float rightPos = imageWidth - cornerToptLeft.Bounds.Width + 1;
float bottomPos = imageHeight - cornerToptLeft.Bounds.Height + 1;
// move it across the width of the image - the width of the shape
var cornerTopRight = cornerToptLeft.RotateDegree(90).Translate(rightPos, 0);
var cornerBottomLeft = cornerToptLeft.RotateDegree(-90).Translate(0, bottomPos);
var cornerBottomRight = cornerToptLeft.RotateDegree(180).Translate(rightPos, bottomPos);
return new PathCollection(cornerToptLeft, cornerBottomLeft, cornerTopRight, cornerBottomRight);
}
public static string RedisKey(this IBotCredentials bc) public static string RedisKey(this IBotCredentials bc)
{ {
return bc.Token.Substring(0, 10); return bc.Token.Substring(0, 10);

View File

@ -7,7 +7,7 @@
#### Guide #### Guide
- Download and run the [NadekoBot Updater.][Updater] - Download and run the [NadekoBot Updater.][Updater]
- Press **`Install Redis`** then - Press **`Install Redis`** then
- Press **`Install ffmpeg`** and **`Install youtube-dl`** if you want music features. - Press **`Install ffmpeg`** and **`Install youtube-dl`** if you want music features.
***NOTE:** RESTART YOUR PC IF YOU DO.* ***NOTE:** RESTART YOUR PC IF YOU DO.*
- Press **`Update`** and go through the installation wizard. - Press **`Update`** and go through the installation wizard.