Esempio n. 1
0
        internal async Task HandleOnReactionAdded(
            Cacheable <IUserMessage, ulong> cachedMessage, ISocketMessageChannel messageChannel, SocketReaction reaction)
        {
            // TODO: Combine checks for reaction add/remove handler into one method
            if (!cachedMessage.HasValue || reaction.UserId == this.Client.CurrentUser.Id)
            {
                // Ignore the bot's own additions.
                return;
            }

            if (!(reaction.Channel is IGuildChannel guildChannel))
            {
                // Only listen to guild reacts.
                this.Logger.Verbose("Reaction addition ignored because it wasn't on a guild channel");
                return;
            }

            if (!(reaction.User.IsSpecified && reaction.User.Value is IGuildUser guildUser))
            {
                this.Logger.Verbose("Reaction addition ignored because it wasn't by a guild user");
                return;
            }

            IUserMessage message      = cachedMessage.Value;
            Player       player       = null;
            bool         playerAdded  = false;
            string       errorMessage = null;
            bool         attempt      = this
                                        .GetTournamentsManager(guildChannel.Guild)
                                        .TryReadWriteActionOnCurrentTournament(currentTournament =>
            {
                player = this.GetPlayerFromReactionEventOrNull(
                    currentTournament, guildUser, message.Id, reaction.Emote.Name, out errorMessage);
                if (player == null)
                {
                    // TODO: we may want to remove the reaction if it's on our team-join messages.
                    this.Logger.Verbose(
                        "Reaction addition ignored because it wasn't by a player. Message: {errorMessage}",
                        errorMessage);
                    return;
                }

                // Because player equality/hashing is only based on the ID, we can check if the player is in the set with
                // the new instance.
                playerAdded = currentTournament.TryAddPlayer(player);
            });

            if (!(attempt && playerAdded) && errorMessage != null)
            {
                // TODO: We should remove the reaction they gave instead of this one (this may also require the manage
                // emojis permission?). This would also require a map from userIds/Players to emojis in the tournament
                // state. The Reactions collection doesn't have information on who added it, and iterating through each
                // emoji to see if the user was there would be slow.
                Task deleteReactionTask = message.RemoveReactionAsync(
                    reaction.Emote, guildUser, RequestOptionsSettings.Default);
                Task sendMessageTask = guildUser.SendMessageAsync(errorMessage);
                await Task.WhenAll(deleteReactionTask, sendMessageTask);

                this.Logger.Verbose("Reaction removed. Message: {errorMessage}", errorMessage);
                return;
            }
            else if (player != null)
            {
                this.Logger.Debug("Player {id} joined team {name}", player.Id, player.Team.Name);
                await guildUser.SendMessageAsync(BotStrings.YouHaveJoinedTeam(player.Team.Name));
            }
        }