+ @Subscribe
+ public void channelNotJoined(ChannelNotJoined channelNotJoined) {
+ Optional<Network> network = getNetwork(channelNotJoined.connection());
+ if (!network.isPresent()) {
+ return;
+ }
+
+ Optional<Channel> channel = getChannel(network.get(), channelNotJoined.channel());
+ if (!channel.isPresent()) {
+ eventBus.post(new GenericMessage(format("Could not join %s but didn’t try to join, either.", channel.get())));
+ return;
+ }
+
+ /* remove all bots for this channel, we might have been kicked. */
+ Collection<Bot> botsToRemove = networkBots.row(network.get())
+ .values().stream()
+ .filter(bot -> bot.channel()
+ .equalsIgnoreCase(channel.get().name()))
+ .collect(Collectors.toSet());
+ botsToRemove.stream()
+ .forEach(bot -> networkBots.row(network.get())
+ .remove(bot.name()));
+
+ if (channelNotJoined.reason() == registeredNicknamesOnly) {
+ channels.remove(channel.get());
+ eventBus.post(new GenericMessage(
+ format("Not trying to join %s anymore.", channel.get())));
+ return;
+ }
+ if (channelNotJoined.reason() == banned) {
+ channelBanManager.ban(channel.get());
+ eventBus.post(new GenericMessage(
+ format("Banned from %s, suspending join for a day.",
+ channel.get())));
+ return;
+ }
+
+ eventBus.post(new GenericMessage(
+ format("Could not join %s: %s", channelNotJoined.channel(),
+ channelNotJoined.reason())));
+ }
+
+ /**
+ * Removes bots that leave a channel, or channels when it’s us that’s leaving.
+ *
+ * @param channelLeft
+ * The channel left event
+ */
+ @Subscribe
+ public void channelLeft(ChannelLeft channelLeft) {
+ Optional<Network> network = getNetwork(channelLeft.connection());
+ if (!network.isPresent()) {
+ return;
+ }
+
+ Bot bot = networkBots.get(network.get(), channelLeft.client().nick().get());
+ if (bot == null) {
+ /* maybe it was us? */
+ if (channelLeft.connection().isSource(channelLeft.client())) {
+ Optional<Channel> channel = getChannel(network.get(), channelLeft.channel());
+ if (!channel.isPresent()) {
+ /* maybe it was an extra channel? */
+ channel = getExtraChannel(network.get(), channelLeft.channel());
+ if (!channel.isPresent()) {
+ /* okay, whatever. */
+ return;
+ }
+
+ extraChannels.remove(channel);
+ } else {
+ channels.remove(channel.get());
+ }
+
+ eventBus.post(new GenericMessage(String.format("Left Channel %s on %s.", channel.get().name(), channel.get().network().name())));
+ }
+
+ return;
+ }
+
+ networkBots.remove(network.get(), channelLeft.client().nick().get());
+ }
+
+ @Subscribe
+ public void kickedFromChannel(KickedFromChannel kickedFromChannel) {
+ Optional<Network> network = getNetwork(kickedFromChannel.connection());
+ if (!network.isPresent()) {
+ return;
+ }
+
+ /* have we been kicked? */
+ if (nicknameMatchesConnection(kickedFromChannel.connection(), kickedFromChannel.kickee())) {
+ Optional<Channel> channel = getChannel(network.get(), kickedFromChannel.channel());
+ if (!channel.isPresent()) {
+ /* maybe it was an extra channel? */
+ channel = getExtraChannel(network.get(), kickedFromChannel.channel());
+ if (!channel.isPresent()) {
+ /* okay, whatever. */
+ return;
+ }
+
+ extraChannels.remove(channel);
+ } else {
+ channels.remove(channel.get());
+ }
+ eventBus.post(new GenericMessage(format(
+ "Kicked from %s by %s: %s",
+ kickedFromChannel.channel(),
+ kickedFromChannel.kicker(),
+ kickedFromChannel.reason().or("<unknown>")
+ )));
+ }
+ }
+
+ private boolean nicknameMatchesConnection(Connection connection, String nickname) {
+ return connection.nickname().equalsIgnoreCase(nickname);
+ }
+
+ /**
+ * Removes a client (which may be a bot) from the table of known bots.
+ *
+ * @param clientQuit
+ * The client quit event
+ */
+ @Subscribe
+ public void clientQuit(ClientQuit clientQuit) {
+ Optional<Network> network = getNetwork(clientQuit.connection());
+ if (!network.isPresent()) {
+ return;
+ }
+
+ networkBots.remove(network.get(), clientQuit.client().nick().get());
+ }
+
+ /**
+ * If the nickname of a bit changes, remove it from the old name and store it
+ * under the new name.
+ *
+ * @param nicknameChanged
+ * The nickname changed event
+ */
+ @Subscribe
+ public void nicknameChanged(NicknameChanged nicknameChanged) {
+ Optional<Network> network = getNetwork(nicknameChanged.connection());
+ if (!network.isPresent()) {
+ return;
+ }
+
+ Bot bot = networkBots.remove(network.get(), nicknameChanged.client().nick().get());
+ if (bot == null) {
+ return;
+ }
+
+ networkBots.put(network.get(), nicknameChanged.newNickname(), bot);
+ }
+