using Serilog; using TwitchChatTTS.Bus; using TwitchChatTTS.Twitch.Redemptions; using TwitchChatTTS.Twitch.Socket.Messages; namespace TwitchChatTTS.Twitch.Socket.Handlers { public class ChannelCustomRedemptionHandler : ITwitchSocketHandler { public string Name => "channel.channel_points_custom_reward_redemption.add"; private readonly IDictionary _messages; private readonly IRedemptionManager _redemptionManager; private readonly ServiceBusCentral _bus; private readonly ILogger _logger; public ChannelCustomRedemptionHandler( IRedemptionManager redemptionManager, ServiceBusCentral bus, ILogger logger ) { _messages = new Dictionary(); _redemptionManager = redemptionManager; _bus = bus; _logger = logger; var topic = _bus.GetTopic("chat_message_redemption"); topic.Subscribe((d) => { var message = d.Value as ChannelChatMessage; if (message != null && !string.IsNullOrEmpty(message.ChannelPointsCustomRewardId)) { _messages.Add(message.ChannelPointsCustomRewardId, message); Task.Run(async () => { await Task.Delay(TimeSpan.FromMilliseconds(5000)); _messages.Remove(message.ChannelPointsCustomRewardId); }); } }); } public async Task Execute(TwitchWebsocketClient sender, object data) { if (data is not ChannelCustomRedemptionMessage message) return; _logger.Information($"Channel Point Reward Redeemed [redeem: {message.Reward.Title}][redeem id: {message.Reward.Id}][transaction: {message.Id}]"); try { var actions = _redemptionManager.Get(message.Reward.Id); if (!actions.Any()) { _logger.Debug($"No redeemable actions for this redeem was found [redeem: {message.Reward.Title}][redeem id: {message.Reward.Id}][transaction: {message.Id}]"); return; } _logger.Debug($"Found {actions.Count()} actions for this Twitch channel point redemption [redeem: {message.Reward.Title}][redeem id: {message.Reward.Id}][transaction: {message.Id}]"); ChannelChatMessage? chatMessage = null; if (actions.Any(a => a.HasMessage)) { if (!_messages.TryGetValue(message.Reward.Id, out chatMessage)) { DateTime start = DateTime.Now; _logger.Debug("Waiting on redemption message..."); while (DateTime.Now - start < TimeSpan.FromMilliseconds(1000) && !_messages.ContainsKey(message.Reward.Id)) await Task.Delay(100); if (!_messages.TryGetValue(message.Reward.Id, out chatMessage)) { _logger.Warning("Chat message was not found within a second of the channel redemption being received. Skipping all redeemable actions."); return; } } if (chatMessage != null) _logger.Information($"Linked redemption to chat message [redemption id: {message.Reward.Id}][message id: {chatMessage.MessageId}]."); } foreach (var action in actions) try { await _redemptionManager.Execute(action, message.UserName, long.Parse(message.UserId), message.UserInput); } catch (Exception ex) { _logger.Error(ex, $"Failed to execute redeemable action [action: {action.Name}][action type: {action.Type}][redeem: {message.Reward.Title}][redeem id: {message.Reward.Id}][transaction: {message.Id}]"); } } catch (Exception ex) { _logger.Error(ex, $"Failed to fetch the redeemable actions for a redemption [redeem: {message.Reward.Title}][redeem id: {message.Reward.Id}][transaction: {message.Id}]"); } } } }