async Task HandleMudaeMessageAsync(SocketUserMessage message) { if (!message.Embeds.Any()) { return; } var guild = ((IGuildChannel)message.Channel).Guild; var embed = message.Embeds.First(); // character must not belong to another user if (embed.Footer.HasValue && embed.Footer.Value.Text.StartsWith("Belongs to", StringComparison.OrdinalIgnoreCase)) { return; } // if (!embed.Author.HasValue || embed.Author.Value.IconUrl != null) { return; } var character = embed.Author.Value.Name.Trim().ToLowerInvariant(); var anime = embed.Description.Split('\n')[0].Trim().ToLowerInvariant(); // matching var matched = false; matched |= _config.WishedCharacterRegex?.IsMatch(character) ?? false; matched |= _config.WishedAnimeRegex?.IsMatch(anime) ?? false; // ensure we can claim right now if (matched) { var state = _state.Get(guild.Id); if (!state.CanClaim && DateTime.Now < state.ClaimReset) { Log.Warning($"{guild} {message.Channel}: Found character '{character}' but cannot claim it due to cooldown."); return; } } if (matched) { Log.Warning($"{guild} {message.Channel}: Found character '{character}', trying marriage."); // reactions may not have been attached when we received this message // remember this message so we can attach an appropriate reaction later when we receive it _claimQueue[message.Id] = message; } else { Log.Info($"{guild} {message.Channel}: Ignored character '{character}', not wished."); } }
async Task RunRollAsync(SocketGuild guild, CancellationToken cancellationToken = default) { while (!cancellationToken.IsCancellationRequested) { var state = _state.Get(guild.Id); var interval = _config.RollIntervalOverride; if (interval == null) { if (!_config.RollEnabled || state.RollsLeft <= 0) { await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken); continue; } interval = new TimeSpan((state.RollsReset - DateTime.Now).Ticks / state.RollsLeft); } foreach (var channel in guild.TextChannels) { if (!_config.BotChannelIds.Contains(channel.Id)) { continue; } using (channel.EnterTypingState()) { await Task.Delay(_config.RollTypingDelay, cancellationToken); try { await channel.SendMessageAsync(_config.RollCommand); --state.RollsLeft; Log.Debug($"{channel.Guild} #{channel}: Rolled '{_config.RollCommand}'."); } catch (Exception e) { Log.Warning($"{channel.Guild} #{channel}: Could not send roll command '{_config.RollCommand}'.", e); } } break; } if (interval < TimeSpan.FromSeconds(5)) { interval = TimeSpan.FromSeconds(5); } await Task.Delay(interval.Value, cancellationToken); } }
async Task HandleReactionAsync(Cacheable <IUserMessage, ulong> cacheable, ISocketMessageChannel channel, SocketReaction reaction) { if (!_config.ClaimEnabled) { return; } if (!(channel is IGuildChannel guildChannel)) { return; } // channel must be enabled for claiming if (!_config.BotChannelIds.Contains(channel.Id)) { return; } // retrieve message if (!_messageCache.TryGetValue(reaction.MessageId, out var message)) { return; } // reactor must be mudae var user = reaction.User.IsSpecified ? reaction.User.Value : _client.GetUser(reaction.UserId); if (user == null || !MudaeInfo.IsMudae(user)) { return; } // reaction must be kakera if (!_kakeraMap.TryGetValue(reaction.Emote.Name, out var kakera)) { return; } // kakera must be configured to be claimed if (!_config.KakeraTargets.Contains(kakera)) { return; } // must have enough kakera power to claim this kakera var state = _state.Get(guildChannel.GuildId); if (!state.CanKakera) { return; } // claim kakera await Task.Delay(_config.KakeraClaimDelay); await message.AddReactionAsync(reaction.Emote); // update state state.KakeraPower -= state.KakeraConsumption; }
async Task HandleMudaeMessageAsync(IUserMessage message) { if (!message.Embeds.Any()) { return; } var guild = ((IGuildChannel)message.Channel).Guild; var embed = message.Embeds.First(); if (embed.Footer.HasValue) { // character must not belong to another user if (embed.Footer.Value.Text.StartsWith("Belongs to", StringComparison.OrdinalIgnoreCase)) { return; } // message must not be $im if (_imFooterRegex.IsMatch(embed.Footer.Value.Text)) { return; } } // if (!embed.Author.HasValue || embed.Author.Value.IconUrl != null) { return; } var description = embed.Description.Split('\n'); var character = embed.Author.Value.Name.Trim().ToLowerInvariant(); var anime = description[0].Trim().ToLowerInvariant(); var KakeraValue = 0; //if length >= 2 then description includes additional info if (description.Length >= 2) { //46983... is emoji symbol if (description[description.Length - 1].Contains("469835869059153940")) { String KakeraValueString = new String(description[description.Length - 1].SkipWhile(c => !Char.IsDigit(c)).TakeWhile(Char.IsDigit).ToArray()); KakeraValue = Convert.ToInt32(KakeraValueString); } } // matching by character and name var matched = false; var kakeraThreshold = _config.KakeraThreshold; matched |= _config.WishedCharacterRegex?.IsMatch(character) ?? false; matched |= _config.WishedAnimeRegex?.IsMatch(anime) ?? false; // matching by wishlist if (message.Content.StartsWith("Wished by")) { matched |= message.GetUserIds().Any(_config.ClaimWishlistUserIds.Contains); } if (matched) { var state = _state.Get(guild.Id); // ensure we can claim right now if (!state.CanClaim && DateTime.Now < state.ClaimReset) { Log.Warning($"{guild} {message.Channel}: Found character '{character}' but cannot claim it due to cooldown."); return; } //check and see if character's kakera value is at or above threshold if (KakeraValue >= kakeraThreshold) { Log.Warning($"{guild} {message.Channel}: Found character '{character}', trying marriage."); } else { Log.Warning($"{guild} {message.Channel}: Found character '{character}' but cannot claim it due to character's kakera value '{KakeraValue}' not greater than or equal to threshold. '{kakeraThreshold}'"); return; } // reactions may not have been attached when we received this message // remember this message so we can attach an appropriate reaction later when we receive it _claimQueue[message.Id] = new ClaimQueueItem { Message = message, Character = new CharacterInfo(character, anime), Measure = new MeasureContext() }; } else { Log.Info($"{guild} #{message.Channel}: Ignored character '{character}', not wished."); } }