public override async Task BuildEmbedsAsync(List <Embed> embeds, IUserMessage msg, SocketReaction reaction) { foreach (Match match in this.Matches(msg.Content)) { ulong guildId = ulong.Parse(match.Groups[1].Value); ulong channelId = ulong.Parse(match.Groups[2].Value); ulong msgId = ulong.Parse(match.Groups[3].Value); SocketGuild guild = this.DiscordClient.GetGuild(guildId); SocketTextChannel textChan = guild?.GetTextChannel(channelId); if (textChan == null) { continue; } IMessage quotedMsg = await textChan.GetMessageAsync(msgId); if (quotedMsg == null) { continue; } EmbedBuilder builder = new EmbedBuilder(); builder .WithAuthorNickname(quotedMsg) .WithLimitedDescription(string.IsNullOrWhiteSpace(quotedMsg.Content) ? "Empty message." : quotedMsg.Content) .WithTimestamp(quotedMsg.Timestamp) .WithField("Quoted by", $"{reaction.User.Value.Mention} from [**#{quotedMsg.Channel.Name}**]({match.Value})", false); embeds.Add(builder.Build()); } }
public async Task RemoveServerAsync(IPEndPoint endPoint, ulong guildID) { GameServer serverToRemove = (await dbContext.GameServers.AsQueryable().ToListAsync().ConfigureAwait(false)).FirstOrDefault(x => x.ServerIP.Address.ToString() == endPoint.Address.ToString() && x.ServerIP.Port == endPoint.Port && x.GuildID == guildID); if (serverToRemove == null) { throw new ArgumentException("The specified server does not exist"); } if (serverToRemove.MessageID != null) { try { SocketGuild guild = discordClient.GetGuild(serverToRemove.GuildID); ITextChannel channel = guild?.GetTextChannel(serverToRemove.ChannelID); if (await(channel?.GetMessageAsync(serverToRemove.MessageID.Value)).ConfigureAwait(false) is Discord.Rest.RestUserMessage msg) { await msg.DeleteAsync().ConfigureAwait(false); } } catch (Exception e) { logger.LogError(e, $"Error trying to remove message for game server {endPoint.Address}"); } } _ = dbContext.GameServers.Remove(serverToRemove); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); }
private static async Task CheckRuns(SocketGuild guild, ulong channelId, int minutesBefore, Func <SocketGuildUser, IMessage, IEmbed, Task> onMatch, CancellationToken token) { var channel = guild?.GetTextChannel(channelId); if (channel == null) { await Task.Delay(3000, token); return; } await foreach (var page in channel.GetMessagesAsync().WithCancellation(token)) { foreach (var message in page) { var embed = message.Embeds.FirstOrDefault(e => e.Type == EmbedType.Rich); var nullableTimestamp = embed?.Timestamp; if (!nullableTimestamp.HasValue) { continue; } var timestamp = nullableTimestamp.Value; // ReSharper disable once InvertIf if (timestamp.AddMinutes(-minutesBefore) <= DateTimeOffset.Now && timestamp.AddMinutes(-minutesBefore + 4.95) > DateTimeOffset.Now && embed.Author.HasValue) { Log.Information("Run matched!"); var host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); if (host == null) { host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); } var messageReferenceCopy = message; try { await onMatch(host, messageReferenceCopy, embed); } catch (Exception e) { Log.Error(e, "error: uncaught exception in onMatch"); } } } } }
private async Task CheckRuns(SocketGuild guild, ulong channelId, double queueTimeSeconds, Func <SocketGuildUser, IMessage, IEmbed, Task> onMatch, CancellationToken token) { var channel = guild?.GetTextChannel(channelId); if (channel == null) { await Task.Delay(3000, token); return; } await foreach (var page in channel.GetMessagesAsync().WithCancellation(token)) { foreach (var message in page) { var embed = message.Embeds.FirstOrDefault(e => e.Type == EmbedType.Rich); var nullableTimestamp = embed?.Timestamp; if (!nullableTimestamp.HasValue) { continue; } var timestamp = nullableTimestamp.Value; // Remove expired posts if (timestamp.AddMinutes(60) < DateTimeOffset.Now) { await message.DeleteAsync(); continue; } #if DEBUG if (queueTimeSeconds > 0 && timestamp.AddSeconds(queueTimeSeconds) <= DateTimeOffset.Now && embed.Author.HasValue) { var eventId = ulong.Parse(embed.Footer?.Text ?? "0"); var toNotify = _db.EventReactions .Where(er => er.EventId == eventId) .Where(er => !er.QueueOpenNotified); await foreach (var er in toNotify.WithCancellation(token)) { var member = guild.GetUser(er.UserId); _ = member.SendMessageAsync($"The event you signed up for notifications on `(ID: {eventId})` is now open for queuing.\n" + "If the run host has declared that they are pulling from the queue, you can join the queue by " + "clicking on the appropriate role reaction on the event post."); er.QueueOpenNotified = true; await _db.UpdateEventReaction(er); } } #endif // ReSharper disable once InvertIf if (timestamp.AddMinutes(-30) <= DateTimeOffset.Now && embed.Author.HasValue) { Log.Information("Run matched!"); var host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); if (host == null) { await guild.DownloadUsersAsync(); host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); } var messageReferenceCopy = message; try { await onMatch(host, messageReferenceCopy, embed); } catch (Exception e) { Log.Error(e, "error: uncaught exception in onMatch"); } } } } }
private async Task GetFeedUpdateAsync(Models.Feed guildFeed, bool getLatest = false) { SocketGuild guild = discordClient.GetGuild(guildFeed.GuildID); SocketTextChannel channel = guild?.GetTextChannel(guildFeed.ChannelID); if (guild == null || channel == null || guildFeed.URL.IsEmpty()) { return; } Feed feed; try { feed = await FeedReader.ReadAsync(guildFeed.URL).ConfigureAwait(false); } catch (Exception ex) { logger.LogWarning(ex, $"Error getting feeds for {guildFeed.URL} in {guild.Name}:{channel.Name}"); return; } if (feed == null || feed.Items == null || feed.Items.Count < 1) { return; } DateTime lastUpdateUTC = guildFeed.LastUpdate ?? DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(updateIntervallMinutes)); IEnumerable <FeedItem> allFeeds = feed?.Items?.Where(x => x.PublishingDate.HasValue); List <FeedItem> updatedFeeds = allFeeds?.Where(x => x.PublishingDate.Value.ToUniversalTime() > lastUpdateUTC) .OrderBy(x => x.PublishingDate) .ToList(); if (updatedFeeds != null && updatedFeeds.Count == 0 && getLatest) { updatedFeeds = allFeeds.Take(1).ToList(); } if (updatedFeeds != null && updatedFeeds.Count > 0) { var builder = new EmbedBuilder(); _ = builder.WithColor(new Color(21, 26, 35)); if (!feed.ImageUrl.IsEmpty()) { _ = builder.WithImageUrl(feed.ImageUrl); } _ = builder.WithTitle($"New update{(updatedFeeds.Count > 1 ? "s" : "")} for \"{guildFeed.Name}".TruncateTo(255, "") + "\""); DateTime latestUpdateUTC = DateTime.MinValue; foreach (FeedItem feedItem in updatedFeeds) { if (feedItem.PublishingDate.HasValue && feedItem.PublishingDate.Value.ToUniversalTime() > latestUpdateUTC) { latestUpdateUTC = feedItem.PublishingDate.Value.ToUniversalTime(); } string fieldName = feedItem.PublishingDate.HasValue ? feedItem.PublishingDate.Value.ToLocalTime().ToString() : DateTime.Now.ToString(); string author = feedItem.Author; if (author.IsEmpty()) { if (feed.Type == FeedType.Rss_1_0) { author = (feedItem.SpecificItem as Rss10FeedItem)?.DC?.Creator; } else if (feed.Type == FeedType.Rss_2_0) { author = (feedItem.SpecificItem as Rss20FeedItem)?.DC?.Creator; } } author = !author.IsEmptyOrWhiteSpace() ? $"{author.Trim()}: " : string.Empty; string maskedLink = $"[{author}{ParseHtml(feedItem.Title).Trim()}]({feedItem.Link})"; string content = ParseHtml(feedItem.Description).Trim(); if (content.IsEmptyOrWhiteSpace()) { content = ParseHtml(feedItem.Content).Trim(); } content = content.IsEmptyOrWhiteSpace() ? "[...]" : content.TruncateTo(250, ""); string fieldContent = $"{maskedLink}{Environment.NewLine}*{content}".TruncateTo(1023, "") + "*"; // Embed field value must be <= 1024 characters _ = builder.AddField(fieldName, fieldContent, true); } _ = await(channel?.SendMessageAsync("", false, builder.Build())).ConfigureAwait(false); if (latestUpdateUTC > DateTime.MinValue) { guildFeed.LastUpdate = latestUpdateUTC; _ = dbContext.Feeds.Update(guildFeed); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } } }
protected override async Task <bool> PostServerInfoAsync(GameServer discordGameServer) { if (discordGameServer == null) { return(false); } MineQuery query = null; try { query = new MineQuery(discordGameServer.ServerIP.Address, discordGameServer.ServerIP.Port, logger); MineQueryResult serverInfo = await query.GetServerInfoAsync().ConfigureAwait(false); if (serverInfo == null) { return(false); } SocketGuild guild = discordClient?.GetGuild(discordGameServer.GuildID); SocketTextChannel channel = guild?.GetTextChannel(discordGameServer.ChannelID); if (guild == null || channel == null) { return(false); } EmbedBuilder builder = new EmbedBuilder() .WithColor(new Color(21, 26, 35)) .WithTitle($"Minecraft Server ({discordGameServer.ServerIP.Address}:{discordGameServer.ServerIP.Port})") .WithDescription($"Motd: {serverInfo.Description.Motd}"); _ = serverInfo.Players.Sample != null && serverInfo.Players.Sample.Count > 0 ? builder.AddField($"Online Players ({serverInfo.Players.Online}/{serverInfo.Players.Max})", string.Join(", ", serverInfo.Players.Sample.Select(x => x.Name))) : builder.AddField("Online Players", $"{serverInfo.Players.Online}/{serverInfo.Players.Max}"); if (discordGameServer.GameVersion.IsEmpty()) { discordGameServer.GameVersion = serverInfo.Version.Name; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } else { if (serverInfo.Version.Name != discordGameServer.GameVersion) { discordGameServer.GameVersion = serverInfo.Version.Name; discordGameServer.LastVersionUpdate = DateTime.Now; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } } string lastServerUpdate = ""; if (discordGameServer.LastVersionUpdate.HasValue) { lastServerUpdate = $" (Last update: {discordGameServer.LastVersionUpdate.Value})"; } _ = builder.WithFooter($"Server version: {serverInfo.Version.Name}{lastServerUpdate} || Last check: {DateTime.Now}"); // Generate chart every full 10 minutes if (DateTime.Now.Minute % 10 == 0) { string chart = await GenerateHistoryChartAsync(discordGameServer, serverInfo.Players.Online, serverInfo.Players.Max).ConfigureAwait(false); if (!chart.IsEmptyOrWhiteSpace()) { _ = builder.AddField("Player Count History", chart); } } if (discordGameServer.MessageID.HasValue) { if (await channel.GetMessageAsync(discordGameServer.MessageID.Value).ConfigureAwait(false) is IUserMessage existingMessage && existingMessage != null) { await existingMessage.ModifyAsync(x => x.Embed = builder.Build()).ConfigureAwait(false); } else { logger.LogWarning($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed."); await RemoveServerAsync(discordGameServer.ServerIP, discordGameServer.GuildID).ConfigureAwait(false); _ = await channel.SendMessageAsync($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed. Please use the proper remove command to remove the gameserver").ConfigureAwait(false); return(false); } } else { IUserMessage message = await(channel?.SendMessageAsync("", false, builder.Build())).ConfigureAwait(false); discordGameServer.MessageID = message.Id; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } }
protected override async Task <bool> PostServerInfoAsync(GameServer discordGameServer) { if (discordGameServer == null) { return(false); } ServerQuery serverQuery = null; try { using var udpClient = new UdpWrapper(); serverQuery = new ServerQuery(udpClient, null); serverQuery.Connect(discordGameServer.ServerIP.ToString()); ServerInfo serverInfo = await serverQuery.GetServerInfoAsync().ConfigureAwait(false); List <Player> players = (await serverQuery.GetPlayersAsync().ConfigureAwait(false)).Where(p => !p.Name.IsEmptyOrWhiteSpace()).ToList(); if (serverInfo == null || players == null) { return(false); } SocketGuild guild = discordClient?.GetGuild(discordGameServer.GuildID); ITextChannel channel = guild?.GetTextChannel(discordGameServer.ChannelID); if (guild == null || channel == null) { return(false); } string onlinePlayers = players.Count > serverInfo.MaxPlayers ? $"{serverInfo.MaxPlayers}(+{players.Count - serverInfo.MaxPlayers})/{serverInfo.MaxPlayers}" : $"{players.Count}/{serverInfo.MaxPlayers}"; var builder = new EmbedBuilder() .WithColor(new Color(21, 26, 35)) .WithTitle($"{serverInfo.Game} Server ({discordGameServer.ServerIP.Address}:{serverInfo.Port})") .WithDescription(serverInfo.Name) .AddField("Online Players", onlinePlayers) .AddField("Current Map", serverInfo.Map); if (players != null && players.Count > 0) { _ = builder.AddField("Currently connected players:", string.Join(", ", players.Select(x => x.Name).Where(name => !name.IsEmpty()).OrderBy(x => x)).TruncateTo(1023)); } //Discord removed support for protocols other than http or https so this currently makes no sense. Leaving it here, in case they re-enable it //string connectLink = $"steam://connect/{discordGameServer.ServerIP.Address}:{serverInfo.Port}"; //_ = builder.AddField("Connect using this link", connectLink); if (discordGameServer.GameVersion.IsEmpty()) { discordGameServer.GameVersion = serverInfo.Version; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } else { if (serverInfo.Version != discordGameServer.GameVersion) { discordGameServer.GameVersion = serverInfo.Version; discordGameServer.LastVersionUpdate = DateTime.Now; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } } string lastServerUpdate = ""; if (discordGameServer.LastVersionUpdate.HasValue) { lastServerUpdate = $" (Last update: {discordGameServer.LastVersionUpdate.Value})"; } _ = builder.AddField("Server version", $"{serverInfo.Version}{lastServerUpdate}"); _ = builder.WithFooter($"Last check: {DateTime.Now}"); string chart = await GenerateHistoryChartAsync(discordGameServer, serverInfo.Players, serverInfo.MaxPlayers).ConfigureAwait(false); if (!chart.IsEmptyOrWhiteSpace()) { _ = builder.AddField("Player Count History", chart); } if (discordGameServer.MessageID.HasValue) { if (await channel.GetMessageAsync(discordGameServer.MessageID.Value).ConfigureAwait(false) is IUserMessage existingMessage && existingMessage != null) { await existingMessage.ModifyAsync(x => x.Embed = builder.Build()).ConfigureAwait(false); } else { logger.LogWarning($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed."); await RemoveServerAsync(discordGameServer.ServerIP, discordGameServer.GuildID).ConfigureAwait(false); _ = await channel.SendMessageAsync($"Error getting updates for server {discordGameServer.ServerIP}. Original message was removed. Please use the proper remove command to remove the gameserver").ConfigureAwait(false); return(false); } } else { discordGameServer.MessageID = (await(channel?.SendMessageAsync("", false, builder.Build())).ConfigureAwait(false)).Id; _ = dbContext.GameServers.Update(discordGameServer); _ = await dbContext.SaveChangesAsync().ConfigureAwait(false); } }
public async Task SavelinksAsync([Summary("The message link to quote")] string link, [Summary("The qauntities of link to save")] int quantity) { // Initializes the control boolean bool success = false; // Remove the message base part and splits all the IDs into an array string[] stringIDs = link.Replace(MessageBaseLink, "").Split('/'); // Creates a new array to hold the IDs ulong[] ids = new ulong[3]; // Parses all the IDs from strings to unsigned longs and saves the result into the array, also it stores the successes or failures into the boolean for (int i = 0; i < 3; i++) { success = UInt64.TryParse(stringIDs[i], out ids[i]); } // If the parse fails, delete the original user command message if (!success) { await Context.Message.DeleteAsync(); await Ageha.Log(LogSeverity.Error, "Could not parse some ID"); return; } // Free up memory stringIDs = null; // Tries to get the guild from the ID SocketGuild sourceGuild = Context.Client.GetGuild(ids[0]); // If the guild is null, reply to the user if (sourceGuild == null) { await ReplyAsync("I'm not in the linked server"); return; } // Tries to get the channel from the ID SocketTextChannel sourceChannel = sourceGuild?.GetTextChannel(ids[1]); // If the channel is null, reply to the user if (sourceChannel == null) { await ReplyAsync("I can't view the linked channel"); return; } // Tries to get the message from the ID IMessage linkedMessage = sourceChannel?.GetMessageAsync(ids[2]).Result; // If the message is null, reply to the user if (linkedMessage == null) { await ReplyAsync("The linked message doesn't exist"); return; } // Free up some memory ids = null; // Gets the cached messages var cachedMessages = await sourceChannel.GetMessagesAsync(linkedMessage, Direction.Before, quantity).FlattenAsync(); // Puts the linked message in the list cachedMessages.Append(linkedMessage); // Reverses the list to be in chronological order cachedMessages.Reverse(); // Sends the quantity of found messages in the channel await ReplyAsync($"Found {cachedMessages.Count()} links."); // Creates an empty dictionary and a counter Dictionary <int, string> links = new Dictionary <int, string>(); int counter = 0; // Only proceeds if any messages are found if (cachedMessages != null || cachedMessages.Count() > 0) { // Creates a valid file name to save the links string fileName = $"{MakeValidFileName(sourceGuild.Name)}_{MakeValidFileName(sourceChannel.Name)}_{linkedMessage.Id}.json"; // Iterates over all messages found foreach (IMessage message in cachedMessages) { // Only tries to pick emotes if the message isn't empty if (!String.IsNullOrWhiteSpace(message.Content)) { // Iterates over all tags foreach (ITag tag in message.Tags) { // Only procceeds on emote tags if (tag.Type == TagType.Emoji) { // Adds the emote link and updates the counter links.Add(counter++, Emote.Parse($"<:{(tag.Value as Emote).Name}:{tag.Key.ToString()}>").Url); } } } // Checks to seed if there are any embeds if (message.Embeds.Count > 0) { GetEmbeds(message.Embeds, ref links, ref counter); } // Checks to seed if there are any attachments if (message.Attachments.Count > 0) { GetAttachments(message.Attachments, ref links, ref counter); } } // Writes the json on a file JsonWrapper.WriteJSON <int, string>(fileName, links); // Sends the json back in the channel await Context.Channel.SendFileAsync(fileName, $"Here is the json containing {cachedMessages.Count()} links from before the message : {linkedMessage.GetJumpUrl()}"); // Deletes the original file File.Delete(fileName); } }
private static async Task CheckRuns(SocketGuild guild, ulong channelId, int minutesBefore, Func <SocketGuildUser, IMessage, IEmbed, Task> onMatch, CancellationToken token) { var channel = guild?.GetTextChannel(channelId); if (channel == null) { await Task.Delay(3000, token); return; } Log.Information("Checking runs..."); await foreach (var page in channel.GetMessagesAsync().WithCancellation(token)) { foreach (var message in page) { var embed = message.Embeds.FirstOrDefault(e => e.Type == EmbedType.Rich); var nullableTimestamp = embed?.Timestamp; if (!nullableTimestamp.HasValue) { continue; } var timestamp = nullableTimestamp.Value; // Remove expired posts if (timestamp.AddMinutes(60) < DateTimeOffset.Now) { await message.DeleteAsync(); continue; } // Hacky solution to avoid rare situations where people get spammed with notifications if (timestamp.AddMinutes(-22) < DateTimeOffset.Now) { continue; } Log.Information("{Username} - ETA {TimeUntil} hrs.", embed.Author?.Name, (timestamp - DateTimeOffset.Now).TotalHours); // ReSharper disable once InvertIf if (timestamp.AddMinutes(-minutesBefore) <= DateTimeOffset.Now && embed.Author.HasValue) { Log.Information("Run matched!"); var host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); if (host == null) { host = guild.Users.FirstOrDefault(u => u.ToString() == embed.Author.Value.Name); } var messageReferenceCopy = message; try { await onMatch(host, messageReferenceCopy, embed); } catch (Exception e) { Log.Error(e, "error: uncaught exception in onMatch"); } } } } }
/// <summary> /// Posts any moderation actions done with the bot into the assigned mod log channel if one is assigned. /// Post is an embed that shares the action, target'd user, user that used the command, and reason for the command. /// </summary> /// <param name="guild">The guild the command was used in.</param> /// <param name="action">The moderation action that was used.</param> /// <param name="user">The moderator who used the command.</param> /// <param name="target">The user targeted by the command.</param> /// <param name="reason">The reason for using the command.</param> /// <returns></returns> public static async Task PostInModLog(SocketGuild guild, string action, SocketUser user, IGuildUser target, [Remainder] string reason) { //Channel to send the chat logs in ulong channel = Data.Data.GetModLogChannel(guild.Id); if (channel != 0) //If a channel has been assigned as the mod log channel { Random ran = new Random(); int color1 = ran.Next(0, 256); //Gets a random color for the embed int color2 = ran.Next(0, 256); int color3 = ran.Next(0, 256); SocketTextChannel channelPost = guild.GetTextChannel(channel); if (target != null) //If action was targeted at a user { //Embedbuilder object EmbedBuilder Embed = new EmbedBuilder(); Embed.AddField("Action:", action); Embed.AddField("Targeted User:"******"{target.Username} ({target.Mention})"); Embed.AddField("Moderator:", $"{user.Username} ({user.Mention})"); Embed.AddField("Reason:", reason); //Assign the author's image Embed.WithThumbnailUrl(user.GetAvatarUrl()); //Add the timestamp to the bottom Embed.WithCurrentTimestamp(); //Assign the color on the left side Embed.WithColor(color1, color2, color3); try { await channelPost.SendMessageAsync("", false, Embed.Build()); } catch (Exception) { await user.SendMessageAsync("I do not have permission to post in the mod log. Please inform the administrator of the server."); } } else //If action was not targeted at a user { //Embedbuilder object EmbedBuilder Embed = new EmbedBuilder(); Embed.AddField("Action:", action); Embed.AddField("Moderator:", $"{user.Username} ({user.Mention})"); if (reason != "") { Embed.AddField("Reason:", reason); } //Assign the author's image Embed.WithThumbnailUrl(user.GetAvatarUrl()); Embed.WithCurrentTimestamp(); //Assign the color on the left side Embed.WithColor(color1, color2, color3); try { await channelPost.SendMessageAsync("", false, Embed.Build()); } catch (Exception) { await user.SendMessageAsync("I do not have permission to post in the mod log. Please inform the administrator of the server."); } } } }
public override async Task ServerUpdate(SocketGuild server) { var triviaServerData = server.GetMemory().GetData <TriviaSystem, TriviaServerData>(); if (!triviaServerData.IsReady) { return; //TODO: Let the admins know that this is misconfigured. } var now = DateTime.Now; if ((now - triviaServerData.lastTriviaPost).TotalSeconds <= triviaServerData.postIntervalInSeconds) { return; } triviaServerData.lastTriviaPost = now; triviaServerData.currentChannel = triviaServerData.triviaChannels[MopBot.Random.Next(triviaServerData.triviaChannels.Count)]; var channel = server.GetTextChannel(triviaServerData.currentChannel); if (channel == null) { return; //TODO: Same as above } TriviaQuestion[] validQuestions; //Find questions we didn't pick yet, handle running out of them. while (true) { lock (triviaServerData.questions) { validQuestions = triviaServerData.questions.Where(q => !q.wasPosted).ToArray(); } if (validQuestions.Length == 0) { if (triviaServerData.autoClearCache && triviaServerData.questions.Count > 0) { ClearCache(triviaServerData); continue; } else { await channel.SendMessageAsync($"{server.Owner.Mention} We're out of trivia questions!\r\n\r\nAdd new questions, or..\r\n• Use `!trivia clearcache` to clear list of used questions;\r\n• Use `!trivia autoclearcache true` to automate this process, if you're fully okay with same questions being repeat;"); return; } } break; } //Set new question triviaServerData.currentQuestion = validQuestions[MopBot.Random.Next(validQuestions.Length)]; triviaServerData.currentQuestion.wasPosted = true; currentQuestionRegex = null; //This will cause a new one to be made, when needed. string mention = null; SocketRole role = null; bool disallowRoleMention = false; var currentUser = server.CurrentUser; if (triviaServerData.triviaRole > 0) { role = server.GetRole(triviaServerData.triviaRole); if (role != null) { if (!role.IsMentionable && currentUser.HasDiscordPermission(gp => gp.ManageRoles)) { await role.ModifyAsync(rp => rp.Mentionable = true); disallowRoleMention = true; } mention = role.Mention; } else { triviaServerData.triviaRole = 0; } } var embedBuilder = MopBot.GetEmbedBuilder(server) .WithAuthor("The next question is...") //.WithTitle("The next question is...") .WithDescription($"**{triviaServerData.currentQuestion.question}**") .WithFooter("Type your answer right in this channel!"); if (triviaServerData.thumbnailUrls?.Length > 0 == true) { try { embedBuilder.WithThumbnailUrl(triviaServerData.thumbnailUrls[MopBot.Random.Next(triviaServerData.thumbnailUrls.Length)]); } catch { } } await channel.SendMessageAsync(mention, embed : embedBuilder.Build()); if (disallowRoleMention) { await role.ModifyAsync(rp => rp.Mentionable = false); } if (triviaServerData.lockTriviaChannel && currentUser.HasChannelPermission(channel, DiscordPermission.ManageChannel)) { //Unlock the channel, since there's a question now. await channel.ModifyPermissions(server.EveryoneRole, op => op.SendMessages == PermValue.Deny?op.Modify(sendMessages : PermValue.Inherit) : op); } }
/// <summary> /// Posts a message towards the 'UserNameQueue' post target containing the name before and after the change with the given title. /// The embed has as thumbnail the avatar of the user (none if default) and is posted towards the given guild. /// </summary> /// <param name="embedTitle">Title of the embed</param> /// <param name="beforeText">Text of the embed to be used for the 'Before' field</param> /// <param name="afterText">Text of the embed to be used for the 'After' field</param> /// <param name="user">User with the invalid username, used for the avatar in the embed.</param> /// <param name="guild">The <see cref"Discord.WebSocket.SocketGuild"/> guild where this is posted towards in the 'UserNameQueue' post target</param> /// <returns></returns> private async Task NotifyAboutIllegalUserName(string embedTitle, string beforeText, string afterText, IUser user, SocketGuild guild) { var embed = GetUserNameNotificationEmbed(embedTitle, beforeText, afterText, user); var userlog = guild.GetTextChannel(Global.PostTargets[PostTarget.USERNAME_QUEUE]); await userlog.SendMessageAsync(embed : embed); }
static Logging() { Program.Initialize += delegate(object?sender, DiscordSocketClient client) { client.ChannelDestroyed += delegate(SocketChannel channel) { //Only currently needed for Logs at the moment //Will try to remove the pair if it exists in the list SaveHandler.LogSave.Remove(new KeyValuePair <ulong, ulong>(((SocketGuildChannel)channel).Guild.Id, channel.Id)); SaveHandler.LockdownSave[((SocketGuildChannel)channel).Guild.Id] .Remove(((SocketGuildChannel)channel).Id); return(Task.CompletedTask); }; client.MessageUpdated += async delegate(Cacheable <IMessage, ulong> oldMessage, SocketMessage newMessage, ISocketMessageChannel channel) { if (!oldMessage.HasValue || newMessage.Author.IsBot) { return; } SocketGuild guild = ((SocketTextChannel)channel).Guild; if (SaveHandler.LogSave.ContainsKey(guild.Id)) { SocketTextChannel logChannel = guild.GetTextChannel(SaveHandler.LogSave[guild.Id]); if (oldMessage.Value.Content != newMessage.Content) { EmbedBuilder builder = new EmbedBuilder { Color = Color.Teal, Title = "Message Edited", Url = newMessage.GetJumpUrl(), Description = $"From {newMessage.Author.Mention} in <#{channel.Id}>:\n**Before:**\n{oldMessage.Value.Content}\n**After:**\n{newMessage.Content}" }; if (builder.Length > EmbedBuilder.MaxDescriptionLength) { string[] msgs = Misc.ConvertToDiscordSendable(builder.Description); for (int i = 0; i < msgs.Length; i++) { string msg = msgs[i]; builder.Description = msg; if (msgs.Length - 1 == i) { builder.WithCurrentTimestamp(); } await logChannel.SendMessageAsync(embed : builder.Build()); if (i == 0) { builder.Title = null; } } } else { builder.WithCurrentTimestamp(); await logChannel.SendMessageAsync(embed : builder.Build()); } } } }; client.UserLeft += async delegate(SocketGuildUser user) { if (SaveHandler.LogSave.ContainsKey(user.Guild.Id)) { SocketTextChannel logChannel = user.Guild.GetTextChannel(SaveHandler.LogSave[user.Guild.Id]); RestAuditLogEntry lastKick = (await user.Guild.GetAuditLogsAsync(3, actionType: ActionType.Kick).FlattenAsync()).FirstOrDefault(l => (l.Data as KickAuditLogData).Target == user); EmbedBuilder builder = new EmbedBuilder { Color = Color.Teal }; if (lastKick != null) { string msg = $"You were kicked from {user.Guild.Name}"; if (lastKick.Reason != null) { msg += $"\nReason: {lastKick.Reason}"; } try { await user.SendMessageAsync(msg); } catch { } builder.WithCurrentTimestamp(); builder.Title = "User Kicked"; builder.Description = $"{lastKick.User.Mention} kicked {user.Mention} | {user}"; if (lastKick.Reason != null) { builder.Description += $"\n__Reason__: \"{lastKick.Reason}\""; } await logChannel.SendMessageAsync(embed : builder.Build()); } builder.WithCurrentTimestamp(); builder.Title = "User Left"; builder.Description = $"{user.Mention} | {user}"; await logChannel.SendMessageAsync(embed : builder.Build()); } }; client.UserBanned += async delegate(SocketUser user, SocketGuild guild) { if (SaveHandler.LogSave.ContainsKey(guild.Id)) { RestAuditLogEntry lastBan = (await guild.GetAuditLogsAsync(3, actionType: ActionType.Ban).FlattenAsync()).FirstOrDefault(l => (l.Data as BanAuditLogData).Target == user); if (lastBan != null) { string msg = $"You were banned from {guild.Name}"; if (lastBan.Reason != null) { msg += $"\nReason: {lastBan.Reason}"; } try { await user.SendMessageAsync(msg); } catch { } SocketTextChannel logChannel = guild.GetTextChannel(SaveHandler.LogSave[guild.Id]); EmbedBuilder builder = new EmbedBuilder { Color = Color.Teal, Title = "User Banned", Description = $"{lastBan.User.Mention} banned {user.Mention} | {user}" }; builder.WithCurrentTimestamp(); if (!string.IsNullOrWhiteSpace(lastBan.Reason)) { builder.Description += $"\n__Reason__: \"{lastBan.Reason}\""; } await logChannel.SendMessageAsync(embed : builder.Build()); } } }; client.MessageDeleted += async delegate(Cacheable <IMessage, ulong> message, ISocketMessageChannel channel) { if (!message.HasValue || message.Value.Author.IsBot) { return; } SocketGuild guild = ((SocketGuildChannel)channel).Guild; if (SaveHandler.LogSave.ContainsKey(guild.Id)) { SocketTextChannel logChannel = guild.GetTextChannel(SaveHandler.LogSave[guild.Id]); if (logChannel.Id != channel.Id && (!string.IsNullOrWhiteSpace(message.Value.Content) || message.Value.Attachments.Any())) { EmbedBuilder builder = new EmbedBuilder { Description = "", Color = Color.Teal, Title = "Message Deleted", }; RestAuditLogEntry messageDeleted = (await guild.GetAuditLogsAsync(3, actionType: ActionType.MessageDeleted).FlattenAsync()).FirstOrDefault(l => (l.Data as MessageDeleteAuditLogData).Target.Id == message.Value.Author.Id); if (!string.IsNullOrWhiteSpace(message.Value.Content)) { builder.Description += $"From {message.Value.Author.Mention}, in <#{channel.Id}>"; } if (messageDeleted != null) { builder.Description += $", deleted by {messageDeleted.User.Mention}"; } builder.Description += $":\n{message.Value.Content}"; if (message.Value.Attachments.Any()) { builder.Description += "\n\nAttachments:\n"; foreach (IAttachment attachment in message.Value.Attachments) { builder.Description += $"{attachment.Url}\n"; } } if (builder.Length > EmbedBuilder.MaxDescriptionLength) { string[] msgs = Misc.ConvertToDiscordSendable(builder.Description); for (int i = 0; i < msgs.Length; i++) { string msg = msgs[i]; builder.Description = msg; if (msgs.Length - 1 == i) { builder.WithCurrentTimestamp(); } await logChannel.SendMessageAsync(embed : builder.Build()); if (i == 0) { builder.Title = null; } } } else { builder.WithCurrentTimestamp(); await logChannel.SendMessageAsync(embed : builder.Build()); } } } }; client.GuildMemberUpdated += async delegate(SocketGuildUser before, SocketGuildUser after) { if (before.IsBot) { return; } if (SaveHandler.LogSave.ContainsKey(after.Guild.Id)) { SocketTextChannel logChannel = after.Guild.GetTextChannel(SaveHandler.LogSave[after.Guild.Id]); if (logChannel != null) { if (before.Nickname != after.Nickname) { EmbedBuilder builder = new EmbedBuilder { Color = Color.Teal }; builder.WithCurrentTimestamp(); if (string.IsNullOrWhiteSpace(after.Nickname)) { builder.Title = "Nickname Removal"; builder.Description = $"{after.Mention}:\n`{before.Nickname}` -> `None`"; } else if (string.IsNullOrWhiteSpace(before.Nickname)) { builder.Title = "Nickname Changed"; builder.Description = $"{after.Mention}:\n`None` -> `{after.Nickname}`"; } else { builder.Title = "Nickname Changed"; builder.Description = $"{after.Mention}:\n`{before.Nickname}` -> `{after.Nickname}`"; } await logChannel.SendMessageAsync(embed : builder.Build()); } } } }; }; }
public static async Task GuildJoinedAlert(SocketGuild g) { destGuild = Program._client.GetGuild(701178110485463152); SocketTextChannel destChannel = destGuild.GetTextChannel(701178110933991466); await destChannel.SendMessageAsync("", false, Utilities.GetEmbedMessage("Guild Joined", $"Joined Guild: {g.Name}", $"Owner: {g.Owner.Username}\nGuild ID: {g.Id}\nUsers: {g.MemberCount}", null)); }
public static async Task ReceiveData(SerializedData.SerializedData data, TcpClient client) { try { if (data == null) { Console.WriteLine("STT: Received data null"); return; } Program.Log($"Receiving data: {data.Data} Channel: {data.Channel} for {data.Port}", true); if (data.Data.Contains("REQUEST_DATA PLAYER_LIST SILENT")) { return; } SocketGuild guild = Bot.Client.Guilds.FirstOrDefault(); if (data.Data.StartsWith("checksync")) { string[] args = data.Data.Split(' '); Program.Log($"Checking rolesync for {args[1]}", true); SyncedUser user = Program.Users.FirstOrDefault(u => u.UserId == args[1]); if (user == null) { Program.Log($"Role sync for {args[1]} not found.", true); return; } foreach (SocketRole role in guild.GetUser(user.DiscordId).Roles) { if (Program.SyncedGroups.ContainsKey(role.Id)) { SendData($"setgroup {user.UserId} {Program.SyncedGroups[role.Id]}", Program.Config.Port, "RoleSync"); } } } if (data.Data == "ping") { if (!bag.ContainsKey(data.Port)) { Console.WriteLine($"STT: Adding {data.Port}"); bag.TryAdd(data.Port, client); } if (!bag[data.Port].Connected || bag[data.Port] == null) { Console.WriteLine($"STT: Bag {data.Port} not connected or null, removing."); if (bag.TryRemove(data.Port, out TcpClient cli)) { cli?.Close(); } } Console.WriteLine($"STT: Received heartbeat for: {data.Port}"); if (!heartbeats.ContainsKey(data.Port)) { Heartbeat(data.Port); heartbeats.TryAdd(data.Port, 0); } else { heartbeats[data.Port]--; } Program.Log($"Updating channelID's for plugin..{data.Port}", true); try { Program.Log($"GameChannelID: {GameChannelId}", true); SendData("set gameid", data.Port, "bot", GameChannelId); Program.Log($"CommandChannelID: {CmdChannelId}", true); SendData("set cmdid", data.Port, "bot", CmdChannelId); } catch (Exception e) { Program.Log(e.ToString()); } return; } if (data.Data.StartsWith("updateStatus")) { Program.Log($"updating status for bot", true); string status = data.Data.Replace("updateStatus ", ""); if (status.StartsWith("0")) { await Bot.Client.SetStatusAsync(UserStatus.Idle); } else { await Bot.Client.SetStatusAsync(UserStatus.Online); } await Bot.Client.SetActivityAsync(new Game(status)); return; } data.Data = data.Data.Substring(data.Data.IndexOf('#') + 1); Console.WriteLine("Getting guild."); Console.WriteLine("Getting channel"); if (guild == null) { Console.WriteLine("Guild not found."); return; } SocketTextChannel chan = null; if (data.Channel == 1) { chan = guild.GetTextChannel(GameChannelId); } else if (data.Channel == 2) { chan = guild.GetTextChannel(CmdChannelId); } else { chan = guild.GetTextChannel(data.Channel); } if (chan == null) { await Program.Log(new LogMessage(LogSeverity.Critical, "recievedData", "Channel not found.")); return; } if (chan.Id == Program.Config.GameLogChannelId || chan.Id == Program.Config.CommandLogChannelId) { Program.Log("Storing message.", true); lock (_messages) { if (!_messages.ContainsKey(chan.Id)) { _messages.Add(chan.Id, string.Empty); } _messages[chan.Id] += $"[{DateTime.Now.Hour}:{DateTime.Now.Minute}:{DateTime.Now.Second}] {data.Data} {Environment.NewLine}"; } return; } Console.WriteLine("Sending message."); await chan.SendMessageAsync($"[{DateTime.Now.Hour}:{DateTime.Now.Minute}:{DateTime.Now.Second}] {data.Data}"); } catch (Exception e) { Console.WriteLine(e); } }