public void RemoveStargazers(StarboardEntry entry) { _starboardData.LockedRef(coll => { coll.Delete($"{entry.GuildId}_{entry.StarboardMessageId}"); coll.Delete($"{entry.GuildId}_{entry.StarredMessageId}"); }); }
public void UpdateStargazers(StarboardEntry entry) { _starboardData.LockedRef(coll => { coll.Upsert($"{entry.GuildId}_{entry.StarboardMessageId}", new StarboardDbEntry { GuildId = entry.GuildId, Key = entry.StarboardMessageId, Value = entry }); coll.Upsert($"{entry.GuildId}_{entry.StarredMessageId}", new StarboardDbEntry { GuildId = entry.GuildId, Key = entry.StarredMessageId, Value = entry }); }); }
public async Task HandleReactionAddAsync(Cacheable <IUserMessage, ulong> cachedMessage, Cacheable <IMessageChannel, ulong> cachedChannel, SocketReaction reaction) { var channel = await cachedChannel.GetOrDownloadAsync(); if (!IsStarReaction(channel, reaction, out var starboard, out var starboardChannel) || reaction.User.IsSpecified && reaction.User.Value.IsBot) { return; } var guildId = channel.Cast <IGuildChannel>().Guild.Id; var messageId = cachedMessage.Id; var starrerId = reaction.UserId; var message = await cachedMessage.GetOrDownloadAsync(); if (_db.TryGetStargazers(guildId, messageId, out var entry)) { using (await _starboardReadWriteLock.LockAsync(entry.StarredMessageId)) { // Add the star to the database if (entry.Stargazers.TryAdd(starrerId, channel == starboardChannel ? StarTarget.StarboardMessage : StarTarget.OriginalMessage)) { // Update message star count await UpdateOrPostToStarboardAsync(starboard, message, entry); _db.UpdateStargazers(entry); } else if (starboard.DeleteInvalidStars) { // Invalid star! Either the starboard post or the actual message already has a reaction by this user. await message.RemoveReactionAsync(_starEmoji, reaction.UserId, DiscordHelper.CreateRequestOptions(x => x.AuditLogReason = "Star reaction is invalid: User has already starred!")); } } } else if (channel != starboardChannel) // Can't make a new starboard message for a post in the starboard channel! { using (await _starboardReadWriteLock.LockAsync(messageId)) { if (message.Reactions.FirstOrDefault(e => e.Key.Name == _starEmoji.Name).Value.ReactionCount >= starboard.StarsRequiredToPost) { // Create new star message! entry = new StarboardEntry { GuildId = guildId, StarredMessageId = messageId, StarboardMessageId = 0, // is set in UpdateOrPostToStarboardAsync Stargazers = { [starrerId] = StarTarget.OriginalMessage } }; await UpdateOrPostToStarboardAsync(starboard, message, entry); } _db.UpdateStargazers(entry); } } }
/// <summary> /// Updates, posts, or deletes a message in the starboard in a guild. /// Calls to this method should be synchronized to _messageWriteLock beforehand! /// </summary> /// <param name="starboard">The guild's starboard configuration</param> /// <param name="message">The message to star (must be from a <see cref="IGuildChannel"/>)</param> /// <param name="entry"></param> /// <returns></returns> private async Task UpdateOrPostToStarboardAsync(StarboardOptions starboard, IMessage message, StarboardEntry entry) { var starboardChannel = _client.GetChannel(starboard.StarboardChannel); if (!(starboardChannel is SocketTextChannel starboardTextChannel)) { return; } if (entry.StarboardMessageId == 0) { if (entry.StarCount >= starboard.StarsRequiredToPost) { // New message just reached star threshold, send it var newMessage = await PostToStarboardAsync(message, entry.StarCount); entry.StarboardMessageId = newMessage.Id; } } else { IMessage starboardMessage; try { starboardMessage = await starboardTextChannel.GetMessageAsync(entry.StarboardMessageId); } catch (HttpException ex) when(ex.HttpCode == HttpStatusCode.NotFound) { Logger.Debug(LogSource.Service, "Could not retrieve original star message in channel."); return; } if (!(starboardMessage is IUserMessage starboardUserMessage)) { return; } if (entry.StarCount >= starboard.StarsRequiredToPost) { // Update existing message var targetMessage = $"{_starEmoji} {entry.StarCount}"; if (starboardMessage.Content != targetMessage) { await starboardUserMessage.ModifyAsync(e => e.Content = targetMessage); } } else { // Star count below the limit so delete the message if any await starboardMessage.DeleteAsync(); entry.StarboardMessageId = 0; } } }
public bool TryGetStargazers(ulong guildId, ulong messageId, [NotNullWhen(true)] out StarboardEntry entry) { entry = GetStargazersInternal(guildId, messageId)?.Value; return(entry != null); }