X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=src%2Fmain%2Fjava%2Fnet%2Fpterodactylus%2Fxdcc%2Fcore%2FCore.java;h=9d5dcb7a9877c7bf63805d599a03ee652e137fc6;hb=db7e9612fa189cee9f4b9086e00d87c4d6c58bbf;hp=251310e4a2c4e56393bc5b714f63df4231ca8837;hpb=6b97ecef1be59f3746e859dfb4a65f2195a6ee90;p=xudocci.git diff --git a/src/main/java/net/pterodactylus/xdcc/core/Core.java b/src/main/java/net/pterodactylus/xdcc/core/Core.java index 251310e..9d5dcb7 100644 --- a/src/main/java/net/pterodactylus/xdcc/core/Core.java +++ b/src/main/java/net/pterodactylus/xdcc/core/Core.java @@ -24,9 +24,11 @@ import java.io.IOException; import java.io.OutputStream; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; @@ -37,11 +39,14 @@ import net.pterodactylus.irc.event.ChannelJoined; import net.pterodactylus.irc.event.ChannelLeft; import net.pterodactylus.irc.event.ChannelMessageReceived; import net.pterodactylus.irc.event.ClientQuit; +import net.pterodactylus.irc.event.ConnectionClosed; import net.pterodactylus.irc.event.ConnectionEstablished; import net.pterodactylus.irc.event.DccAcceptReceived; import net.pterodactylus.irc.event.DccDownloadFailed; import net.pterodactylus.irc.event.DccDownloadFinished; import net.pterodactylus.irc.event.DccSendReceived; +import net.pterodactylus.irc.event.NicknameChanged; +import net.pterodactylus.irc.event.PrivateNoticeReceived; import net.pterodactylus.irc.event.PrivateMessageReceived; import net.pterodactylus.irc.util.MessageCleaner; import net.pterodactylus.irc.util.RandomNickname; @@ -62,6 +67,7 @@ import net.pterodactylus.xdcc.data.Server; import com.google.common.base.Optional; import com.google.common.collect.HashBasedTable; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Lists; import com.google.common.collect.Maps; @@ -70,7 +76,7 @@ import com.google.common.collect.Table; import com.google.common.eventbus.EventBus; import com.google.common.eventbus.Subscribe; import com.google.common.io.Closeables; -import com.google.common.util.concurrent.AbstractIdleService; +import com.google.common.util.concurrent.AbstractExecutionThreadService; import com.google.inject.Inject; /** @@ -78,7 +84,7 @@ import com.google.inject.Inject; * * @author David ‘Bombe’ Roden */ -public class Core extends AbstractIdleService { +public class Core extends AbstractExecutionThreadService { /** The logger. */ private static final Logger logger = Logger.getLogger(Core.class.getName()); @@ -226,15 +232,7 @@ public class Core extends AbstractIdleService { protected void startUp() { for (Channel channel : channels) { logger.info(String.format("Connecting to Channel %s on Network %s…", channel.name(), channel.network().name())); - if (!networkConnections.containsKey(channel.network())) { - /* select a random server. */ - List servers = Lists.newArrayList(channel.network().servers()); - Server server = servers.get((int) (Math.random() * servers.size())); - Connection connection = new ConnectionBuilder(eventBus).connect(server.hostname()).port(server.unencryptedPorts().iterator().next()).build(); - connection.username(RandomNickname.get()).realName(RandomNickname.get()); - networkConnections.put(channel.network(), connection); - connection.start(); - } + connectNetwork(channel.network()); } /* notify listeners. */ @@ -242,10 +240,62 @@ public class Core extends AbstractIdleService { } @Override + protected void run() throws Exception { + while (isRunning()) { + try { + Thread.sleep(TimeUnit.MINUTES.toMillis(1)); + } catch (InterruptedException ie1) { + /* ignore. */ + } + + /* find channels that should be monitored but are not. */ + for (Channel channel : channels) { + if (joinedChannels.contains(channel)) { + continue; + } + + connectNetwork(channel.network()); + Connection connection = networkConnections.get(channel.network()); + if (connection.established()) { + eventBus.post(new GenericMessage(String.format("Trying to join %s on %s.", channel.name(), channel.network().name()))); + connection.joinChannel(channel.name()); + } + } + } + } + + @Override protected void shutDown() { } // + // PRIVATE METHODS + // + + /** + * Starts a new connection for the given network if no such connection exists + * already. + * + * @param network + * The network to connect to + */ + private void connectNetwork(Network network) { + if (!networkConnections.containsKey(network)) { + /* select a random server. */ + List servers = Lists.newArrayList(network.servers()); + if (servers.isEmpty()) { + eventBus.post(new GenericError(String.format("Network %s does not have any servers.", network.name()))); + return; + } + Server server = servers.get((int) (Math.random() * servers.size())); + Connection connection = new ConnectionBuilder(eventBus).connect(server.hostname()).port(server.unencryptedPorts().iterator().next()).build(); + connection.username(RandomNickname.get()).realName(RandomNickname.get()); + networkConnections.put(network, connection); + connection.start(); + } + } + + // // EVENT HANDLERS // @@ -280,6 +330,45 @@ public class Core extends AbstractIdleService { } /** + * Remove all data stored for a network if the connection is closed. + * + * @param connectionClosed + * The connection closed event + */ + @Subscribe + public void connectionClosed(ConnectionClosed connectionClosed) { + Optional network = getNetwork(connectionClosed.connection()); + if (!network.isPresent()) { + return; + } + + /* find all channels that need to be removed. */ + for (Collection channels : ImmutableList.of(joinedChannels, extraChannels)) { + for (Iterator channelIterator = channels.iterator(); channelIterator.hasNext(); ) { + Channel joinedChannel = channelIterator.next(); + if (!joinedChannel.network().equals(network.get())) { + continue; + } + + channelIterator.remove(); + } + } + + /* now remove all bots for that network. */ + Map bots = networkBots.row(network.get()); + int botCount = bots.size(); + int packCount = 0; + for (Bot bot : bots.values()) { + packCount += bot.packs().size(); + } + bots.clear(); + eventBus.post(new GenericMessage(String.format("Network %s disconnected, %d bots removed, %d packs removed.", network.get().name(), botCount, packCount))); + + /* now remove the network. */ + networkConnections.remove(network.get()); + } + + /** * Shows a message when a channel was joined by us. * * @param channelJoined @@ -343,7 +432,10 @@ public class Core extends AbstractIdleService { return; } - networkBots.remove(network.get(), channelLeft.client().nick().get()); + Bot removedBot = networkBots.remove(network.get(), channelLeft.client().nick().get()); + if (removedBot != null) { + eventBus.post(new GenericMessage(String.format("Bot %s (%s) was removed, %d packs removed.", removedBot.name(), removedBot.network().name(), removedBot.packs().size()))); + } } /** @@ -359,7 +451,32 @@ public class Core extends AbstractIdleService { return; } - networkBots.remove(network.get(), clientQuit.client().nick().get()); + Bot removedBot = networkBots.remove(network.get(), clientQuit.client().nick().get()); + if (removedBot != null) { + eventBus.post(new GenericMessage(String.format("Bot %s (%s) was removed, %d packs removed.", removedBot.name(), removedBot.network().name(), removedBot.packs().size()))); + } + } + + /** + * 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 = 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); } /** @@ -417,6 +534,22 @@ public class Core extends AbstractIdleService { } /** + * Sends a message to all console when a notice was received. + * + * @param privateNoticeReceived + * The notice received event + */ + @Subscribe + public void privateNoticeReceived(PrivateNoticeReceived privateNoticeReceived) { + Optional network = getNetwork(privateNoticeReceived.connection()); + if (!network.isPresent()) { + return; + } + + eventBus.post(new GenericMessage(String.format("Notice from %s (%s): %s", privateNoticeReceived.reply().source(), network.get(), privateNoticeReceived.text()))); + } + + /** * Starts a DCC download. * * @param dccSendReceived @@ -450,7 +583,7 @@ public class Core extends AbstractIdleService { } /* remove download. */ - downloads.remove(download); + downloads.remove(download.pack().name()); return; } @@ -497,7 +630,7 @@ public class Core extends AbstractIdleService { eventBus.post(new GenericError(String.format("Download %s from %s does not start at the right position!"))); logger.log(Level.WARNING, String.format("Download %s from %s: have %d bytes but wants to resume from %d!", dccAcceptReceived.filename(), dccAcceptReceived.source(), outputFile.length(), dccAcceptReceived.position())); - downloads.remove(download); + downloads.remove(download.pack().name()); return; } OutputStream outputStream = new FileOutputStream(outputFile, true); @@ -531,7 +664,7 @@ public class Core extends AbstractIdleService { file.renameTo(new File(finalDirectory, download.pack().name())); eventBus.post(new DownloadFinished(download)); dccReceivers.remove(dccDownloadFinished.dccReceiver()); - downloads.remove(download); + downloads.remove(download.pack().name()); } catch (IOException ioe1) { /* TODO - handle all the errors. */ logger.log(Level.WARNING, String.format("Could not move file %s to directory %s.", download.filename(), finalDirectory), ioe1); @@ -556,7 +689,7 @@ public class Core extends AbstractIdleService { Closeables.close(download.outputStream(), true); eventBus.post(new DownloadFailed(download)); dccReceivers.remove(dccDownloadFailed.dccReceiver()); - downloads.remove(download); + downloads.remove(download.pack().name()); } catch (IOException ioe1) { /* swallow silently. */ }