summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/java/org/openslx/satserver/util/IrcClient.java326
-rw-r--r--src/main/java/org/openslx/taskmanager/tasks/IrcNotification.java68
2 files changed, 394 insertions, 0 deletions
diff --git a/src/main/java/org/openslx/satserver/util/IrcClient.java b/src/main/java/org/openslx/satserver/util/IrcClient.java
new file mode 100644
index 0000000..f7b6632
--- /dev/null
+++ b/src/main/java/org/openslx/satserver/util/IrcClient.java
@@ -0,0 +1,326 @@
+package org.openslx.satserver.util;
+
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.TrustManager;
+
+import org.apache.log4j.Logger;
+import org.schwering.irc.lib.IRCConfig;
+import org.schwering.irc.lib.IRCConfigBuilder;
+import org.schwering.irc.lib.IRCConnection;
+import org.schwering.irc.lib.IRCConnectionFactory;
+import org.schwering.irc.lib.IRCEventListener;
+import org.schwering.irc.lib.IRCExceptionHandler;
+import org.schwering.irc.lib.IRCSSLSupport;
+import org.schwering.irc.lib.IRCTrafficLogger;
+import org.schwering.irc.lib.IRCUser;
+import org.schwering.irc.lib.util.IRCModeParser;
+
+public class IrcClient
+{
+
+ private static final Logger LOGGER = Logger.getLogger( IrcClient.class );
+
+ private static final Map<String, Wrapper> connections = new HashMap<>();
+
+ static
+ {
+ new Thread() {
+ public void run()
+ {
+ while ( !Thread.interrupted() ) {
+ try {
+ Thread.sleep( 60000 );
+ } catch ( InterruptedException e ) {
+ return;
+ }
+ List<Wrapper> copy;
+ synchronized ( connections ) {
+ copy = new ArrayList<Wrapper>( connections.values() );
+ }
+ for ( Wrapper c : copy ) {
+ c.ping();
+ }
+ }
+ };
+ }.start();
+ }
+
+ public static void sendMessage( String serverAddress, String channel, String nick, String message, List<String> outErrors )
+ {
+ String host = serverAddress;
+ Wrapper wrapper = null;
+ int port = -1;
+ boolean ssl = false;
+ synchronized ( connections ) {
+ wrapper = connections.get( serverAddress );
+ if ( wrapper == null ) {
+ port = 6667;
+ int i = serverAddress.indexOf( ':', serverAddress.lastIndexOf( ']' ) + 1 );
+ if ( i != -1 ) {
+ host = serverAddress.substring( 0, i );
+ if ( i + 1 < serverAddress.length() && serverAddress.charAt( i + 1 ) == '+' ) {
+ ssl = true;
+ i++;
+ }
+ port = Util.parseInt( serverAddress.substring( i + 1 ), 0 );
+ }
+ if ( Util.isEmpty( host ) ) {
+ outErrors.add( "Host is empty after parsing" );
+ return;
+ }
+ if ( host.charAt( 0 ) == '[' && host.length() > 2 ) {
+ host = host.substring( 1, host.length() - 1 );
+ }
+
+ IRCSSLSupport sslSupport = null;
+ if ( ssl ) {
+ sslSupport = new IRCSSLSupport()
+ { // Return null everywhere so java uses the defaults
+ @Override
+ public TrustManager[] getTrustManagers()
+ {
+ return null;
+ }
+
+ @Override
+ public SecureRandom getSecureRandom()
+ {
+ return null;
+ }
+
+ @Override
+ public KeyManager[] getKeyManagers()
+ {
+ return null;
+ }
+ };
+ }
+ wrapper = new Wrapper( serverAddress );
+ IRCConfig config = IRCConfigBuilder.newBuilder().autoPong( true ).encoding( "UTF-8" ).host( host )
+ .port( port ).nick( nick ).timeout( 70000 ).exceptionHandler( wrapper ).trafficLogger( IRCTrafficLogger.SYSTEM_OUT )
+ .sslSupport( sslSupport ).build();
+ IRCConnection connection = IRCConnectionFactory.newConnection( config );
+ wrapper.setConnection( connection );
+ connections.put( serverAddress, wrapper );
+ }
+ } // sync end
+ synchronized ( wrapper ) {
+ if ( !wrapper.connection.isConnected() ) {
+ try {
+ wrapper.connection.connect();
+ } catch ( KeyManagementException | NoSuchAlgorithmException | IOException e ) {
+ LOGGER.warn( "Cannot connect to " + host + " port " + port + " SSL: " + ssl, e );
+ outErrors.add( "Cannot connect to " + host + " port " + port + " SSL: " + ssl );
+ return;
+ }
+ }
+ if ( wrapper.connection.isConnected() ) {
+ wrapper.sendMessage( channel, message );
+ }
+ }
+ }
+
+ static class Wrapper implements IRCExceptionHandler, IRCEventListener
+ {
+
+ private IRCConnection connection;
+ private final String host;
+ private final Set<String> channels = new HashSet<>();
+
+ public Wrapper( String host )
+ {
+ this.host = host;
+ }
+
+ public synchronized void ping()
+ {
+ LOGGER.debug( "Pinging " + host );
+ try {
+ connection.send( "PING keepalive" );
+ } catch ( Exception e ) {
+ }
+ }
+
+ public synchronized void sendMessage( String channel, String message )
+ {
+ try {
+ if ( !channels.contains( channel.toLowerCase() ) ) {
+ connection.doJoin( channel );
+ }
+ connection.doPrivmsg( channel, message );
+ } catch ( Exception e ) {
+ }
+ }
+
+ public void setConnection( IRCConnection connection )
+ {
+ if ( this.connection != null )
+ throw new RuntimeException( "Connection already set" );
+ this.connection = connection;
+ connection.addIRCEventListener( this );
+ }
+
+ /*
+ * IRCExceptionHandler
+ */
+
+ @Override
+ public void exception( IRCConnection connection, Throwable exception )
+ {
+ LOGGER.warn( "IRC Exception for " + host, exception );
+ if ( exception instanceof IOException ) {
+ connection.close();
+ }
+ }
+
+ /*
+ * IRCEventListener
+ */
+
+ @Override
+ public void onRegistered()
+ {
+ LOGGER.debug( "Registered" );
+ }
+
+ @Override
+ public void onDisconnected()
+ {
+ LOGGER.warn( host + " is dead." );
+ synchronized ( connections ) {
+ connections.remove( this.host );
+ }
+ }
+
+ @Override
+ public void onError( String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onError( int num, String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onInvite( String chan, IRCUser user, String passiveNick )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public synchronized void onJoin( String chan, IRCUser user )
+ {
+ if ( user.getNick().equalsIgnoreCase( connection.getNick() ) ) {
+ LOGGER.debug( "I joined " + chan );
+ channels.add( chan.toLowerCase() );
+ }
+ }
+
+ @Override
+ public synchronized void onKick( String chan, IRCUser user, String passiveNick, String msg )
+ {
+ if ( passiveNick.equalsIgnoreCase( connection.getNick() ) ) {
+ LOGGER.debug( "I was kicked from " + chan );
+ channels.remove( chan.toLowerCase() );
+ }
+ }
+
+ @Override
+ public void onMode( String chan, IRCUser user, IRCModeParser modeParser )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onMode( IRCUser user, String passiveNick, String mode )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onNick( IRCUser user, String newNick )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onNotice( String target, IRCUser user, String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public synchronized void onPart( String chan, IRCUser user, String msg )
+ {
+ if ( user.getNick().equalsIgnoreCase( connection.getNick() ) ) {
+ LOGGER.debug( "I left " + chan );
+ channels.remove( chan.toLowerCase() );
+ }
+ }
+
+ @Override
+ public void onPing( String ping )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onPrivmsg( String target, IRCUser user, String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onQuit( IRCUser user, String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onReply( int num, String value, String msg )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void onTopic( String chan, IRCUser user, String topic )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void unknown( String prefix, String command, String middle, String trailing )
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/openslx/taskmanager/tasks/IrcNotification.java b/src/main/java/org/openslx/taskmanager/tasks/IrcNotification.java
new file mode 100644
index 0000000..92f29f4
--- /dev/null
+++ b/src/main/java/org/openslx/taskmanager/tasks/IrcNotification.java
@@ -0,0 +1,68 @@
+package org.openslx.taskmanager.tasks;
+
+import java.util.ArrayList;
+
+import org.openslx.satserver.util.IrcClient;
+import org.openslx.satserver.util.Util;
+import org.openslx.taskmanager.api.AbstractTask;
+
+import com.google.gson.annotations.Expose;
+
+public class IrcNotification extends AbstractTask
+{
+
+ @Expose
+ private String serverAddress;
+
+ @Expose
+ private String channel;
+
+ @Expose
+ private String message;
+
+ @Expose
+ private String nickName;
+
+ private Output status = new Output();
+
+ @Override
+ protected boolean initTask()
+ {
+ this.setStatusObject( status );
+ if ( Util.isEmpty( serverAddress ) ) {
+ status.add( "serverAddress empty" );
+ return false;
+ }
+ if ( Util.isEmpty( channel ) ) {
+ status.add( "channel empty" );
+ return false;
+ }
+ if ( Util.isEmpty( message ) ) {
+ status.add( "message empty" );
+ return false;
+ }
+ if ( Util.isEmpty( nickName ) ) {
+ nickName = "bwlp-" + (int) ( Math.random() * 10000 );
+ }
+ return true;
+ }
+
+ @Override
+ protected boolean execute()
+ {
+ ArrayList<String> errors = new ArrayList<>( 0 );
+ IrcClient.sendMessage( serverAddress, channel, nickName, message, errors );
+ return true;
+ }
+
+ public static class Output
+ {
+ private String messages;
+
+ public void add( String message )
+ {
+ this.messages += message + "\n";
+ }
+ }
+
+}