public async Task PopularityAsync(int n, string channelIgnoreTerms, string categoryIgnoreTerms, [Remainder] string exclude) { List <ulong> excludeIds = new List <ulong>(); foreach (string s in exclude.Split(' ')) { if (UInt64.TryParse(s, out ulong u)) { excludeIds.Add(u); } else { await ReplyAsync($"Failed to parse exclusion ID {s} at position {excludeIds.Count + 1}. Please check that it's a valid number!"); return; } } List <string> chanIgnoreStrings = channelIgnoreTerms.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); List <string> catIgnoreStrings = categoryIgnoreTerms.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries).ToList(); IGuild guild = Context.Guild; // don't need to check null as must be called from guild List <KeyValuePair <IGuildChannel, DateTime> > channels = new List <KeyValuePair <IGuildChannel, DateTime> >(); IMessage alertMsg = await ReplyAsync("Sorting channels by oldest last message. This may take a while, please wait..."); foreach (IMessageChannel c in await guild.GetTextChannelsAsync()) { if (excludeIds.Contains(c.Id)) { continue; } if (chanIgnoreStrings.Any(s => c.Name.ToLower().Contains(s.ToLower()))) { continue; // don't check announcement channels as they tend not to be used as often } ulong?category = (c as SocketTextChannel).CategoryId; if (category == null) { continue; // not going to check anything that's not in a category } if (excludeIds.Contains(category.Value)) { continue; } if (catIgnoreStrings.Any(s => (c as SocketTextChannel).Category.Name.ToLower().Contains(s.ToLower()))) { continue; } var msg = (await c.GetMessagesAsync(1).FlattenAsync())?.FirstOrDefault(); DateTime ts = msg != null ? msg.Timestamp.DateTime : c.CreatedAt.DateTime; channels.Add(new KeyValuePair <IGuildChannel, DateTime>(c as IGuildChannel, ts)); } channels.Sort((x, y) => DateTime.Compare(x.Value, y.Value)); EmbedBuilder builder = new EmbedBuilder(); n = n <= 20 ? n : 20; n = n <= channels.Count ? n : channels.Count; for (int i = 0; i < n; i++) { IGuildChannel c = channels[i].Key as IGuildChannel; DateTime dt = channels[i].Value; int numUsers = (await c.GetUsersAsync().FlattenAsync()).Count(); builder.AddField($"{(c as SocketTextChannel).Category.Name}/{c.Name}", $"{(c as SocketTextChannel).Mention}\n" + $"Number of users: {numUsers}.\n" + $"Last message at {dt.ToString()}.\n" + $"Channel created at {c.CreatedAt.DateTime}"); } await alertMsg.DeleteAsync(); await Context.Channel.SendMessageAsync("*Most recent activity of channels in this server:*", false, builder.Build()); }
private static async Task UpdateVoiceChannels(SocketUser su, SocketVoiceState oldState, SocketVoiceState newState) { if (newState.VoiceChannel == oldState.VoiceChannel) { return; // The event can be triggered without changing channels } // Handle joining a channel if (newState.VoiceChannel != null && Utilities.VoiceWhitelist.check(newState.VoiceChannel.Guild.Id, newState.VoiceChannel.Name)) // Check to see if a channel was joined and that channel is not in the blacklist { IGuildChannel vc = newState.VoiceChannel; // var vct = Utilities.Voice.ProcessName(vc.Name); Console.WriteLine($"{su.Username}#{su.Discriminator} has joined {vc.Name}({vc.Id})"); var users = (await vc.GetUsersAsync().FlattenAsync()).ToList(); if (users.Count == 1) // If there is only one person in the group, it was previously empty, and another slot needs opened up { var pos = 0; var number = 1; var vcs = await vc.Guild.GetVoiceChannelsAsync(); // Get a list of voice channels var vcso = vcs.OrderBy(item => item.Position); // Order the list of voice channels foreach (var channel in vcso) // Loop over every channel { var chnl = Utilities.Voice.ProcessName(channel.Name); // Get the name and number from the channel if (chnl.name != vct.name) { continue; // Check to see if the channel is of the same type } pos = Math.Max(channel.Position, pos); // If the channel is lower, save the new position if (chnl.number != number) { // Is the channel number correct await((SocketVoiceChannel)channel).ModifyAsync(x => { // ReSharper disable once AccessToModifiedClosure x.Name = chnl.name + " " + number; // Update the channel number }); } number++; // Increment the number that the channel is supposed to be } var rcpe = (await vc.Guild.GetVoiceChannelsAsync()).Select(channel => new ReorderChannelProperties(channel.Id, channel.Position + (channel.Position > pos ? 1 : 0))).ToList(); // Enumerable to store the new channel order var nvc = await vc.Guild.CreateVoiceChannelAsync(vct.name + " " + number); // Create the channel Console.WriteLine($"Created channel {nvc.Name}({nvc.Id})"); await nvc.ModifyAsync(x => { x.CategoryId = ((INestedChannel)vc).CategoryId; x.Position = pos + 1; // Set the position of the channel }); rcpe.Add(new ReorderChannelProperties(nvc.GuildId, pos + 1)); // Add the channel to the list of channels to reorder await vc.Guild.ReorderChannelsAsync(rcpe); // Reorder the channels } } // Handle leaving a channel if (oldState.VoiceChannel != null && Utilities.VoiceWhitelist.check(oldState.VoiceChannel.Guild.Id, oldState.VoiceChannel.Name)) { IGuildChannel vc = oldState.VoiceChannel; var vct = Utilities.Voice.ProcessName(vc.Name); Console.WriteLine($"{su.Username}#{su.Discriminator} has left {vc.Name}({vc.Id})"); var users = (await vc.GetUsersAsync().FlattenAsync()).ToList(); if (!users.Any()) // If there are no users in the channel { Console.WriteLine($"Removing empty channel {vc.Name}({vc.Id})"); await vc.DeleteAsync(); // Delete it var number = 1; var vcs = await vc.Guild.GetVoiceChannelsAsync(); var vcso = vcs.OrderBy((item) => item.Position); // This functions almost identically to the number adjustment in the join foreach (var channel in vcso) { var chnl = Utilities.Voice.ProcessName(channel.Name); if (chnl.name != vct.name) { continue; } if (chnl.number == vct.number) { continue; // Because the deleted channel is still in the list, skip it } if (chnl.number != number) { await((SocketVoiceChannel)channel).ModifyAsync(x => { // ReSharper disable once AccessToModifiedClosure x.Name = chnl.name + " " + number; }); } number++; } } } }