Esempio n. 1
0
        async Task HandleReactionAdded(ReactionAddedEventArgs e)
        {
            var options = _options.CurrentValue;

            if (_claimEmojiFilter.IsClaimEmoji(e.Emoji) && _pendingClaims.TryRemove(e.Message.Id, out var claim))
            {
                var(logPlace, channel, message, character, stopwatch) = claim;

                await Task.Delay(TimeSpan.FromSeconds(options.DelaySeconds));

                var replySubs = new
                {
                    character      = character.DisplayName.Split(' ', 2)[0].ToLowerInvariant(),
                    character_full = character.DisplayName.ToLowerInvariant(),
                    Character      = character.DisplayName.Split(' ', 2)[0],
                    Character_full = character.DisplayName,

                    anime = character.DisplayAnime.ToLowerInvariant(),
                    Anime = character.DisplayAnime
                };

                await _replySender.SendAsync(channel, ReplyEvent.BeforeClaim, replySubs);

                IUserMessage response;

                try
                {
                    response = await _commandHandler.ReactAsync(message, e.Emoji);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, $"Could not claim character '{character}' in {logPlace}.");
                    return;
                }

                if (_outputParser.TryParseClaimSucceeded(response.Content, out var claimer, out _) && claimer.Equals(e.Client.CurrentUser.Name, StringComparison.OrdinalIgnoreCase))
                {
                    _logger.LogWarning($"Claimed character '{character}' in {logPlace} in {stopwatch.Elapsed.TotalMilliseconds}ms.");

                    await _replySender.SendAsync(channel, ReplyEvent.ClaimSucceeded, replySubs);

                    return;
                }

                if (_outputParser.TryParseClaimFailed(response.Content, out var resetTime))
                {
                    _states.GetOrAdd(message.ChannelId, new ClaimState()).CooldownResetTime = DateTime.Now + resetTime;

                    _logger.LogWarning($"Could not claim character '{character}' in {logPlace} due to cooldown. Cooldown finishes in {resetTime}.");

                    await _replySender.SendAsync(channel, ReplyEvent.ClaimFailed, replySubs);

                    return;
                }

                _logger.LogWarning($"Probably claimed character '{character}' in {logPlace}, but result could not be determined. Channel is probably busy.");
            }

            else if (_claimEmojiFilter.IsKakeraEmoji(e.Emoji, out var kakera) && _pendingKakeraClaims.TryRemove(e.Message.Id, out claim))
            {
                var(logPlace, channel, message, character, stopwatch) = claim;

                // check cooldown here (to allow skipping cooldown check for purple kakera)
                var state = _states.GetOrAdd(channel.Id, new ClaimState());
                var now   = DateTime.Now;

                if (!options.KakeraIgnoreCooldown && now < state.KakeraResetTime && kakera != KakeraType.Purple)
                {
                    return;
                }

                if (!options.KakeraTargets.Contains(kakera))
                {
                    _logger.LogInformation($"Ignoring {kakera} kakera on character '{character}' in {logPlace} because it is not targeted.");
                    return;
                }

                await Task.Delay(TimeSpan.FromSeconds(options.KakeraDelaySeconds));

                var replySubs = new
                {
                    kakera = kakera.ToString().ToLowerInvariant(),
                    Kakera = kakera.ToString()
                };

                await _replySender.SendAsync(channel, ReplyEvent.BeforeKakera, replySubs);

                IUserMessage response;

                try
                {
                    response = await _commandHandler.ReactAsync(message, e.Emoji);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, $"Could not claim {kakera} kakera on character '{character}' in {logPlace}.");
                    return;
                }

                if (_outputParser.TryParseKakeraSucceeded(response.Content, out var claimer, out _) && claimer.Equals(e.Client.CurrentUser.Name, StringComparison.OrdinalIgnoreCase))
                {
                    _logger.LogWarning($"Claimed {kakera} kakera on character '{character}' in {logPlace} in {stopwatch.Elapsed.TotalMilliseconds}ms.");

                    await _replySender.SendAsync(channel, ReplyEvent.KakeraSucceeded, replySubs);

                    return;
                }

                if (_outputParser.TryParseKakeraFailed(response.Content, out var resetTime))
                {
                    state.KakeraResetTime = now + resetTime;

                    _logger.LogWarning($"Could not claim {kakera} kakera on character '{character}' in {logPlace} due to cooldown. Kakera is reset in {resetTime}.");

                    await _replySender.SendAsync(channel, ReplyEvent.KakeraFailed, replySubs);

                    return;
                }

                _logger.LogWarning($"Probably claimed {kakera} kakera on character '{character}' in {logPlace}, but result could not be determined. Channel is probably busy.");
            }
        }
Esempio n. 2
0
#pragma warning disable 1998
        async Task HandleMessageReceived(MessageReceivedEventArgs e)
#pragma warning restore 1998
        {
            // purge old pending claims (avoids memory leak)
            foreach (var id in _pendingClaims.Keys)
            {
                if (_pendingClaims.TryGetValue(id, out var claim) && claim.CreatedTime.AddMinutes(1) < DateTime.Now)
                {
                    _pendingClaims.TryRemove(id, out _);
                }
            }

            foreach (var id in _pendingKakeraClaims.Keys)
            {
                if (_pendingKakeraClaims.TryGetValue(id, out var claim) && claim.CreatedTime.AddMinutes(1) < DateTime.Now)
                {
                    _pendingKakeraClaims.TryRemove(id, out _);
                }
            }

            var options = _options.CurrentValue;

            // enabled, message author is mudae, channel is configured, embed exists
            if (!options.Enabled || !(e.Message is IUserMessage message && _userFilter.IsMudae(message.Author)) || _channelList.CurrentValue.Items.All(x => x.Id != message.ChannelId) || message.Embeds.Count == 0)
            {
                return;
            }

            var stopwatch = Stopwatch.StartNew();

            var channel = (IMessageChannel)e.Client.GetChannel(message.ChannelId);
            var guild   = channel is IGuildChannel gc?e.Client.GetGuild(gc.GuildId) : null;

            var logPlace = $"channel '{channel.Name}' ({channel.Id}, server '{guild?.Name}')";

            var embed       = message.Embeds[0];
            var description = embed.Description.Split('\n', StringSplitOptions.RemoveEmptyEntries);
            var character   = new CharacterInfo(embed.Author.Name, description[0]);

            // ignore $im messages
            if (!options.BypassImCheck && description.Any(l => l.StartsWith("claim rank:", StringComparison.OrdinalIgnoreCase) || l.StartsWith("like rank:", StringComparison.OrdinalIgnoreCase)))
            {
                return;
            }

            _logger.LogDebug($"Detected character '{character}' in {logPlace}.");

            _pendingKakeraClaims[message.Id] = new PendingClaim(logPlace, channel, message, character, stopwatch);

            // ignore already claimed
            if (embed.Footer?.Text.StartsWith("belongs", StringComparison.OrdinalIgnoreCase) == true)
            {
                return;
            }

            var wishedBy = message.Content.StartsWith("wished by", StringComparison.OrdinalIgnoreCase) ? message.GetUserIds().ToArray() : null;

            // must be wished or included in a user wishlist
            if (!_characterFilter.IsWished(character, wishedBy))
            {
                _logger.LogInformation($"Ignoring character '{character}' in {logPlace} because they are not wished.");
                return;
            }

            // check cooldown
            var state = _states.GetOrAdd(channel.Id, new ClaimState());
            var now   = DateTime.Now;

            if (!options.IgnoreCooldown && now < state.CooldownResetTime)
            {
                _logger.LogWarning($"Ignoring character '{character}' in {logPlace} because of cooldown. Cooldown finishes in {state.CooldownResetTime - now}.");
                return;
            }

            _logger.LogWarning($"Attempting to claim character '{character}' in {logPlace}...");

            _pendingClaims[message.Id] = new PendingClaim(logPlace, channel, message, character, stopwatch);

            /* Claim from message event instead of reaction event */

            if (_pendingClaims.TryRemove(e.Message.Id, out var claim1))
            {
                var(logPlace1, channel1, message1, character1, stopwatch1) = claim1;

                await Task.Delay(TimeSpan.FromSeconds(options.DelaySeconds));

                var replySubs = new
                {
                    character      = character1.DisplayName.Split(' ', 2)[0].ToLowerInvariant(),
                    character_full = character1.DisplayName.ToLowerInvariant(),
                    Character      = character1.DisplayName.Split(' ', 2)[0],
                    Character_full = character1.DisplayName,

                    anime = character1.DisplayAnime.ToLowerInvariant(),
                    Anime = character1.DisplayAnime
                };

                await _replySender.SendAsync(channel1, ReplyEvent.BeforeClaim, replySubs);

                IUserMessage response;

                try
                {
                    IEmoji emoji = new LocalEmoji("\uD83D\uDC96");

                    response = await _commandHandler.ReactAsync(message1, emoji);
                }
                catch (Exception ex)
                {
                    _logger.LogWarning(ex, $"Could not claim character '{character1}' in {logPlace1}.");
                    return;
                }

                bool tryParseClaim = _outputParser.TryParseClaimSucceeded(response.Content, out var claimer, out _);
                _logger.LogDebug(response.Content);
                bool claimerEquals = claimer.Equals(e.Client.CurrentUser.Name, StringComparison.OrdinalIgnoreCase);

                _logger.LogDebug($"TryParseClaim: '{tryParseClaim}'. ClaimerEquals: '{claimerEquals}', claimer:{claimer} and user {e.Client.CurrentUser.Name}");

                if (tryParseClaim && claimerEquals)
                {
                    _logger.LogWarning($"Claimed character '{character1}' in {logPlace1} in {stopwatch1.Elapsed.TotalMilliseconds}ms.");

                    if (options.NotifyOnCharacter)
                    {
                        _notification.SendToast($"Claimed character '{character1}' in {logPlace1}.");
                    }

                    await _replySender.SendAsync(channel1, ReplyEvent.ClaimSucceeded, replySubs);

                    return;
                }

                if (_outputParser.TryParseClaimFailed(response.Content, out var resetTime))
                {
                    _states.GetOrAdd(message1.ChannelId, new ClaimState()).CooldownResetTime = DateTime.Now + resetTime;

                    _logger.LogWarning($"Could not claim character '{character1}' in {logPlace1} due to cooldown. Cooldown finishes in {resetTime}.");

                    await _replySender.SendAsync(channel1, ReplyEvent.ClaimFailed, replySubs);

                    return;
                }

                _logger.LogWarning($"Probably claimed character '{character1}' in {logPlace1}, but result could not be determined. Channel is probably busy.");

                if (options.NotifyOnCharacter)
                {
                    _notification.SendToast($"Probably claimed character '{character1}' in {logPlace1}, but result could not be determined.");
                }
            }
        }