private async Task ReadLog(string logLink) { using var typing = Context.Channel.EnterTypingState(); var logMatch = FFLogsUtils.LogLinkToIdRegex.Match(logLink); if (!logMatch.Success) { await ReplyAsync("That doesn't look like a log link!"); return; } var logId = logMatch.Value; var req = FFLogsUtils.BuildLogRequest(logId); var res = (await FFLogsAPI.MakeGraphQLRequest <LogInfo>(req)).Content.Data.ReportInfo; if (res == null) { await ReplyAsync("That log is private; please make it unlisted or public."); return; } var encounters = res.Fights .Where(f => f.Kill != null && f.FriendlyPlayers != null); var originalUsers = res.MasterData.Actors .Where(a => a.Server != null) .ToList(); var members = Context.Guild.Users; var potentialUsers = originalUsers.ToDictionary(a => a.Id, a => a) .Select(kvp => new KeyValuePair <int, PotentialDbUser>(kvp.Key, new PotentialDbUser { Name = kvp.Value.Name, World = kvp.Value.Server, User = Db.Users.FirstOrDefault(u => string.Equals(u.Name, kvp.Value.Name, StringComparison.InvariantCultureIgnoreCase) && string.Equals(u.World, kvp.Value.Server, StringComparison.InvariantCultureIgnoreCase)), })) .Select(async kvp => { var(id, potentialUser) = kvp; await RegisterUser(members, potentialUser); return(new KeyValuePair <int, DiscordXIVUser>(id, potentialUser.User)); }) .ToList(); // We can't cleanly go from a KeyValuePair<int, Task<DiscordXIVUser>> // to a KeyValuePair<int, DiscordXIVUser>, so let's break it up into // multiple queries. var users = (await Task.WhenAll(potentialUsers)) .Where(kvp => kvp.Value != null) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value);; var missedUsers = new List <LogInfo.ReportDataWrapper.ReportData.Report.Master.Actor>(); var addedAny = false; foreach (var encounter in encounters) { var roleName = encounter.Name; if (roleName == "The Queen's Guard") { roleName = "Queen's Guard"; } roleName += " Progression"; var role = Context.Guild.Roles.FirstOrDefault(r => r.Name == roleName); if (role == null) { Log.Error("Role {RoleName} does not exist!", roleName); continue; } var contingentRoles = DelubrumProgressionRoles.GetContingentRoles(role.Id) .Select(r => Context.Guild.GetRole(r)) .ToList(); var killRole = Context.Guild.GetRole(DelubrumProgressionRoles.GetKillRole(role.Name)); foreach (var id in encounter.FriendlyPlayers) { if (!users.ContainsKey(id)) { var actor = originalUsers.Find(a => a.Id == id); if (actor != null) { missedUsers.Add(actor); } continue; } var user = Context.Guild.GetUser(users[id].DiscordId); if (user == null || user.HasRole(806362589134454805)) { continue; } if (killRole.Id == 806362589134454805 && encounter.Kill == true) { addedAny = true; // Remove all contingent roles (this is bodge and should be refactored) foreach (var progRole in contingentRoles) { Log.Information("Checking role {RoleName} on user {User}", progRole.Name, user); if (user.HasRole(progRole)) { await user.RemoveRoleAsync(progRole); Log.Information("Removed role {RoleName} from user {User}", progRole.Name, user); } } // Give everyone the clear role if they cleared DRS Log.Information("Checking role {RoleName} on user {User}", killRole.Name, user); if (!user.HasRole(killRole)) { await user.AddRoleAsync(killRole); Log.Information("Added role {RoleName} to {User}", killRole.Name, user); } } else { // Give all contingent roles as well as the clear role for the fight foreach (var progRole in contingentRoles) { Log.Information("Checking role {RoleName} on user {User}", progRole.Name, user); if (!user.HasRole(progRole)) { addedAny = true; await user.AddRoleAsync(progRole); Log.Information("Added role {RoleName} to user {User}", progRole.Name, user); } } if (encounter.Kill == true) { Log.Information("Checking role {RoleName} on user {User}", killRole.Name, user); if (!user.HasRole(killRole)) { addedAny = true; await user.AddRoleAsync(killRole); Log.Information("Added role {RoleName} to {User}", killRole.Name, user); } } } } } if (addedAny) { await ReplyAsync("Roles added!"); } else { await ReplyAsync("No roles to add."); } if (missedUsers.Any()) { await ReplyAsync($"Missed users: ```{missedUsers.Select(a => $"({a.Server}) {a.Name}").Distinct().Aggregate("", (agg, next) => agg + $"{next}\n") + "```"}\nThey may need to re-register with `~iam`."); } }
public async Task AddDelubrumProgRoleAsync([Remainder] string args) { var isFFLogs = FFLogsUtils.IsLogLink(args); Log.Information($"FFLogs link provided: {isFFLogs}"); if (isFFLogs) { await ReadLog(args); return; } var executor = Context.Guild.GetUser(Context.User.Id); if (!executor.HasRole(DelubrumProgressionRoles.Executor, Context) && !executor.HasRole(579916868035411968, Context) && // or Mentor !executor.GuildPermissions.KickMembers) // or can kick users { Log.Information("User does not have roler role."); var res = await ReplyAsync($"{Context.User.Mention}, you don't have the roler role!"); await Task.Delay(5000); await res.DeleteAsync(); return; } var words = args.Split(' '); var members = words .Where(w => w.StartsWith('<')) .Select(idStr => RegexSearches.NonNumbers.Replace(idStr, "")) .Select(ulong.Parse) .Select(id => Context.Guild.GetUser(id) ?? (IGuildUser)Context.Client.Rest.GetGuildUserAsync(Context.Guild.Id, id).GetAwaiter().GetResult()); var roleName = string.Join(' ', words.Where(w => !w.StartsWith('<'))); roleName = RegexSearches.UnicodeApostrophe.Replace(roleName, "'"); roleName = roleName.Trim(); var role = Context.Guild.Roles.FirstOrDefault(r => string.Equals(r.Name.ToLowerInvariant(), roleName.ToLowerInvariant(), StringComparison.InvariantCultureIgnoreCase)); if (role == null) { Log.Information("Role name invalid."); var res = await ReplyAsync($"{Context.User.Mention}, no role by that name exists! Make sure you spelled it correctly."); await Task.Delay(5000); await res.DeleteAsync(); return; } if (!DelubrumProgressionRoles.Roles.Keys.Contains(role.Id)) { Log.Information("Role key invalid."); return; } var contingentRoles = DelubrumProgressionRoles.GetContingentRoles(role.Id) .Select(Context.Guild.GetRole) .ToList(); await Task.WhenAll(members .Select(m => { try { return(m.AddRolesAsync(contingentRoles.Where(r => !m.MemberHasRole(r, Context)))); } catch (Exception e) { Log.Error(e, "Failed to add roles to user {User}.", m.ToString()); return(Task.CompletedTask); } })); await ReplyAsync("Roles added!"); }