/* * #%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.theholywaffle.teamspeak3.TS3Api; import com.github.theholywaffle.teamspeak3.TS3ApiAsync; import com.github.theholywaffle.teamspeak3.TS3Config; import com.github.theholywaffle.teamspeak3.TS3Query; import com.github.theholywaffle.teamspeak3.api.CommandFuture.SuccessListener; import com.github.theholywaffle.teamspeak3.api.event.ClientJoinEvent; import com.github.theholywaffle.teamspeak3.api.event.ClientLeaveEvent; import com.github.theholywaffle.teamspeak3.api.event.TS3EventAdapter; import com.github.theholywaffle.teamspeak3.api.event.TS3EventType; import com.github.theholywaffle.teamspeak3.api.wrapper.Channel; import java.util.HashMap; import java.util.List; import java.util.Random; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.logging.Level; /** * A more advanced example of a query which trolls clients on a server * by moving them into other channels and sending them creepy messages. *

* Unlike the other examples, this class uses the asynchronous API * in combination with a {@code ScheduledExecutorService}. *

*/ public class TrollExample { private static final Random RANDOM = new Random(); // Troll-y messages because reason. They're not especially good, I'm sorry :( private static final String[] MESSAGES = { "Get off my server, damn kids!", "Tell me a joke!", "Hey Apple! Hey Apple! Apple! Hey Apple!", "A virus has been detected", "Move out of this channel or you will be banned in 15 seconds.", "Say something :3", "Boo!" }; public static void main(String[] args) { new TrollExample(); } private final TS3Query query; private final ScheduledExecutorService executor; private final HashMap workers; public TrollExample() { // Start the query final TS3Config config = new TS3Config(); config.setHost("77.77.77.77"); config.setDebugLevel(Level.ALL); query = new TS3Query(config); query.connect(); // And let's use one separate thread to troll everyone executor = new ScheduledThreadPoolExecutor(1); workers = new HashMap<>(); // Log in, select the virtual server and set a nickname TS3Api api = query.getApi(); api.login("serveradmin", "serveradminpassword"); api.selectVirtualServerById(1); api.setNickname("Global Server Admin"); api.registerEvent(TS3EventType.SERVER); api.addTS3Listeners(new TS3EventAdapter() { @Override public void onClientJoin(ClientJoinEvent e) { final int clientId = e.getClientId(); final ClientTrollWorker worker = new ClientTrollWorker(clientId); workers.put(clientId, worker); // Let's wait a short moment until we begin trolling - 10 to 20 seconds long timeout = 10 + RANDOM.nextInt(11); executor.schedule(worker, timeout, TimeUnit.SECONDS); } @Override public void onClientLeave(ClientLeaveEvent e) { final ClientTrollWorker worker = workers.remove(e.getClientId()); if (worker == null) return; worker.shutdown(); } }); } private class ClientTrollWorker implements Runnable { private final int clientId; private boolean cancelled; private ClientTrollWorker(int clientId) { this.clientId = clientId; cancelled = false; } @Override public void run() { // We were cancelled, abandon ship! if (cancelled) return; // Important! // We're using the asynchronous API so we don't block // our executor which has only 1 thread final TS3ApiAsync asyncApi = query.getAsyncApi(); // Let's decide what to do int choice = RANDOM.nextInt(4); // 0 .. 3 switch (choice) { case 0: // Poke the client with a random message String pokeMessage = MESSAGES[RANDOM.nextInt(MESSAGES.length)]; asyncApi.pokeClient(clientId, pokeMessage); break; case 1: // Send the client a private message String privateMessage = MESSAGES[RANDOM.nextInt(MESSAGES.length)]; asyncApi.sendPrivateMessage(clientId, privateMessage); break; case 2: // Kick the client to the default channel asyncApi.kickClientFromChannel(clientId); break; case 3: // Move client into a different channel // First, get all channels // (Using .getChannels every time works on small servers, but might // not be a good idea on servers with 50+ clients! ) asyncApi.getChannels().onSuccess(new SuccessListener>() { @Override public void handleSuccess(List result) { // Once we retrieved the channels (some time in the future), choose one channel int randomChannelIndex = RANDOM.nextInt(result.size()); Channel randomChannel = result.get(randomChannelIndex); // Then move the client into that channel asyncApi.moveClient(clientId, randomChannel.getId()); } }); break; default: // java.util.Random is broken throw new IllegalStateException("java.util.Random returned an illegal value."); } // And finally, re-schedule the runnable long timeout = RANDOM.nextInt(30) + 30; // Wait 30 to 60 seconds executor.schedule(this, timeout, TimeUnit.SECONDS); } private void shutdown() { cancelled = true; } } }