All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.twitch4j.chat.events.IRCEventHandler Maven / Gradle / Ivy

package com.github.twitch4j.chat.events;

import com.github.philippheuer.events4j.core.EventManager;
import com.github.twitch4j.chat.TwitchChat;
import com.github.twitch4j.chat.events.channel.*;
import com.github.twitch4j.chat.events.roomstate.*;
import com.github.twitch4j.common.enums.SubscriptionPlan;
import com.github.twitch4j.common.events.domain.EventChannel;
import com.github.twitch4j.common.events.domain.EventUser;
import com.github.twitch4j.common.events.user.PrivateMessageEvent;
import lombok.Getter;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.time.Month;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;

import static com.github.twitch4j.common.util.TwitchUtils.ANONYMOUS_CHEERER;
import static com.github.twitch4j.common.util.TwitchUtils.ANONYMOUS_GIFTER;

/**
 * IRC Event Handler
 *
 * Listens for any irc triggered events and created the corresponding events for the EventDispatcher.
 */
@Getter
@Slf4j
public class IRCEventHandler {

    /**
     * Twitch Client
     */
    private final TwitchChat twitchChat;

    /**
     * Event Manager
     */
    private final EventManager eventManager;

    /**
     * Constructor
     *
     * @param twitchChat The Twitch Chat instance
     */
    public IRCEventHandler(TwitchChat twitchChat) {
        this.twitchChat = twitchChat;
        this.eventManager = twitchChat.getEventManager();

        // register event handlers
        eventManager.onEvent("twitch4j-chat-message-trigger", IRCMessageEvent.class, this::onChannelMessage);
        eventManager.onEvent("twitch4j-chat-whisper-trigger", IRCMessageEvent.class, this::onWhisper);
        eventManager.onEvent("twitch4j-chat-bits-badge-trigger", IRCMessageEvent.class, this::onBitsBadgeTier);
        eventManager.onEvent("twitch4j-chat-cheer-trigger", IRCMessageEvent.class, this::onChannelCheer);
        eventManager.onEvent("twitch4j-chat-sub-trigger", IRCMessageEvent.class, this::onChannelSubscription);
        eventManager.onEvent("twitch4j-chat-clearchat-trigger", IRCMessageEvent.class, this::onClearChat);
        eventManager.onEvent("twitch4j-chat-join-trigger", IRCMessageEvent.class, this::onChannnelClientJoinEvent);
        eventManager.onEvent("twitch4j-chat-leave-trigger", IRCMessageEvent.class, this::onChannnelClientLeaveEvent);
        eventManager.onEvent("twitch4j-chat-mod-trigger", IRCMessageEvent.class, this::onChannelModChange);
        eventManager.onEvent("twitch4j-chat-notice-trigger", IRCMessageEvent.class, this::onNoticeEvent);
        eventManager.onEvent("twitch4j-chat-host-on-trigger", IRCMessageEvent.class, this::onHostOnEvent);
        eventManager.onEvent("twitch4j-chat-host-off-trigger", IRCMessageEvent.class, this::onHostOffEvent);
        eventManager.onEvent("twitch4j-chat-list-mods-trigger", IRCMessageEvent.class, this::onListModsEvent);
        eventManager.onEvent("twitch4j-chat-list-vips-trigger", IRCMessageEvent.class, this::onListVipsEvent);
        eventManager.onEvent("twitch4j-chat-roomstate-trigger", IRCMessageEvent.class, this::onChannelState);
        eventManager.onEvent("twitch4j-chat-gift-trigger", IRCMessageEvent.class, this::onGiftReceived);
        eventManager.onEvent("twitch4j-chat-payforward-trigger", IRCMessageEvent.class, this::onPayForward);
        eventManager.onEvent("twitch4j-chat-raid-trigger", IRCMessageEvent.class, this::onRaid);
        eventManager.onEvent("twitch4j-chat-unraid-trigger", IRCMessageEvent.class, this::onUnraid);
        eventManager.onEvent("twitch4j-chat-rewardgift-trigger", IRCMessageEvent.class, this::onRewardGift);
        eventManager.onEvent("twitch4j-chat-ritual-trigger", IRCMessageEvent.class, this::onRitual);
        eventManager.onEvent("twitch4j-chat-delete-trigger", IRCMessageEvent.class, this::onMessageDeleteResponse);
        eventManager.onEvent("twitch4j-chat-userstate-trigger", IRCMessageEvent.class, this::onUserState);
    }

    /**
     * ChatChannel Message Event
     * @param event IRCMessageEvent
     */
    public void onChannelMessage(IRCMessageEvent event) {
        if(event.getCommandType().equals("PRIVMSG")) {
            if(!event.getTags().containsKey("bits") && event.getMessage().isPresent()) {
                // Load Info
                EventChannel channel = event.getChannel();
                EventUser user = event.getUser();

                // Dispatch Event
                if(event.getMessage().get().startsWith("\u0001ACTION ")) {
                    // Action
                    eventManager.publish(new ChannelMessageActionEvent(channel, event, user, event.getMessage().get().substring(8), event.getClientPermissions()));
                } else {
                    // Regular Message
                    eventManager.publish(new ChannelMessageEvent(channel, event, user, event.getMessage().get(), event.getClientPermissions()));
                }
            }
        }
    }

    /**
     * Whisper Event
     * @param event IRCMessageEvent
     */
    public void onWhisper(IRCMessageEvent event) {
        if(event.getCommandType().equals("WHISPER")) {
            // Load Info
            EventUser user = event.getUser();

            // Dispatch Event
            eventManager.publish(new PrivateMessageEvent(user, event.getMessage().get(), event.getClientPermissions()));
        }
    }

    /**
     * ChatChannel Bits Badge Earned Event Parser
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onBitsBadgeTier(IRCMessageEvent event) {
        if ("USERNOTICE".equals(event.getCommandType()) && "bitsbadgetier".equalsIgnoreCase(event.getTags().get("msg-id"))) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();

            String thresholdParam = event.getTags().get("msg-param-threshold");
            int bitsThreshold = thresholdParam != null ? Integer.parseInt(thresholdParam) : -1;

            // Dispatch Event
            eventManager.publish(new BitsBadgeEarnedEvent(channel, user, bitsThreshold));
        }
    }

    /**
     * ChatChannel Cheer (Bits) Event
     * @param event IRCMessageEvent
     */
    public void onChannelCheer(IRCMessageEvent event) {
        if(event.getCommandType().equals("PRIVMSG")) {
            if(event.getTags().containsKey("bits")) {
                // Load Info
                EventChannel channel = event.getChannel();
                EventUser user = event.getUser();
                String message = event.getMessage().orElse("");
                Integer bits = Integer.parseInt(event.getTags().get("bits"));
                int subMonths = event.getSubscriberMonths().orElse(0);
                int subTier = event.getSubscriptionTier().orElse(0);

                // Dispatch Event
                eventManager.publish(new CheerEvent(channel, user != null ? user : ANONYMOUS_CHEERER, message, bits, subMonths, subTier, event.getFlags()));
            }
        }
    }

    /**
     * ChatChannel Subscription Event
     *
     * @param event IRCMessageEvent
     */
    public void onChannelSubscription(IRCMessageEvent event) {
        final String msgId;
        if (event.getCommandType().equals("USERNOTICE") && (msgId = event.getTags().get("msg-id")) != null) {
            EventChannel channel = event.getChannel();

            // Sub
            if (msgId.equalsIgnoreCase("sub") || msgId.equalsIgnoreCase("resub")) {
                // Load Info
                EventUser user = event.getUser();
                String subPlan = event.getTagValue("msg-param-sub-plan").get();
                int cumulativeMonths = event.getTags().containsKey("msg-param-cumulative-months") ? Integer.parseInt(event.getTags().get("msg-param-cumulative-months")) : 0;
                //according to the Twitch docs, msg-param-months is used only for giftsubs, which are handled below

                // twitch sometimes returns 0 months for new subs
                if (cumulativeMonths == 0) {
                    cumulativeMonths = 1;
                }

                // check user's sub streak
                // Twitch API specifies that 0 is returned if the user chooses not to share their streak
                Integer streak = event.getTags().containsKey("msg-param-streak-months") ? Integer.parseInt(event.getTags().get("msg-param-streak-months")) : 0;

                // Dispatch Event
                eventManager.publish(new SubscriptionEvent(channel, user, subPlan, event.getMessage(), cumulativeMonths, false, null, streak, null, event.getFlags()));
            }
            // Receive Gifted Sub
            else if (msgId.equalsIgnoreCase("subgift") || msgId.equalsIgnoreCase("anonsubgift")) {
                // Load Info
                EventUser user = new EventUser(event.getTagValue("msg-param-recipient-id").get(), event.getTagValue("msg-param-recipient-user-name").get());
                EventUser giftedBy = event.getUser();
                String subPlan = event.getTagValue("msg-param-sub-plan").get();
                int subStreak = event.getTags().containsKey("msg-param-months") ? Integer.parseInt(event.getTags().get("msg-param-months")) : 1;

                // twitch sometimes returns 0 months for new subs
                if (subStreak == 0) {
                    subStreak = 1;
                }

                // Handle multi-month gifts
                String giftMonthsParam = event.getTags().get("msg-param-gift-months");
                int giftMonths = giftMonthsParam != null ? Integer.parseInt(giftMonthsParam) : 1;

                // Dispatch Event
                eventManager.publish(new SubscriptionEvent(channel, user, subPlan, event.getMessage(), subStreak, true, giftedBy != null ? giftedBy : ANONYMOUS_GIFTER, 0, giftMonths, event.getFlags()));
            }
            // Gift X Subs
            else if (msgId.equalsIgnoreCase("submysterygift") || msgId.equalsIgnoreCase("anonsubmysterygift")) {
                // Load Info
                EventUser user = event.getUser();
                String subPlan = event.getTagValue("msg-param-sub-plan").get();
                Integer subsGifted = (event.getTags().containsKey("msg-param-mass-gift-count")) ? Integer.parseInt(event.getTags().get("msg-param-mass-gift-count")) : 0;
                Integer subsGiftedTotal = (event.getTags().containsKey("msg-param-sender-count")) ? Integer.parseInt(event.getTags().get("msg-param-sender-count")) : 0;

                // Dispatch Event
                eventManager.publish(new GiftSubscriptionsEvent(channel, user != null ? user : ANONYMOUS_GIFTER, subPlan, subsGifted, subsGiftedTotal));
            }
            // Upgrading from a gifted sub
            else if (msgId.equalsIgnoreCase("giftpaidupgrade") || msgId.equalsIgnoreCase("anongiftpaidupgrade")) {
                // Load Info
                EventUser user = event.getUser();
                String promoName = event.getTagValue("msg-param-promo-name").orElse(null);
                String giftTotalParam = event.getTags().get("msg-param-promo-gift-total");
                Integer giftTotal = giftTotalParam != null ? Integer.parseInt(giftTotalParam) : null;
                String senderLogin = event.getTagValue("msg-param-sender-login").orElse(null);
                String senderName = event.getTagValue("msg-param-sender-name").orElse(null);

                // Dispatch Event
                eventManager.publish(new GiftSubUpgradeEvent(channel, user, promoName, giftTotal, senderLogin, senderName));
            }
            // Upgrading from a Prime sub to a normal one
            else if (msgId.equalsIgnoreCase("primepaidupgrade")) {
                // Load Info
                EventUser user = event.getUser();
                SubscriptionPlan subPlan = event.getTagValue("msg-param-sub-plan").map(SubscriptionPlan::fromString).orElse(null);

                // Dispatch Event
                eventManager.publish(new PrimeSubUpgradeEvent(channel, user, subPlan));
            }
            // Extend Subscription
            else if (msgId.equalsIgnoreCase("extendsub")) {
                // Load Info
                EventUser user = event.getUser();
                SubscriptionPlan subPlan = event.getTagValue("msg-param-sub-plan").map(SubscriptionPlan::fromString).orElse(null);

                String cumMonthsParam = event.getTags().get("msg-param-cumulative-months");
                int cumulativeMonths = cumMonthsParam != null ? Math.max(Integer.parseInt(cumMonthsParam), 1) : 1;

                String endMonthParam = event.getTags().get("msg-param-sub-benefit-end-month");
                Month endMonth = endMonthParam != null ? Month.of(Integer.parseInt(endMonthParam)) : null;

                // Dispatch Event
                eventManager.publish(new ExtendSubscriptionEvent(channel, user, subPlan, cumulativeMonths, endMonth));
            }
        }
    }

    /**
     * ChatChannel Prime Community Gift Event Parser: user receives a gift from a prime member
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onGiftReceived(IRCMessageEvent event) {
        if ("USERNOTICE".equals(event.getCommandType()) && "primecommunitygiftreceived".equalsIgnoreCase(event.getTags().get("msg-id"))) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();
            String giftName = event.getTagValue("msg-param-gift-name").orElse(null);
            String recipientName = event.getTagValue("msg-param-recipient").orElse(null);

            // Dispatch Event
            eventManager.publish(new PrimeGiftReceivedEvent(channel, user, giftName, recipientName));
        }
    }

    /**
     * ChatChannel Pay Forward Event Parser: user pays forward a gift they previously received
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onPayForward(IRCMessageEvent event) {
        String msgId;
        if ("USERNOTICE".equals(event.getCommandType()) && (msgId = event.getTags().get("msg-id")) != null
            && (msgId.equalsIgnoreCase("standardpayforward") || msgId.equalsIgnoreCase("communitypayforward"))) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();

            // Present for both standard & community when not anonymous
            String gifterId = event.getTagValue("msg-param-prior-gifter-id").orElse(null);
            String gifterName = gifterId != null
                ? event.getTagValue("msg-param-prior-gifter-user-name").orElseGet(() -> event.getTagValue("msg-param-prior-gifter-display-name").orElse(null))
                : null;
            EventUser gifter = gifterId != null ? new EventUser(gifterId, gifterName) : null;

            // Only present for standard
            String recipientId = msgId.charAt(0) == 's' ? event.getTagValue("msg-param-recipient-id").orElse(null) : null;
            String recipientName = recipientId != null
                ? event.getTagValue("msg-param-recipient-user-name").orElseGet(() -> event.getTagValue("msg-param-recipient-display-name").orElse(null))
                : null;
            EventUser recipient = recipientId != null ? new EventUser(recipientId, recipientName) : null;

            // Dispatch Event
            eventManager.publish(new PayForwardEvent(channel, user, gifter, recipient));
        }
    }

    /**
     * ChatChannel Raid Event (receiving)
     * @param event IRCMessageEvent
     */
    public void onRaid(IRCMessageEvent event) {
        if (event.getCommandType().equals("USERNOTICE") && event.getTags().containsKey("msg-id") && event.getTags().get("msg-id").equalsIgnoreCase("raid")) {
            EventChannel channel = event.getChannel();
            EventUser raider = event.getUser();
            Integer viewers;
            try {
                viewers = Integer.parseInt(event.getTags().get("msg-param-viewerCount"));
            }
            catch(NumberFormatException ex) {
                viewers = 0;
            }
            eventManager.publish(new RaidEvent(channel, raider, viewers));
        }
    }

    /**
     * ChatChannel Unraid Parser: raid cancellation
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onUnraid(IRCMessageEvent event) {
        if ("USERNOTICE".equals(event.getCommandType()) && "unraid".equalsIgnoreCase(event.getTags().get("msg-id"))) {
            eventManager.publish(new RaidCancellationEvent(event.getChannel()));
        }
    }

    /**
     * ChatChannel Reward Gift Event Parser: monetary event triggered emotes to be shared
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onRewardGift(IRCMessageEvent event) {
        if ("USERNOTICE".equals(event.getCommandType()) && "rewardgift".equalsIgnoreCase(event.getTags().get("msg-id"))) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();
            String domain = event.getTagValue("msg-param-domain").orElse(null);
            String triggerType = event.getTagValue("msg-param-trigger-type").orElse(null);

            String selectedCountParam = event.getTags().get("msg-param-selected-count");
            Integer selectedCount = selectedCountParam != null ? Integer.parseInt(selectedCountParam) : null;

            String totalRewardCountParam = event.getTags().get("msg-param-total-reward-count");
            Integer totalRewardCount = totalRewardCountParam != null ? Integer.parseInt(totalRewardCountParam) : null;

            String triggerAmountParam = event.getTags().get("msg-param-trigger-amount");
            Integer triggerAmount = triggerAmountParam != null ? Integer.parseInt(triggerAmountParam) : null;

            // Dispatch Event
            eventManager.publish(new RewardGiftEvent(channel, user, domain, triggerType, selectedCount, totalRewardCount, triggerAmount));
        }
    }

    /**
     * ChatChannel Ritual Event Parser: celebration of a shared viewer milestone
     *
     * @param event the {@link IRCMessageEvent} to be checked
     */
    public void onRitual(IRCMessageEvent event) {
        if ("USERNOTICE".equals(event.getCommandType()) && "ritual".equalsIgnoreCase(event.getTags().get("msg-id"))) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();
            String ritualName = event.getTagValue("msg-param-ritual-name").orElse(null);

            // Dispatch Event
            eventManager.publish(new RitualEvent(channel, user, ritualName));
        }
    }

    /**
     * ChatChannel clearing chat, timeouting or banning user Event
     * @param event IRCMessageEvent
     */
    public void onClearChat(IRCMessageEvent event) {
        if (event.getCommandType().equals("CLEARCHAT")) {
            EventChannel channel = event.getChannel();
            if (event.getTags().containsKey("target-user-id")) { // ban or timeout
                if (event.getTags().containsKey("ban-duration")) { // timeout
                    // Load Info
                    EventUser user = event.getTargetUser();
                    Integer duration = Integer.parseInt(event.getTagValue("ban-duration").get());
                    String banReason = event.getTags().get("ban-reason") != null ? event.getTags().get("ban-reason").toString() : "";
                    banReason = banReason.replaceAll("\\\\s", " ");
                    UserTimeoutEvent timeoutEvent = new UserTimeoutEvent(channel, user, duration, banReason);

                    // Dispatch Event
                    eventManager.publish(timeoutEvent);
                } else { // ban
                    // Load Info
                    EventUser user = event.getTargetUser();
                    String banReason = event.getTagValue("ban-reason").orElse("");
                    banReason = banReason.replaceAll("\\\\s", " ");
                    UserBanEvent banEvent = new UserBanEvent(channel, user, banReason);

                    // Dispatch Event
                    eventManager.publish(banEvent);
                }
            } else { // Clear chat event
                eventManager.publish(new ClearChatEvent(channel));
            }
        }
    }

    /**
     * User Joins ChatChannel Event
     * @param event IRCMessageEvent
     */
    public void onChannnelClientJoinEvent(IRCMessageEvent event) {
        if(event.getCommandType().equals("JOIN") && event.getChannelName().isPresent() && event.getClientName().isPresent()) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();

            // Dispatch Event
            if (channel != null && user != null) {
                eventManager.publish(new ChannelJoinEvent(channel, user));
            }
        }
    }

    /**
     * User Leaves ChatChannel Event
     * @param event IRCMessageEvent
     */
    public void onChannnelClientLeaveEvent(IRCMessageEvent event) {
        if(event.getCommandType().equals("PART") && event.getChannelName().isPresent() && event.getClientName().isPresent()) {
            // Load Info
            EventChannel channel = event.getChannel();
            EventUser user = event.getUser();

            // Dispatch Event
            if (channel != null && user != null) {
                eventManager.publish(new ChannelLeaveEvent(channel, user));
            }
        }
    }

    /**
     * Mod Status Change Event
     * @param event IRCMessageEvent
     */
    public void onChannelModChange(IRCMessageEvent event) {
        if(event.getCommandType().equals("MODE") && event.getPayload().isPresent()) {
            // Receiving Mod Status
            if(event.getPayload().get().substring(1).startsWith("o")) {
                // Load Info
                EventChannel channel = event.getChannel();
                EventUser user = new EventUser(null, event.getPayload().get().substring(3));

                // Dispatch Event
                eventManager.publish(new ChannelModEvent(channel, user, event.getPayload().get().startsWith("+")));
            }
        }
    }

    public void onNoticeEvent(IRCMessageEvent event) {
        if (event.getCommandType().equals("NOTICE")) {
            EventChannel channel = event.getChannel();
            String messageId = event.getTagValue("msg-id").get();
            String message = event.getMessage().orElse(null); // can be null, ie. bad_delete_message_error

            eventManager.publish(new ChannelNoticeEvent(channel, messageId, message));
        }
    }

    public void onHostOnEvent(IRCMessageEvent event) {
        if (event.getCommandType().equals("NOTICE")) {
            EventChannel channel = event.getChannel();
            String messageId = event.getTagValue("msg-id").get();

            if(messageId.equals("host_on")) {
                String message = event.getMessage().get();
                String targetChannelName = message.substring(12, message.length() - 1);
                EventChannel targetChannel = new EventChannel(null, targetChannelName);
                eventManager.publish(new HostOnEvent(channel, targetChannel));
            }
        }
    }

    public void onHostOffEvent(IRCMessageEvent event) {
        if (event.getCommandType().equals("NOTICE")) {
            EventChannel channel = event.getChannel();
            String messageId = event.getTagValue("msg-id").get();

            if(messageId.equals("host_off")) {
                eventManager.publish(new HostOffEvent(channel));
            }
        }
    }

    public void onListModsEvent(IRCMessageEvent event) {
        if ("NOTICE".equals(event.getCommandType()) && event.getTagValue("msg-id").filter(s -> s.equals("room_mods") || s.equals("no_mods")).isPresent()) {
            List names = extractItemsFromDelimitedList(event.getMessage(), "The moderators of this channel are: ", ", ");
            eventManager.publish(new ListModsEvent(event.getChannel(), names));
        }
    }

    public void onListVipsEvent(IRCMessageEvent event) {
        if ("NOTICE".equals(event.getCommandType()) && event.getTagValue("msg-id").filter(s -> s.equals("vips_success") || s.equals("no_vips")).isPresent()) {
            List names = extractItemsFromDelimitedList(event.getMessage(), "The VIPs of this channel are: ", ", ");
            eventManager.publish(new ListVipsEvent(event.getChannel(), names));
        }
    }

    public void onChannelState(IRCMessageEvent event) {
        if (event.getCommandType().equals("ROOMSTATE")) {
            // getting Status on channel
            EventChannel channel = event.getChannel();
            Map states = new HashMap<>();
            if (event.getTags().size() > 2) {
                event.getTags().forEach((k, v) -> {
                    switch (k) {
                        case "broadcaster-lang":
                            Locale locale = v != null ? Locale.forLanguageTag(v) : null;
                            states.put(ChannelStateEvent.ChannelState.BROADCAST_LANG, locale);
                            eventManager.publish(new BroadcasterLanguageEvent(channel, locale));
                            break;
                        case "emote-only":
                            boolean eoActive = "1".equals(v);
                            states.put(ChannelStateEvent.ChannelState.EMOTE, eoActive);
                            eventManager.publish(new EmoteOnlyEvent(channel, eoActive));
                            break;
                        case "followers-only":
                            long followDelay = Long.parseLong(v);
                            states.put(ChannelStateEvent.ChannelState.FOLLOWERS, followDelay);
                            eventManager.publish(new FollowersOnlyEvent(channel, followDelay));
                            break;
                        case "r9k":
                            boolean uniqActive = "1".equals(v);
                            states.put(ChannelStateEvent.ChannelState.R9K, uniqActive);
                            eventManager.publish(new Robot9000Event(channel, uniqActive));
                            break;
                        case "slow":
                            long slowDelay = Long.parseLong(v);
                            states.put(ChannelStateEvent.ChannelState.SLOW, slowDelay);
                            eventManager.publish(new SlowModeEvent(channel, slowDelay));
                            break;
                        case "subs-only":
                            boolean subActive = "1".equals(v);
                            states.put(ChannelStateEvent.ChannelState.SUBSCRIBERS, subActive);
                            eventManager.publish(new SubscribersOnlyEvent(channel, subActive));
                            break;
                        default:
                            break;
                    }
                });
            }
            eventManager.publish(new ChannelStateEvent(channel, states));
        }
    }

    public void onMessageDeleteResponse(IRCMessageEvent event) {
        if (event.getCommandType().equals("NOTICE")) {
            EventChannel channel = event.getChannel();
            String messageId = event.getTagValue("msg-id").get();

            if (messageId.equals("delete_message_success")) {
                eventManager.publish(new MessageDeleteSuccess(channel));
            } else if (messageId.equals("bad_delete_message_error")) {
                eventManager.publish(new MessageDeleteError(channel));
                log.warn("Failed to delete a message in {}!", channel.getName());
            }
        }
    }

    public void onUserState(IRCMessageEvent event) {
        if (event.getCommandType().equals("USERSTATE")) {
            eventManager.publish(new UserStateEvent(event));
        }
    }

    @NonNull
    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
    private static List extractItemsFromDelimitedList(@NonNull Optional message, @NonNull String prefix, @NonNull String delim) {
        return message.filter(s -> s.startsWith(prefix))
            .map(s -> s.substring(prefix.length()))
            .map(s -> s.charAt(s.length() - 1) == '.' ? s.substring(0, s.length() - 1) : s) // remove trailing period if present
            .map(s -> StringUtils.split(s, delim))
            .map(Arrays::asList)
            .map(Collections::unmodifiableList)
            .orElse(Collections.emptyList());
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy