From a316b76d70d042a1c7100261a04aa0a5b8528e02 Mon Sep 17 00:00:00 2001 From: Manevolent Date: Sun, 5 Aug 2018 19:20:02 -0400 Subject: [PATCH] Channel subscription, getting channel info, and multithreaded event handling --- .../ts3j/event/ChannelSubscribedEvent.java | 47 ++++++ .../manevolent/ts3j/event/TS3Event.java | 2 + .../manevolent/ts3j/event/TS3Listener.java | 2 + .../client/LocalTeamspeakClientSocket.java | 19 ++- .../manevolent/ts3j/ServerConnectionTest.java | 136 +++++++++++++++--- 5 files changed, 182 insertions(+), 24 deletions(-) create mode 100644 src/main/java/com/github/manevolent/ts3j/event/ChannelSubscribedEvent.java diff --git a/src/main/java/com/github/manevolent/ts3j/event/ChannelSubscribedEvent.java b/src/main/java/com/github/manevolent/ts3j/event/ChannelSubscribedEvent.java new file mode 100644 index 0000000..a38b809 --- /dev/null +++ b/src/main/java/com/github/manevolent/ts3j/event/ChannelSubscribedEvent.java @@ -0,0 +1,47 @@ +package com.github.manevolent.ts3j.event; + +/* + * #%L + * TeamSpeak 3 Java API + * %% + * Copyright (C) 2014 Bert De Geyter + * %% + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * #L% + */ + +import com.github.manevolent.ts3j.api.ChannelProperty; + +import java.util.Map; + +public class ChannelSubscribedEvent extends BaseEvent { + + public ChannelSubscribedEvent(Map map) { + super(map); + } + + public int getChannelId() { + return getInt(ChannelProperty.CID); + } + + @Override + public void fire(TS3Listener listener) { + listener.onChannelSubscribed(this); + } +} diff --git a/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java b/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java index 2b42b88..44adebb 100644 --- a/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java +++ b/src/main/java/com/github/manevolent/ts3j/event/TS3Event.java @@ -67,6 +67,8 @@ public interface TS3Event { return new ClientNeededPermissionsEvent(command.toMap()); case "notifyclientupdated": // CLIENT return new ClientUpdatedEvent(command.toMap()); + case "notifychannelsubscribed": // CLIENT + return new ChannelSubscribedEvent(command.toMap()); default: throw new IllegalArgumentException("unknown event: " + command.getName()); } diff --git a/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java b/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java index cc78d02..47d299c 100644 --- a/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java +++ b/src/main/java/com/github/manevolent/ts3j/event/TS3Listener.java @@ -65,4 +65,6 @@ public interface TS3Listener { void onClientChanged(ClientUpdatedEvent e); void onDisconnected(DisconnectedEvent e); + + void onChannelSubscribed(ChannelSubscribedEvent e); } diff --git a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java index 3150fa2..37cb6a1 100644 --- a/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java +++ b/src/main/java/com/github/manevolent/ts3j/protocol/socket/client/LocalTeamspeakClientSocket.java @@ -26,9 +26,7 @@ import java.net.*; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.*; import java.util.function.Function; import java.util.stream.Collectors; @@ -48,6 +46,7 @@ public class LocalTeamspeakClientSocket private final DatagramPacket packet = new DatagramPacket(new byte[500], 500); private final Map namedProcessors = new HashMap<>(); + private final ExecutorService commandExecutionService = Executors.newCachedThreadPool(); private final Object commandSendLock = new Object(); @@ -239,7 +238,8 @@ public class LocalTeamspeakClientSocket processor.process(client, singleCommand); } else if (singleCommand.getName().startsWith("notify")) { TS3Event event = TS3Event.createEvent(singleCommand); - listeners.forEach(event::fire); + + commandExecutionService.submit(() -> listeners.forEach(event::fire)); } else { CommandProcessor awaitingCommandProcessor; @@ -815,6 +815,17 @@ public class LocalTeamspeakClientSocket return clients.iterator().next(); } + public Channel getChannelInfo(int channelId) + throws IOException, TimeoutException, ExecutionException, InterruptedException { + Command command = new SingleCommand( + "channelinfo", + ProtocolRole.CLIENT, + new CommandSingleParameter("cid", Integer.toString(channelId)) + ); + + return executeCommand(command, x -> new Channel(x.toMap())).get().iterator().next(); + } + public void disconnect() throws IOException, TimeoutException, diff --git a/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java b/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java index fb482b4..fba3941 100644 --- a/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java +++ b/src/test/java/com/github/manevolent/ts3j/ServerConnectionTest.java @@ -3,14 +3,18 @@ package com.github.manevolent.ts3j; import com.github.manevolent.ts3j.api.Client; import com.github.manevolent.ts3j.audio.Microphone; import com.github.manevolent.ts3j.enums.CodecType; +import com.github.manevolent.ts3j.event.*; import com.github.manevolent.ts3j.identity.LocalIdentity; import com.github.manevolent.ts3j.protocol.client.ClientConnectionState; import com.github.manevolent.ts3j.protocol.socket.client.LocalTeamspeakClientSocket; import com.github.manevolent.ts3j.util.Ts3Debugging; +import java.io.IOException; import java.math.BigInteger; import java.net.InetSocketAddress; import java.util.Base64; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; import static org.junit.Assert.assertEquals; @@ -27,24 +31,6 @@ public class ServerConnectionTest { LocalTeamspeakClientSocket client = new LocalTeamspeakClientSocket(); - client.setMicrophone(new Microphone() { - @Override - public boolean isReady() { - return true; - } - - @Override - public CodecType getCodec() { - return CodecType.OPUS_MUSIC; - } - - @Override - public byte[] provide() { - System.err.println("Provide."); - return new byte[0]; - } - }); - client.setIdentity(identity); client.setNickname("Hello from Java"); @@ -58,11 +44,121 @@ public class ServerConnectionTest { 10000L ); - client.sendServerMessage("\u26D4 You are not listening to this channel."); + client.addListener(new TS3Listener() { + @Override + public void onTextMessage(TextMessageEvent e) { + + } + + @Override + public void onClientJoin(ClientJoinEvent e) { + + } + + @Override + public void onClientLeave(ClientLeaveEvent e) { + + } + + @Override + public void onServerEdit(ServerEditedEvent e) { + + } + + @Override + public void onChannelEdit(ChannelEditedEvent e) { + + } + + @Override + public void onChannelDescriptionChanged(ChannelDescriptionEditedEvent e) { + + } + + @Override + public void onClientMoved(ClientMovedEvent e) { + + } + + @Override + public void onChannelCreate(ChannelCreateEvent e) { + + } + + @Override + public void onChannelDeleted(ChannelDeletedEvent e) { + + } + + @Override + public void onChannelMoved(ChannelMovedEvent e) { + + } + + @Override + public void onChannelPasswordChanged(ChannelPasswordChangedEvent e) { + + } + + @Override + public void onChannelList(ChannelListEvent e) { + + } + + @Override + public void onPrivilegeKeyUsed(PrivilegeKeyUsedEvent e) { + + } + + @Override + public void onChannelGroupList(ChannelGroupListEvent e) { + + } + + @Override + public void onServerGroupList(ServerGroupListEvent e) { + + } + + @Override + public void onClientNeededPermissions(ClientNeededPermissionsEvent e) { + + } + + @Override + public void onClientChannelGroupChanged(ClientChannelGroupChangedEvent e) { + + } + + @Override + public void onClientChanged(ClientUpdatedEvent e) { + + } + + @Override + public void onDisconnected(DisconnectedEvent e) { + + } + + @Override + public void onChannelSubscribed(ChannelSubscribedEvent e) { + try { + client.getChannelInfo(e.getChannelId()); + } catch (IOException e1) { + e1.printStackTrace(); + } catch (TimeoutException e1) { + e1.printStackTrace(); + } catch (ExecutionException e1) { + e1.printStackTrace(); + } catch (InterruptedException e1) { + e1.printStackTrace(); + } + } + }); assertEquals(client.getState(), ClientConnectionState.CONNECTED); - client.setNickname("gjklsdfkjlgdsfgd2"); + client.subscribeAll(); client.waitForState(ClientConnectionState.DISCONNECTED, 10000L); } catch (Throwable ex) {