Added .rip command again :^)
This commit is contained in:
		| @@ -6,6 +6,8 @@ using Discord; | ||||
| using Discord.Commands; | ||||
| using Discord.WebSocket; | ||||
| using NadekoBot.Extensions; | ||||
| using NadekoBot.Modules.Music.Services; | ||||
| using NadekoBot.Modules.Administration.Services; | ||||
|  | ||||
| namespace NadekoBot.Common.Replacements | ||||
| { | ||||
| @@ -44,19 +46,19 @@ namespace NadekoBot.Common.Replacements | ||||
|  | ||||
|             _reps.TryAdd("%sid%", () => g == null ? "DM" : g.Id.ToString()); | ||||
|             _reps.TryAdd("%server%", () => g == null ? "DM" : g.Name); | ||||
|             //_reps.TryAdd("%server_time%", () => | ||||
|             //{ | ||||
|             //    TimeZoneInfo to = TimeZoneInfo.Local; | ||||
|             //    if (g != null) | ||||
|             //    { | ||||
|             //        if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz)) | ||||
|             //            to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local; | ||||
|             //    } | ||||
|             _reps.TryAdd("%server_time%", () => | ||||
|             { | ||||
|                 TimeZoneInfo to = TimeZoneInfo.Local; | ||||
|                 if (g != null) | ||||
|                 { | ||||
|                     if (GuildTimezoneService.AllServices.TryGetValue(client.CurrentUser.Id, out var tz)) | ||||
|                         to = tz.GetTimeZoneOrDefault(g.Id) ?? TimeZoneInfo.Local; | ||||
|                 } | ||||
|  | ||||
|             //    return TimeZoneInfo.ConvertTime(DateTime.UtcNow, | ||||
|             //        TimeZoneInfo.Utc, | ||||
|             //        to).ToString("HH:mm ") + to.StandardName.GetInitials(); | ||||
|             //}); | ||||
|                 return TimeZoneInfo.ConvertTime(DateTime.UtcNow, | ||||
|                     TimeZoneInfo.Utc, | ||||
|                     to).ToString("HH:mm ") + to.StandardName.GetInitials(); | ||||
|             }); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
| @@ -86,26 +88,26 @@ namespace NadekoBot.Common.Replacements | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         //public ReplacementBuilder WithMusic(MusicService ms) | ||||
|         //{ | ||||
|         //    _reps.TryAdd("%playing%", () => | ||||
|         //    { | ||||
|         //        var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.Current.Current != null); | ||||
|         //        if (cnt != 1) return cnt.ToString(); | ||||
|         //        try | ||||
|         //        { | ||||
|         //            var mp = ms.MusicPlayers.FirstOrDefault(); | ||||
|         //            var title =  mp.Value?.Current.Current?.Title; | ||||
|         //            return title ?? "No songs"; | ||||
|         //        } | ||||
|         //        catch | ||||
|         //        { | ||||
|         //            return "error"; | ||||
|         //        } | ||||
|         //    }); | ||||
|         //    _reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.QueueArray().Songs.Length).ToString()); | ||||
|         //    return this; | ||||
|         //} | ||||
|         public ReplacementBuilder WithMusic(MusicService ms) | ||||
|         { | ||||
|             _reps.TryAdd("%playing%", () => | ||||
|             { | ||||
|                 var cnt = ms.MusicPlayers.Count(kvp => kvp.Value.Current.Current != null); | ||||
|                 if (cnt != 1) return cnt.ToString(); | ||||
|                 try | ||||
|                 { | ||||
|                     var mp = ms.MusicPlayers.FirstOrDefault(); | ||||
|                     var title = mp.Value?.Current.Current?.Title; | ||||
|                     return title ?? "No songs"; | ||||
|                 } | ||||
|                 catch | ||||
|                 { | ||||
|                     return "error"; | ||||
|                 } | ||||
|             }); | ||||
|             _reps.TryAdd("%queued%", () => ms.MusicPlayers.Sum(kvp => kvp.Value.QueueArray().Songs.Length).ToString()); | ||||
|             return this; | ||||
|         } | ||||
|  | ||||
|         public ReplacementBuilder WithRngRegex() | ||||
|         { | ||||
|   | ||||
| @@ -6,6 +6,7 @@ using NadekoBot.Common.Replacements; | ||||
| using NadekoBot.Core.Services; | ||||
| using NadekoBot.Core.Services.Database.Models; | ||||
| using NLog; | ||||
| using NadekoBot.Modules.Music.Services; | ||||
|  | ||||
| namespace NadekoBot.Modules.Administration.Services | ||||
| { | ||||
| @@ -27,7 +28,7 @@ namespace NadekoBot.Modules.Administration.Services | ||||
|         } | ||||
|  | ||||
|         public PlayingRotateService(DiscordSocketClient client, IBotConfigProvider bcp, | ||||
|             DbService db, IDataCache cache, NadekoBot bot) | ||||
|             DbService db, IDataCache cache, NadekoBot bot, MusicService music) | ||||
|         { | ||||
|             _client = client; | ||||
|             _bcp = bcp; | ||||
| @@ -41,8 +42,7 @@ namespace NadekoBot.Modules.Administration.Services | ||||
|                 _rep = new ReplacementBuilder() | ||||
|                     .WithClient(client) | ||||
|                     .WithStats(client) | ||||
|                     //todo how to add music to replacement builder? | ||||
|                     //.WithMusic(music) | ||||
|                     .WithMusic(music) | ||||
|                     .Build(); | ||||
|  | ||||
|                 _t = new Timer(async (objState) => | ||||
|   | ||||
| @@ -36,6 +36,22 @@ namespace NadekoBot.Modules.Searches | ||||
|             _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] | ||||
|         [RequireContext(ContextType.Guild)] | ||||
|         [RequireUserPermission(GuildPermission.ManageMessages)] | ||||
|   | ||||
| @@ -18,6 +18,11 @@ using Newtonsoft.Json.Linq; | ||||
| using AngleSharp; | ||||
| using System.Threading; | ||||
| 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 | ||||
| { | ||||
| @@ -29,11 +34,16 @@ namespace NadekoBot.Modules.Searches.Services | ||||
|         private readonly IGoogleApiService _google; | ||||
|         private readonly DbService _db; | ||||
|         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<UserChannelPair, string> UserLanguages { get; } = new ConcurrentDictionary<UserChannelPair, string>(); | ||||
|          | ||||
|         public readonly string PokemonAbilitiesFile = "data/pokemon/pokemon_abilities7.json"; | ||||
|  | ||||
|         public readonly string PokemonListFile = "data/pokemon/pokemon_list7.json"; | ||||
|         public Dictionary<string, SearchPokemon> Pokemons { get; } = new Dictionary<string, SearchPokemon>(); | ||||
|         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>>(); | ||||
|  | ||||
|         public SearchesService(DiscordSocketClient client, IGoogleApiService google,  | ||||
|             DbService db, NadekoBot bot) | ||||
|             DbService db, NadekoBot bot, IImagesService imgs, IDataCache cache, | ||||
|             FontProvider fonts) | ||||
|         { | ||||
|             Http = new HttpClient(); | ||||
|             Http.AddFakeHeaders(); | ||||
| @@ -58,6 +69,10 @@ namespace NadekoBot.Modules.Searches.Services | ||||
|             _google = google; | ||||
|             _db = db; | ||||
|             _log = LogManager.GetCurrentClassLogger(); | ||||
|             _imgs = imgs; | ||||
|             _cache = cache; | ||||
|             _fonts = fonts; | ||||
|             http = new HttpClient(); | ||||
|  | ||||
|             _blacklistedTags = new ConcurrentDictionary<ulong, HashSet<string>>( | ||||
|                 bot.AllGuildConfigs.ToDictionary( | ||||
| @@ -126,6 +141,61 @@ namespace NadekoBot.Modules.Searches.Services | ||||
|                 _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) | ||||
|         { | ||||
|             var langarr = langs.ToLowerInvariant().Split('>'); | ||||
| @@ -212,7 +282,7 @@ namespace NadekoBot.Modules.Searches.Services | ||||
|  | ||||
|         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 html = document.QuerySelector(".post > .joke-content"); | ||||
|   | ||||
| @@ -37,7 +37,7 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|         private readonly Logger _log; | ||||
|         private readonly NadekoStrings _strings; | ||||
|         private readonly IDataCache _cache; | ||||
|         private readonly FontCollection _fonts = new FontCollection(); | ||||
|         private readonly FontProvider _fonts; | ||||
|         public const int XP_REQUIRED_LVL_1 = 36; | ||||
|  | ||||
|         private readonly ConcurrentDictionary<ulong, ConcurrentHashSet<ulong>> _excludedRoles | ||||
| @@ -59,17 +59,11 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|         private readonly CancellationTokenSource _clearRewardTimerTokenSource; | ||||
|         private readonly Task _clearRewardTimer; | ||||
|         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, | ||||
|             NadekoBot bot, IImagesService images, | ||||
|             DbService db, NadekoStrings strings, IDataCache cache) | ||||
|             DbService db, NadekoStrings strings, IDataCache cache, | ||||
|             FontProvider fonts) | ||||
|         { | ||||
|             _db = db; | ||||
|             _cmd = cmd; | ||||
| @@ -78,6 +72,7 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|             _log = LogManager.GetCurrentClassLogger(); | ||||
|             _strings = strings; | ||||
|             _cache = cache; | ||||
|             _fonts = fonts; | ||||
|  | ||||
|             //load settings | ||||
|             var allGuildConfigs = bot.AllGuildConfigs.Where(x => x.XpSettings != null); | ||||
| @@ -105,16 +100,6 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|                 allGuildConfigs.Where(x => x.XpSettings.ServerExcluded) | ||||
|                                .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; | ||||
|  | ||||
|             _updateXpTimer = new Timer(async _ => | ||||
| @@ -547,16 +532,6 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|             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 () => | ||||
|         { | ||||
| @@ -564,7 +539,7 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|             { | ||||
|  | ||||
|                 var username = stats.User.ToString(); | ||||
|                 var usernameFont = _usernameFontFamily | ||||
|                 var usernameFont = _fonts.UsernameFontFamily | ||||
|                     .CreateFont(username.Length <= 6 | ||||
|                         ? 50 | ||||
|                         : 50 - username.Length); | ||||
| @@ -574,17 +549,17 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|  | ||||
|                 // level | ||||
|  | ||||
|                 img.DrawText(stats.Global.Level.ToString(), _levelFont, Rgba32.White, | ||||
|                 img.DrawText(stats.Global.Level.ToString(), _fonts.LevelFont, Rgba32.White, | ||||
|                     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)); | ||||
|  | ||||
|                 //club name | ||||
|  | ||||
|                 var clubName = stats.User.Club?.ToString() ?? "-"; | ||||
|  | ||||
|                 var clubFont = _clubFontFamily | ||||
|                 var clubFont = _fonts.ClubFontFamily | ||||
|                     .CreateFont(clubName.Length <= 8 | ||||
|                         ? 35 | ||||
|                         : 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, 235), | ||||
|                 }); | ||||
|                 img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _xpFont, brush, pen, | ||||
|                 img.DrawText($"{global.LevelXp}/{global.RequiredXp}", _fonts.XpFont, brush, pen, | ||||
|                     new PointF(430, 130)); | ||||
|  | ||||
|                 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, 379), | ||||
|                 }); | ||||
|                 img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _xpFont, brush, pen, | ||||
|                 img.DrawText($"{guild.LevelXp}/{guild.RequiredXp}", _fonts.XpFont, brush, pen, | ||||
|                     new PointF(400, 270)); | ||||
|  | ||||
|                 if (stats.FullGuildStats.AwardedXp != 0) | ||||
| @@ -624,16 +599,16 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|                     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)); | ||||
|                 } | ||||
|  | ||||
|                 //ranking | ||||
|  | ||||
|                 img.DrawText(stats.GlobalRanking.ToString(), _rankFont, Rgba32.White, | ||||
|                 img.DrawText(stats.GlobalRanking.ToString(), _fonts.RankFont, Rgba32.White, | ||||
|                     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)); | ||||
|  | ||||
|                 //time on this level | ||||
| @@ -644,10 +619,10 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|                     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)); | ||||
|  | ||||
|                 img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _timeFont, Rgba32.White, | ||||
|                 img.DrawText(GetTimeSpent(stats.FullGuildStats.LastLevelUp), _fonts.TimeFont, Rgba32.White, | ||||
|                     new PointF(50, 344)); | ||||
|  | ||||
|                 //avatar | ||||
| @@ -664,7 +639,7 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|                             using (var temp = await http.GetStreamAsync(avatarUrl)) | ||||
|                             using (var tempDraw = Image.Load(temp).Resize(69, 70)) | ||||
|                             { | ||||
|                                 ApplyRoundedCorners(tempDraw, 35); | ||||
|                                 tempDraw.ApplyRoundedCorners(35); | ||||
|                                 data = tempDraw.ToStream().ToArray(); | ||||
|                             } | ||||
|  | ||||
| @@ -710,7 +685,7 @@ namespace NadekoBot.Modules.Xp.Services | ||||
|                                 return; | ||||
|                             using (var tempDraw = Image.Load(await temp.Content.ReadAsStreamAsync()).Resize(45, 45)) | ||||
|                             { | ||||
|                                 ApplyRoundedCorners(tempDraw, 22.5f); | ||||
|                                 tempDraw.ApplyRoundedCorners(22.5f); | ||||
|                                 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() | ||||
|         { | ||||
|             _cmd.OnMessageNoTrigger -= _cmd_OnMessageNoTrigger; | ||||
|   | ||||
| @@ -19,6 +19,9 @@ namespace NadekoBot.Core.Services | ||||
|  | ||||
|         ImmutableArray<byte> XpCard { get; } | ||||
|  | ||||
|         ImmutableArray<byte> Rip { get; } | ||||
|         ImmutableArray<byte> FlowerCircle { get; } | ||||
|  | ||||
|         void Reload(); | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										38
									
								
								NadekoBot.Core/Services/Impl/FontProvider.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								NadekoBot.Core/Services/Impl/FontProvider.cs
									
									
									
									
									
										Normal 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; } | ||||
|     } | ||||
| } | ||||
| @@ -27,6 +27,9 @@ namespace NadekoBot.Core.Services.Impl | ||||
|  | ||||
|         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> Tails { get; private set; } | ||||
| @@ -44,6 +47,9 @@ namespace NadekoBot.Core.Services.Impl | ||||
|  | ||||
|         public ImmutableArray<byte> XpCard { get; private set; } | ||||
|  | ||||
|         public ImmutableArray<byte> Rip { get; private set; } | ||||
|         public ImmutableArray<byte> FlowerCircle { get; private set; } | ||||
|  | ||||
|         public ImagesService() | ||||
|         { | ||||
|             _log = LogManager.GetCurrentClassLogger(); | ||||
| @@ -82,6 +88,9 @@ namespace NadekoBot.Core.Services.Impl | ||||
|                 RategirlDot = File.ReadAllBytes(_rategirlDot).ToImmutableArray(); | ||||
|  | ||||
|                 XpCard = File.ReadAllBytes(_xpCardPath).ToImmutableArray(); | ||||
|  | ||||
|                 Rip = File.ReadAllBytes(_ripPath).ToImmutableArray(); | ||||
|                 FlowerCircle = File.ReadAllBytes(_ripFlowersPath).ToImmutableArray(); | ||||
|             } | ||||
|             catch (Exception ex) | ||||
|             { | ||||
|   | ||||
| @@ -17,11 +17,47 @@ using NadekoBot.Common.Collections; | ||||
| using SixLabors.Primitives; | ||||
| using NadekoBot.Common; | ||||
| using NadekoBot.Core.Services; | ||||
| using SixLabors.Shapes; | ||||
| using System.Numerics; | ||||
|  | ||||
| namespace NadekoBot.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) | ||||
|         { | ||||
|             return bc.Token.Substring(0, 10); | ||||
|   | ||||
| @@ -7,7 +7,7 @@ | ||||
|  | ||||
| #### Guide  | ||||
| - 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.   | ||||
| ***NOTE:** RESTART YOUR PC IF YOU DO.* | ||||
| - Press **`Update`** and go through the installation wizard.			 | ||||
|   | ||||
		Reference in New Issue
	
	Block a user