public async Task ModColorAdd(CommandContext context, string name, string hex) { if (CurrentSettings.ApprovedColors.ContainsKey(name)) { await context.RespondAsync($"That name '{name}' is already in the list, {context.User.Mention}!"); return; } if (!ColorAnalyzer.IsValid(hex)) { await context.RespondAsync($"That hex '{hex}' isn't a valid code, {context.User.Mention}! Should be in the format `#RRGGBB`."); return; } if (CurrentSettings.ApprovedColors.Values.Contains(hex)) { await context.RespondAsync($"That hex '{hex}' is already in the list, {context.User.Mention}!"); return; } CurrentSettings.ApprovedColors.Add(name, hex); CurrentSettings.StoreSettings(); await context.RespondAsync($"Adding `{hex}` to the approved list as '{name}', {context.User.Mention}! You might want to ask ketura to update the preview image."); }
public async Task TestColor(CommandContext context, string colorcode, bool american = true) { string color = american ? "color" : "colour"; if (String.IsNullOrWhiteSpace(colorcode)) { var embed = new DiscordEmbedBuilder() { Color = new DiscordColor("#FF0000") }; embed.AddField($"Usage", $"`/{color}test #RRGGBB`. If you don't provide a hex {color} code, this message will show."); embed.AddField($"Summary", $"Dark background is `#2C2F33`, and light background is `#FFFFFF`. Chosen {color} roles must have a contrast ratio of at least {ColorAnalyzer.MinimumDarkContrast} : 1 on the dark mode background, and at least {ColorAnalyzer.MinimumLightContrast} : 1 on the light."); embed.AddField($"Contrast", $@" It's very easy to pick a {color} that isn't readable on one or the other of the two themes that Discord provides. To help keep our eyes from melting any more than they already are from looking at discord 12 hours a day, this bot will enforce contrast standards when selecting {color} roles. Official guidelines suggest a ratio of 4.5 : 1 for text : background, but in our experience this is overkill for usernames. We expect names to have at least a {ColorAnalyzer.MinimumDarkContrast} : 1 ratio on the dark mode background, and at least {ColorAnalyzer.MinimumLightContrast} : 1 on the (second-hand citizen) light mode background. If you're having trouble finding a {color} that meets this bot's standards, try using the following online utility to search for suitable colors: https://webaim.org/resources/contrastchecker/ ."); embed.AddField($"Further Reading", $"See this link for more details on contrast ratios: https://www.boia.org/blog/how-contrast-ratio-pertains-to-website-accessibility"); await context.RespondAsync($"I don't see a {color}, {context.User.Mention}! Here is some more information on how to use `/{color}test`:", embed : embed.Build()); return; } Color parsedColor = new Color(); try { parsedColor = ColorAnalyzer.FromHex(colorcode); var result = ColorAnalyzer.AnalyzeColor(parsedColor); string message = ""; if (result.Passes) { message = $":D That {color} would work, {context.User.Mention}! It has a dark theme contrast of {result.DarkRatio}, and a light theme ratio of {result.LightRatio}."; } else { message = $"D: Hmm, that {color} won't work, {context.User.Mention}! It has a dark theme contrast of {result.DarkRatio} (needs to be >= {ColorAnalyzer.MinimumDarkContrast}), and a light theme ratio of {result.LightRatio} (needs to be >= {ColorAnalyzer.MinimumLightContrast})."; } await context.RespondAsync(message); } catch { await context.RespondAsync($"I'm sorry {context.User.Mention}, but I can't parse '`{colorcode}`' as a valid color! It should be a hex code in the format `#RRGGBB`."); return; } }
public async Task ModColorAnalyze(CommandContext context) { var colorRoles = context.Guild.Roles.Values.Where(x => x.Name.StartsWith("#")).ToDictionary(x => x.Id, y => y); var colorResults = new Dictionary <bool, List <ulong> >(); colorResults[false] = new List <ulong>(); colorResults[true] = new List <ulong>(); foreach (var pair in colorRoles) { var dColor = pair.Value.Color; var color = Color.FromArgb(dColor.R, dColor.G, dColor.B); var result = ColorAnalyzer.AnalyzeColor(color); colorResults[result.Passes].Add(pair.Value.Id); } var embed = new DiscordEmbedBuilder() { Color = new DiscordColor("#FF0000") }; List <string> passed = colorResults[true].Select(x => $"<@&{x}>").ToList(); List <string> failed = colorResults[false].Select(x => $"<@&{x}>").ToList(); if (passed.Any()) { embed.AddField($"Meets Contrast Requirements", String.Join(',', passed)); } if (failed.Any()) { embed.AddField($"Does Not Meet Contrast Requirements", String.Join(',', failed)); } if (!passed.Any() && !failed.Any()) { await context.RespondAsync($"Looks like there's no roles for me to look at, {context.User.Mention}!"); } await context.RespondAsync($"Analysis results of existing roles, {context.User.Mention}:", embed : embed.Build()); }
public async Task Color(CommandContext context, string colorname, bool american = true) { string color = american ? "color" : "colour"; if (String.IsNullOrWhiteSpace(colorname)) { await ColorError(context, american); return; } colorname = colorname.ToLower(); bool foundColor = false; DiscordColor newColor = new DiscordColor(); if (colorname == "rainbow") { int rand = new Random((int)DateTime.Now.Ticks).Next(0, CurrentSettings.ApprovedColors.Count()); colorname = CurrentSettings.ApprovedColors.Keys.ElementAt(rand); newColor = new DiscordColor(CurrentSettings.ApprovedColors[colorname]); foundColor = true; } else if (colorname == "random") { var customRoles = ColorRegistry.GetCustomColorRoles(context.Guild); int rand = new Random((int)DateTime.Now.Ticks).Next(0, customRoles.Count()); colorname = customRoles[rand].Name; foundColor = true; } else if (CurrentSettings.ApprovedColors.ContainsKey(colorname.ToLower())) { colorname = colorname.ToLower(); newColor = new DiscordColor(CurrentSettings.ApprovedColors[colorname]); foundColor = true; } else { AnalysisResult result = new AnalysisResult(); try { result = ColorAnalyzer.AnalyzeColor(ColorAnalyzer.FromHex(colorname)); if (result.Passes) { foundColor = true; newColor = new DiscordColor(colorname); } else { string message = $"D: Hmm, that {color} won't work, {context.User.Mention}! It has a dark theme contrast of {result.DarkRatio} (needs to be >= {ColorAnalyzer.MinimumDarkContrast}), and a light theme ratio of {result.LightRatio} (needs to be >= {ColorAnalyzer.MinimumLightContrast})."; await context.RespondAsync(message); return; } } catch { await ColorError(context, american); return; } } if (!foundColor) { await ColorError(context, american); return; } await RemoveColorRolesFromUser(context); var roles = context.Guild.Roles; if (CurrentSettings.ApprovedColors.ContainsKey(colorname) && roles.Values.Any(x => x.Name.ToLower().Contains(colorname))) { var newrole = roles.Values.Where(x => x.Name.Contains(colorname)).First(); await context.Member.GrantRoleAsync(newrole, "Added by Iris bot upon user's request."); } else if (roles.Values.Any(x => x.Name.ToLower().Contains(colorname))) { var newrole = roles.Values.Where(x => x.Name.ToLower().Contains(colorname)).First(); await context.Member.GrantRoleAsync(newrole, "Added by Iris bot upon user's request."); } else { var newrole = await ColorRegistry.CreateColorRole(context, newColor, colorname); await context.Member.GrantRoleAsync(newrole, "Added by Iris bot upon user's request."); } await context.RespondAsync($"One paint job coming right up, {context.User.Mention}!"); await ColorCommands.PurgeRoles(context); }