001package com.github.theholywaffle.teamspeak3;
002
003/*
004 * #%L
005 * TeamSpeak 3 Java API
006 * %%
007 * Copyright (C) 2014 Bert De Geyter
008 * %%
009 * Permission is hereby granted, free of charge, to any person obtaining a copy
010 * of this software and associated documentation files (the "Software"), to deal
011 * in the Software without restriction, including without limitation the rights
012 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
013 * copies of the Software, and to permit persons to whom the Software is
014 * furnished to do so, subject to the following conditions:
015 * 
016 * The above copyright notice and this permission notice shall be included in
017 * all copies or substantial portions of the Software.
018 * 
019 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
020 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
021 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
022 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
023 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
024 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
025 * THE SOFTWARE.
026 * #L%
027 */
028
029import com.github.theholywaffle.teamspeak3.api.*;
030import com.github.theholywaffle.teamspeak3.api.event.TS3EventType;
031import com.github.theholywaffle.teamspeak3.api.event.TS3Listener;
032import com.github.theholywaffle.teamspeak3.api.exception.TS3CommandFailedException;
033import com.github.theholywaffle.teamspeak3.api.exception.TS3ConnectionFailedException;
034import com.github.theholywaffle.teamspeak3.api.exception.TS3FileTransferFailedException;
035import com.github.theholywaffle.teamspeak3.api.wrapper.*;
036
037import java.io.InputStream;
038import java.io.OutputStream;
039import java.util.List;
040import java.util.Map;
041import java.util.regex.Pattern;
042
043/**
044 * API to interact with the {@link TS3Query} synchronously.
045 * <p>
046 * This class is used to easily interact with a {@link TS3Query}. It constructs commands,
047 * sends them to the TeamSpeak3 server, processes the response and returns the result.
048 * </p><p>
049 * All methods in this class are synchronous, so they will block until the response arrives.
050 * Calls to this API will usually take about 50 milliseconds to complete (plus ping),
051 * but delays can range up to 4 seconds.
052 * If a command takes longer than 4 seconds to complete, a {@link TS3ConnectionFailedException}
053 * will be thrown.
054 * </p><p>
055 * You won't be able to execute most commands while you're not logged in due to missing permissions.
056 * Make sure to either pass your login credentials to the {@link TS3Config} object when
057 * creating the {@code TS3Query} or to call {@link #login(String, String)} to log in.
058 * </p><p>
059 * After that, most commands also require you to select a {@linkplain VirtualServer virtual server}.
060 * To do so, call either {@link #selectVirtualServerByPort(int)} or {@link #selectVirtualServerById(int)}.
061 * </p><p>
062 * Be aware that many methods in this class will return {@code null} or {@code -1} if a command fails.
063 * </p>
064 *
065 * @see TS3ApiAsync The asynchronous version of the API
066 */
067public class TS3Api {
068
069        private final TS3ApiAsync asyncApi;
070
071        /**
072         * Creates a new synchronous API object for the given {@code TS3Query}.
073         * <p>
074         * <b>Usually, this constructor should not be called.</b> Use {@link TS3Query#getApi()} instead.
075         * </p>
076         *
077         * @param asyncApi
078         *              the asynchronous version of the API this class routes its method calls through
079         */
080        TS3Api(TS3ApiAsync asyncApi) {
081                this.asyncApi = asyncApi;
082        }
083
084        /**
085         * Adds a new ban entry. At least one of the parameters {@code ip}, {@code name} or {@code uid} needs to be non-null.
086         * Returns the ID of the newly created ban entry.
087         *
088         * @param ip
089         *              a RegEx pattern to match a client's IP against, can be {@code null}
090         * @param name
091         *              a RegEx pattern to match a client's name against, can be {@code null}
092         * @param uid
093         *              the unique identifier of a client, can be {@code null}
094         * @param timeInSeconds
095         *              the duration of the ban in seconds. 0 equals a permanent ban
096         * @param reason
097         *              the reason for the ban, can be {@code null}
098         *
099         * @return the ID of the newly created ban entry
100         *
101         * @throws TS3CommandFailedException
102         *              if the execution of a command fails
103         * @querycommands 1
104         * @see Pattern RegEx Pattern
105         * @see #addBan(String, String, String, String, long, String)
106         * @see Client#getId()
107         * @see Client#getUniqueIdentifier()
108         * @see ClientInfo#getIp()
109         */
110        public int addBan(String ip, String name, String uid, long timeInSeconds, String reason) {
111                return asyncApi.addBan(ip, name, uid, timeInSeconds, reason).getUninterruptibly();
112        }
113
114        /**
115         * Adds a new ban entry. At least one of the parameters {@code ip}, {@code name}, {@code uid}, or
116         * {@code myTSId} needs to be non-null. Returns the ID of the newly created ban entry.
117         * <p>
118         * Note that creating a ban entry for the {@code "empty"} "myTeamSpeak" ID will ban all clients who
119         * don't have a linked "myTeamSpeak" account.
120         * </p>
121         *
122         * @param ip
123         *              a RegEx pattern to match a client's IP against, can be {@code null}
124         * @param name
125         *              a RegEx pattern to match a client's name against, can be {@code null}
126         * @param uid
127         *              the unique identifier of a client, can be {@code null}
128         * @param myTSId
129         *              the "myTeamSpeak" ID of a client, the string {@code "empty"}, or {@code null}
130         * @param timeInSeconds
131         *              the duration of the ban in seconds. 0 equals a permanent ban
132         * @param reason
133         *              the reason for the ban, can be {@code null}
134         *
135         * @return the ID of the newly created ban entry
136         *
137         * @throws TS3CommandFailedException
138         *              if the execution of a command fails
139         * @querycommands 1
140         * @see Pattern RegEx Pattern
141         * @see Client#getId()
142         * @see Client#getUniqueIdentifier()
143         * @see ClientInfo#getIp()
144         */
145        public int addBan(String ip, String name, String uid, String myTSId, long timeInSeconds, String reason) {
146                return asyncApi.addBan(ip, name, uid, myTSId, timeInSeconds, reason).getUninterruptibly();
147        }
148
149        /**
150         * Adds a specified permission to a client in a specific channel.
151         *
152         * @param channelId
153         *              the ID of the channel wherein the permission should be granted
154         * @param clientDBId
155         *              the database ID of the client to add a permission to
156         * @param permName
157         *              the name of the permission to grant
158         * @param permValue
159         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
160         *
161         * @throws TS3CommandFailedException
162         *              if the execution of a command fails
163         * @querycommands 1
164         * @see Channel#getId()
165         * @see Client#getDatabaseId()
166         * @see Permission
167         */
168        public void addChannelClientPermission(int channelId, int clientDBId, String permName, int permValue) {
169                asyncApi.addChannelClientPermission(channelId, clientDBId, permName, permValue).getUninterruptibly();
170        }
171
172        /**
173         * Creates a new channel group for clients using a given name and returns its ID.
174         * <p>
175         * To create channel group templates or ones for server queries,
176         * use {@link #addChannelGroup(String, PermissionGroupDatabaseType)}.
177         * </p>
178         *
179         * @param name
180         *              the name of the new channel group
181         *
182         * @return the ID of the newly created channel group
183         *
184         * @throws TS3CommandFailedException
185         *              if the execution of a command fails
186         * @querycommands 1
187         * @see ChannelGroup
188         */
189        public int addChannelGroup(String name) {
190                return asyncApi.addChannelGroup(name).getUninterruptibly();
191        }
192
193        /**
194         * Creates a new channel group using a given name and returns its ID.
195         *
196         * @param name
197         *              the name of the new channel group
198         * @param type
199         *              the desired type of channel group
200         *
201         * @return the ID of the newly created channel group
202         *
203         * @throws TS3CommandFailedException
204         *              if the execution of a command fails
205         * @querycommands 1
206         * @see ChannelGroup
207         */
208        public int addChannelGroup(String name, PermissionGroupDatabaseType type) {
209                return asyncApi.addChannelGroup(name, type).getUninterruptibly();
210        }
211
212        /**
213         * Adds a specified permission to a channel group.
214         *
215         * @param groupId
216         *              the ID of the channel group to grant the permission
217         * @param permName
218         *              the name of the permission to be granted
219         * @param permValue
220         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
221         *
222         * @throws TS3CommandFailedException
223         *              if the execution of a command fails
224         * @querycommands 1
225         * @see ChannelGroup#getId()
226         * @see Permission
227         */
228        public void addChannelGroupPermission(int groupId, String permName, int permValue) {
229                asyncApi.addChannelGroupPermission(groupId, permName, permValue).getUninterruptibly();
230        }
231
232        /**
233         * Adds a specified permission to a channel.
234         *
235         * @param channelId
236         *              the ID of the channel wherein the permission should be granted
237         * @param permName
238         *              the name of the permission to grant
239         * @param permValue
240         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
241         *
242         * @throws TS3CommandFailedException
243         *              if the execution of a command fails
244         * @querycommands 1
245         * @see Channel#getId()
246         * @see Permission
247         */
248        public void addChannelPermission(int channelId, String permName, int permValue) {
249                asyncApi.addChannelPermission(channelId, permName, permValue).getUninterruptibly();
250        }
251
252        /**
253         * Adds a specified permission to a channel.
254         *
255         * @param clientDBId
256         *              the database ID of the client to grant the permission
257         * @param permName
258         *              the name of the permission to grant
259         * @param value
260         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
261         * @param skipped
262         *              if set to {@code true}, the permission will not be overridden by channel group permissions
263         *
264         * @throws TS3CommandFailedException
265         *              if the execution of a command fails
266         * @querycommands 1
267         * @see Client#getDatabaseId()
268         * @see Permission
269         */
270        public void addClientPermission(int clientDBId, String permName, int value, boolean skipped) {
271                asyncApi.addClientPermission(clientDBId, permName, value, skipped).getUninterruptibly();
272        }
273
274        /**
275         * Adds a client to the specified server group.
276         * <p>
277         * Please note that a client cannot be added to default groups or template groups.
278         * </p>
279         *
280         * @param groupId
281         *              the ID of the server group to add the client to
282         * @param clientDatabaseId
283         *              the database ID of the client to add
284         *
285         * @throws TS3CommandFailedException
286         *              if the execution of a command fails
287         * @querycommands 1
288         * @see ServerGroup#getId()
289         * @see Client#getDatabaseId()
290         */
291        public void addClientToServerGroup(int groupId, int clientDatabaseId) {
292                asyncApi.addClientToServerGroup(groupId, clientDatabaseId).getUninterruptibly();
293        }
294
295        /**
296         * Submits a complaint about the specified client.
297         * The length of the message is limited to 200 UTF-8 bytes and BB codes in it will be ignored.
298         *
299         * @param clientDBId
300         *              the database ID of the client
301         * @param message
302         *              the message of the complaint, may not contain BB codes
303         *
304         * @throws TS3CommandFailedException
305         *              if the execution of a command fails
306         * @querycommands 1
307         * @see Client#getDatabaseId()
308         * @see Complaint#getMessage()
309         */
310        public void addComplaint(int clientDBId, String message) {
311                asyncApi.addComplaint(clientDBId, message).getUninterruptibly();
312        }
313
314        /**
315         * Adds a specified permission to all server groups of the type specified by {@code type} on all virtual servers.
316         *
317         * @param type
318         *              the kind of server group this permission should be added to
319         * @param permName
320         *              the name of the permission to be granted
321         * @param value
322         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
323         * @param negated
324         *              if set to true, the lowest permission value will be selected instead of the highest
325         * @param skipped
326         *              if set to true, this permission will not be overridden by client or channel group permissions
327         *
328         * @throws TS3CommandFailedException
329         *              if the execution of a command fails
330         * @querycommands 1
331         * @see ServerGroupType
332         * @see Permission
333         */
334        public void addPermissionToAllServerGroups(ServerGroupType type, String permName, int value, boolean negated, boolean skipped) {
335                asyncApi.addPermissionToAllServerGroups(type, permName, value, negated, skipped).getUninterruptibly();
336        }
337
338        /**
339         * Create a new privilege key that allows one client to join a server or channel group.
340         * <ul>
341         * <li>If {@code type} is set to {@linkplain PrivilegeKeyType#SERVER_GROUP SERVER_GROUP},
342         * {@code groupId} is used as a server group ID and {@code channelId} is ignored.</li>
343         * <li>If {@code type} is set to {@linkplain PrivilegeKeyType#CHANNEL_GROUP CHANNEL_GROUP},
344         * {@code groupId} is used as a channel group ID and {@code channelId} is used as the channel in which the group should be set.</li>
345         * </ul>
346         *
347         * @param type
348         *              the type of token that should be created
349         * @param groupId
350         *              the ID of the server or channel group
351         * @param channelId
352         *              the ID of the channel, in case the token is channel group token
353         * @param description
354         *              the description for the token, can be null
355         *
356         * @return the created token for a client to use
357         *
358         * @throws TS3CommandFailedException
359         *              if the execution of a command fails
360         * @querycommands 1
361         * @see PrivilegeKeyType
362         * @see #addPrivilegeKeyServerGroup(int, String)
363         * @see #addPrivilegeKeyChannelGroup(int, int, String)
364         */
365        public String addPrivilegeKey(PrivilegeKeyType type, int groupId, int channelId, String description) {
366                return asyncApi.addPrivilegeKey(type, groupId, channelId, description).getUninterruptibly();
367        }
368
369        /**
370         * Creates a new privilege key for a channel group.
371         *
372         * @param channelGroupId
373         *              the ID of the channel group
374         * @param channelId
375         *              the ID of the channel in which the channel group should be set
376         * @param description
377         *              the description for the token, can be null
378         *
379         * @return the created token for a client to use
380         *
381         * @throws TS3CommandFailedException
382         *              if the execution of a command fails
383         * @querycommands 1
384         * @see ChannelGroup#getId()
385         * @see Channel#getId()
386         * @see #addPrivilegeKey(PrivilegeKeyType, int, int, String)
387         * @see #addPrivilegeKeyServerGroup(int, String)
388         */
389        public String addPrivilegeKeyChannelGroup(int channelGroupId, int channelId, String description) {
390                return asyncApi.addPrivilegeKeyChannelGroup(channelGroupId, channelId, description).getUninterruptibly();
391        }
392
393        /**
394         * Creates a new privilege key for a server group.
395         *
396         * @param serverGroupId
397         *              the ID of the server group
398         * @param description
399         *              the description for the token, can be null
400         *
401         * @return the created token for a client to use
402         *
403         * @throws TS3CommandFailedException
404         *              if the execution of a command fails
405         * @querycommands 1
406         * @see ServerGroup#getId()
407         * @see #addPrivilegeKey(PrivilegeKeyType, int, int, String)
408         * @see #addPrivilegeKeyChannelGroup(int, int, String)
409         */
410        public String addPrivilegeKeyServerGroup(int serverGroupId, String description) {
411                return asyncApi.addPrivilegeKeyServerGroup(serverGroupId, description).getUninterruptibly();
412        }
413
414        /**
415         * Creates a new server group for clients using a given name and returns its ID.
416         * <p>
417         * To create server group templates or ones for server queries,
418         * use {@link #addServerGroup(String, PermissionGroupDatabaseType)}.
419         * </p>
420         *
421         * @param name
422         *              the name of the new server group
423         *
424         * @return the ID of the newly created server group
425         *
426         * @throws TS3CommandFailedException
427         *              if the execution of a command fails
428         * @querycommands 1
429         * @see ServerGroup
430         */
431        public int addServerGroup(String name) {
432                return asyncApi.addServerGroup(name).getUninterruptibly();
433        }
434
435        /**
436         * Creates a new server group using a given name and returns its ID.
437         *
438         * @param name
439         *              the name of the new server group
440         * @param type
441         *              the desired type of server group
442         *
443         * @return the ID of the newly created server group
444         *
445         * @throws TS3CommandFailedException
446         *              if the execution of a command fails
447         * @querycommands 1
448         * @see ServerGroup
449         * @see PermissionGroupDatabaseType
450         */
451        public int addServerGroup(String name, PermissionGroupDatabaseType type) {
452                return asyncApi.addServerGroup(name, type).getUninterruptibly();
453        }
454
455        /**
456         * Adds a specified permission to a server group.
457         *
458         * @param groupId
459         *              the ID of the channel group to which the permission should be added
460         * @param permName
461         *              the name of the permission to add
462         * @param value
463         *              the numeric value of the permission (or for boolean permissions: 1 = true, 0 = false)
464         * @param negated
465         *              if set to true, the lowest permission value will be selected instead of the highest
466         * @param skipped
467         *              if set to true, this permission will not be overridden by client or channel group permissions
468         *
469         * @throws TS3CommandFailedException
470         *              if the execution of a command fails
471         * @querycommands 1
472         * @see ServerGroup#getId()
473         * @see Permission
474         */
475        public void addServerGroupPermission(int groupId, String permName, int value, boolean negated, boolean skipped) {
476                asyncApi.addServerGroupPermission(groupId, permName, value, negated, skipped).getUninterruptibly();
477        }
478
479        /**
480         * Creates a server query login with name {@code loginName} for the client specified by {@code clientDBId}
481         * on the currently selected virtual server and returns the password of the created login.
482         * If the client already had a server query login, the existing login will be deleted and replaced.
483         * <p>
484         * Moreover, this method can be used to create new <i>global</i> server query logins that are not tied to any
485         * particular virtual server or client. To create such a server query login, make sure no virtual server is
486         * selected (e.g. use {@code selectVirtualServerById(0)}) and call this method with {@code clientDBId = 0}.
487         * </p>
488         *
489         * @param loginName
490         *              the name of the server query login to add
491         * @param clientDBId
492         *              the database ID of the client for which a server query login should be created
493         *
494         * @return an object containing the password of the new server query login
495         *
496         * @throws TS3CommandFailedException
497         *              if the execution of a command fails
498         * @querycommands 1
499         * @see #deleteServerQueryLogin(int)
500         * @see #getServerQueryLogins()
501         * @see #updateServerQueryLogin(String)
502         */
503        public CreatedQueryLogin addServerQueryLogin(String loginName, int clientDBId) {
504                return asyncApi.addServerQueryLogin(loginName, clientDBId).getUninterruptibly();
505        }
506
507        /**
508         * Adds one or more {@link TS3Listener}s to the event manager of the query.
509         * These listeners will be notified when the TS3 server fires an event.
510         * <p>
511         * Note that for the TS3 server to fire events, you must first also register
512         * the event types you want to listen to.
513         * </p>
514         *
515         * @param listeners
516         *              one or more listeners to register
517         *
518         * @see #registerAllEvents()
519         * @see #registerEvent(TS3EventType, int)
520         * @see TS3Listener
521         * @see TS3EventType
522         */
523        public void addTS3Listeners(TS3Listener... listeners) {
524                asyncApi.addTS3Listeners(listeners);
525        }
526
527        /**
528         * Bans a client with a given client ID for a given time.
529         * <p>
530         * Please note that this will create up to three separate ban rules,
531         * one for the targeted client's IP address, one for their unique identifier,
532         * and potentially one more entry for their "myTeamSpeak" ID, if available.
533         * </p><p>
534         * <i>Exception:</i> If the banned client connects via a loopback address
535         * (i.e. {@code 127.0.0.1} or {@code localhost}), no IP ban is created.
536         * </p>
537         *
538         * @param clientId
539         *              the ID of the client
540         * @param timeInSeconds
541         *              the duration of the ban in seconds. 0 equals a permanent ban
542         *
543         * @return an array containing the IDs of the created ban entries
544         *
545         * @throws TS3CommandFailedException
546         *              if the execution of a command fails
547         * @querycommands 1
548         * @see Client#getId()
549         * @see #addBan(String, String, String, long, String)
550         */
551        public int[] banClient(int clientId, long timeInSeconds) {
552                return asyncApi.banClient(clientId, timeInSeconds).getUninterruptibly();
553        }
554
555        /**
556         * Bans a client with a given client ID for a given time for the specified reason.
557         * <p>
558         * Please note that this will create up to three separate ban rules,
559         * one for the targeted client's IP address, one for their unique identifier,
560         * and potentially one more entry for their "myTeamSpeak" ID, if available.
561         * </p><p>
562         * <i>Exception:</i> If the banned client connects via a loopback address
563         * (i.e. {@code 127.0.0.1} or {@code localhost}), no IP ban is created.
564         * </p>
565         *
566         * @param clientId
567         *              the ID of the client
568         * @param timeInSeconds
569         *              the duration of the ban in seconds. 0 equals a permanent ban
570         * @param reason
571         *              the reason for the ban, can be null
572         *
573         * @return an array containing the IDs of the created ban entries
574         *
575         * @throws TS3CommandFailedException
576         *              if the execution of a command fails
577         * @querycommands 1
578         * @see Client#getId()
579         * @see #addBan(String, String, String, long, String)
580         */
581        public int[] banClient(int clientId, long timeInSeconds, String reason) {
582                return asyncApi.banClient(clientId, timeInSeconds, reason).getUninterruptibly();
583        }
584
585        /**
586         * Bans a client with a given client ID permanently for the specified reason.
587         * <p>
588         * Please note that this will create up to three separate ban rules,
589         * one for the targeted client's IP address, one for their unique identifier,
590         * and potentially one more entry for their "myTeamSpeak" ID, if available.
591         * </p><p>
592         * <i>Exception:</i> If the banned client connects via a loopback address
593         * (i.e. {@code 127.0.0.1} or {@code localhost}), no IP ban is created.
594         * </p>
595         *
596         * @param clientId
597         *              the ID of the client
598         * @param reason
599         *              the reason for the ban, can be null
600         *
601         * @return an array containing the IDs of the created ban entries
602         *
603         * @throws TS3CommandFailedException
604         *              if the execution of a command fails
605         * @querycommands 1
606         * @see Client#getId()
607         * @see #addBan(String, String, String, long, String)
608         */
609        public int[] banClient(int clientId, String reason) {
610                return asyncApi.banClient(clientId, reason).getUninterruptibly();
611        }
612
613        /**
614         * Bans multiple clients by their client ID for a given time for the specified reason.
615         * <p>
616         * Please note that this will create up to three separate ban rules for each client,
617         * one for the targeted client's IP address, one for their unique identifier,
618         * and potentially one more entry for their "myTeamSpeak" ID, if available.
619         * </p><p>
620         * <i>Exception:</i> If the banned client connects via a loopback address
621         * (i.e. {@code 127.0.0.1} or {@code localhost}), no IP ban is created.
622         * </p><p>
623         * <i>Exception:</i> If two or more clients are connecting from the
624         * same IP address, only one IP ban entry for that IP will be created.
625         * </p>
626         *
627         * @param clientIds
628         *              the IDs of the clients to be banned
629         * @param timeInSeconds
630         *              the duration of the ban in seconds. 0 equals a permanent ban
631         * @param reason
632         *              the reason for the ban, can be null
633         * @param continueOnError
634         *              if true, continue to the next client if banning one client fails, else do not create any bans on error
635         *
636         * @return an array containing the IDs of the created ban entries
637         *
638         * @throws TS3CommandFailedException
639         *              if the execution of a command fails
640         * @querycommands 1
641         * @see Client#getId()
642         * @see #addBan(String, String, String, long, String)
643         */
644        public int[] banClients(int[] clientIds, long timeInSeconds, String reason, boolean continueOnError) {
645                return asyncApi.banClients(clientIds, timeInSeconds, reason, continueOnError).getUninterruptibly();
646        }
647
648        /**
649         * Sends a text message to all clients on all virtual servers.
650         * These messages will appear to clients in the tab for server messages.
651         *
652         * @param message
653         *              the message to be sent
654         *
655         * @throws TS3CommandFailedException
656         *              if the execution of a command fails
657         * @querycommands 1
658         */
659        public void broadcast(String message) {
660                asyncApi.broadcast(message).getUninterruptibly();
661        }
662
663        /**
664         * Creates a copy of the channel group specified by {@code sourceGroupId},
665         * overwriting any other channel group specified by {@code targetGroupId}.
666         * <p>
667         * The parameter {@code type} can be used to create server query and template groups.
668         * </p>
669         *
670         * @param sourceGroupId
671         *              the ID of the channel group to copy
672         * @param targetGroupId
673         *              the ID of another channel group to overwrite
674         * @param type
675         *              the desired type of channel group
676         *
677         * @throws TS3CommandFailedException
678         *              if the execution of a command fails
679         * @querycommands 1
680         * @see ChannelGroup#getId()
681         */
682        public void copyChannelGroup(int sourceGroupId, int targetGroupId, PermissionGroupDatabaseType type) {
683                asyncApi.copyChannelGroup(sourceGroupId, targetGroupId, type).getUninterruptibly();
684        }
685
686        /**
687         * Creates a copy of the channel group specified by {@code sourceGroupId} with a given name
688         * and returns the ID of the newly created channel group.
689         *
690         * @param sourceGroupId
691         *              the ID of the channel group to copy
692         * @param targetName
693         *              the name for the copy of the channel group
694         * @param type
695         *              the desired type of channel group
696         *
697         * @return the ID of the newly created channel group
698         *
699         * @throws TS3CommandFailedException
700         *              if the execution of a command fails
701         * @querycommands 1
702         * @see ChannelGroup#getId()
703         */
704        public int copyChannelGroup(int sourceGroupId, String targetName, PermissionGroupDatabaseType type) {
705                return asyncApi.copyChannelGroup(sourceGroupId, targetName, type).getUninterruptibly();
706        }
707
708        /**
709         * Creates a copy of the server group specified by {@code sourceGroupId},
710         * overwriting another server group specified by {@code targetGroupId}.
711         * <p>
712         * The parameter {@code type} can be used to create server query and template groups.
713         * </p>
714         *
715         * @param sourceGroupId
716         *              the ID of the server group to copy
717         * @param targetGroupId
718         *              the ID of another server group to overwrite
719         * @param type
720         *              the desired type of server group
721         *
722         * @return the ID of the newly created server group
723         *
724         * @throws TS3CommandFailedException
725         *              if the execution of a command fails
726         * @querycommands 1
727         * @see ServerGroup#getId()
728         */
729        public int copyServerGroup(int sourceGroupId, int targetGroupId, PermissionGroupDatabaseType type) {
730                return asyncApi.copyServerGroup(sourceGroupId, targetGroupId, type).getUninterruptibly();
731        }
732
733        /**
734         * Creates a copy of the server group specified by {@code sourceGroupId} with a given name
735         * and returns the ID of the newly created server group.
736         *
737         * @param sourceGroupId
738         *              the ID of the server group to copy
739         * @param targetName
740         *              the name for the copy of the server group
741         * @param type
742         *              the desired type of server group
743         *
744         * @return the ID of the newly created server group
745         *
746         * @throws TS3CommandFailedException
747         *              if the execution of a command fails
748         * @querycommands 1
749         * @see ServerGroup#getId()
750         */
751        public int copyServerGroup(int sourceGroupId, String targetName, PermissionGroupDatabaseType type) {
752                return asyncApi.copyServerGroup(sourceGroupId, targetName, type).getUninterruptibly();
753        }
754
755        /**
756         * Creates a new channel with a given name using the given properties and returns its ID.
757         *
758         * @param name
759         *              the name for the new channel
760         * @param options
761         *              a map of options that should be set for the channel
762         *
763         * @return the ID of the newly created channel
764         *
765         * @throws TS3CommandFailedException
766         *              if the execution of a command fails
767         * @querycommands 1
768         * @see Channel
769         */
770        public int createChannel(String name, Map<ChannelProperty, String> options) {
771                return asyncApi.createChannel(name, options).getUninterruptibly();
772        }
773
774        /**
775         * Creates a new directory on the file repository in the specified channel.
776         *
777         * @param directoryPath
778         *              the path to the directory that should be created
779         * @param channelId
780         *              the ID of the channel the directory should be created in
781         *
782         * @throws TS3CommandFailedException
783         *              if the execution of a command fails
784         * @querycommands 1
785         * @see FileInfo#getPath()
786         * @see Channel#getId()
787         */
788        public void createFileDirectory(String directoryPath, int channelId) {
789                asyncApi.createFileDirectory(directoryPath, channelId).getUninterruptibly();
790        }
791
792        /**
793         * Creates a new directory on the file repository in the specified channel.
794         *
795         * @param directoryPath
796         *              the path to the directory that should be created
797         * @param channelId
798         *              the ID of the channel the directory should be created in
799         * @param channelPassword
800         *              the password of that channel
801         *
802         * @throws TS3CommandFailedException
803         *              if the execution of a command fails
804         * @querycommands 1
805         * @see FileInfo#getPath()
806         * @see Channel#getId()
807         */
808        public void createFileDirectory(String directoryPath, int channelId, String channelPassword) {
809                asyncApi.createFileDirectory(directoryPath, channelId, channelPassword).getUninterruptibly();
810        }
811
812        /**
813         * Creates a new virtual server with the given name and returns an object containing the ID of the newly
814         * created virtual server, the default server admin token and the virtual server's voice port. Usually,
815         * the virtual server is also automatically started. This can be turned off on the TS3 server, though.
816         * <p>
817         * If {@link VirtualServerProperty#VIRTUALSERVER_PORT} is not specified in the virtual server properties,
818         * the server will test for the first unused UDP port.
819         * </p><p>
820         * Please also note that creating virtual servers usually requires the server query admin account
821         * and that there is a limit to how many virtual servers can be created, which is dependent on your license.
822         * Unlicensed TS3 server instances are limited to 1 virtual server with up to 32 client slots.
823         * </p>
824         *
825         * @param name
826         *              the name for the new virtual server
827         * @param options
828         *              a map of options that should be set for the virtual server
829         *
830         * @return information about the newly created virtual server
831         *
832         * @throws TS3CommandFailedException
833         *              if the execution of a command fails
834         * @querycommands 1
835         * @see VirtualServer
836         */
837        public CreatedVirtualServer createServer(String name, Map<VirtualServerProperty, String> options) {
838                return asyncApi.createServer(name, options).getUninterruptibly();
839        }
840
841        /**
842         * Creates a {@link Snapshot} of the selected virtual server containing all settings,
843         * groups and known client identities. The data from a server snapshot can be
844         * used to restore a virtual servers configuration.
845         *
846         * @return a snapshot of the virtual server
847         *
848         * @throws TS3CommandFailedException
849         *              if the execution of a command fails
850         * @querycommands 1
851         * @see #deployServerSnapshot(Snapshot)
852         */
853        public Snapshot createServerSnapshot() {
854                return asyncApi.createServerSnapshot().getUninterruptibly();
855        }
856
857        /**
858         * Deletes all active ban rules from the server. Use with caution.
859         *
860         * @throws TS3CommandFailedException
861         *              if the execution of a command fails
862         * @querycommands 1
863         */
864        public void deleteAllBans() {
865                asyncApi.deleteAllBans().getUninterruptibly();
866        }
867
868        /**
869         * Deletes all complaints about the client with specified database ID from the server.
870         *
871         * @param clientDBId
872         *              the database ID of the client
873         *
874         * @throws TS3CommandFailedException
875         *              if the execution of a command fails
876         * @querycommands 1
877         * @see Client#getDatabaseId()
878         * @see Complaint
879         */
880        public void deleteAllComplaints(int clientDBId) {
881                asyncApi.deleteAllComplaints(clientDBId).getUninterruptibly();
882        }
883
884        /**
885         * Deletes the ban rule with the specified ID from the server.
886         *
887         * @param banId
888         *              the ID of the ban to delete
889         *
890         * @throws TS3CommandFailedException
891         *              if the execution of a command fails
892         * @querycommands 1
893         * @see Ban#getId()
894         */
895        public void deleteBan(int banId) {
896                asyncApi.deleteBan(banId).getUninterruptibly();
897        }
898
899        /**
900         * Deletes an existing channel specified by its ID, kicking all clients out of the channel.
901         *
902         * @param channelId
903         *              the ID of the channel to delete
904         *
905         * @throws TS3CommandFailedException
906         *              if the execution of a command fails
907         * @querycommands 1
908         * @see Channel#getId()
909         * @see #deleteChannel(int, boolean)
910         * @see #kickClientFromChannel(String, int...)
911         */
912        public void deleteChannel(int channelId) {
913                asyncApi.deleteChannel(channelId).getUninterruptibly();
914        }
915
916        /**
917         * Deletes an existing channel with a given ID.
918         * If {@code force} is true, the channel will be deleted even if there are clients within,
919         * else the command will fail in this situation.
920         *
921         * @param channelId
922         *              the ID of the channel to delete
923         * @param force
924         *              whether clients should be kicked out of the channel
925         *
926         * @throws TS3CommandFailedException
927         *              if the execution of a command fails
928         * @querycommands 1
929         * @see Channel#getId()
930         * @see #kickClientFromChannel(String, int...)
931         */
932        public void deleteChannel(int channelId, boolean force) {
933                asyncApi.deleteChannel(channelId, force).getUninterruptibly();
934        }
935
936        /**
937         * Removes a specified permission from a client in a specific channel.
938         *
939         * @param channelId
940         *              the ID of the channel wherein the permission should be removed
941         * @param clientDBId
942         *              the database ID of the client
943         * @param permName
944         *              the name of the permission to revoke
945         *
946         * @throws TS3CommandFailedException
947         *              if the execution of a command fails
948         * @querycommands 1
949         * @see Channel#getId()
950         * @see Client#getDatabaseId()
951         * @see Permission#getName()
952         */
953        public void deleteChannelClientPermission(int channelId, int clientDBId, String permName) {
954                asyncApi.deleteChannelClientPermission(channelId, clientDBId, permName).getUninterruptibly();
955        }
956
957        /**
958         * Removes the channel group with the given ID.
959         *
960         * @param groupId
961         *              the ID of the channel group
962         *
963         * @throws TS3CommandFailedException
964         *              if the execution of a command fails
965         * @querycommands 1
966         * @see ChannelGroup#getId()
967         */
968        public void deleteChannelGroup(int groupId) {
969                asyncApi.deleteChannelGroup(groupId).getUninterruptibly();
970        }
971
972        /**
973         * Removes the channel group with the given ID.
974         * If {@code force} is true, the channel group will be deleted even if it still contains clients,
975         * else the command will fail in this situation.
976         *
977         * @param groupId
978         *              the ID of the channel group
979         * @param force
980         *              whether the channel group should be deleted even if it still contains clients
981         *
982         * @throws TS3CommandFailedException
983         *              if the execution of a command fails
984         * @querycommands 1
985         * @see ChannelGroup#getId()
986         */
987        public void deleteChannelGroup(int groupId, boolean force) {
988                asyncApi.deleteChannelGroup(groupId, force).getUninterruptibly();
989        }
990
991        /**
992         * Removes a permission from the channel group with the given ID.
993         *
994         * @param groupId
995         *              the ID of the channel group
996         * @param permName
997         *              the name of the permission to revoke
998         *
999         * @throws TS3CommandFailedException
1000         *              if the execution of a command fails
1001         * @querycommands 1
1002         * @see ChannelGroup#getId()
1003         * @see Permission#getName()
1004         */
1005        public void deleteChannelGroupPermission(int groupId, String permName) {
1006                asyncApi.deleteChannelGroupPermission(groupId, permName).getUninterruptibly();
1007        }
1008
1009        /**
1010         * Removes a permission from the channel with the given ID.
1011         *
1012         * @param channelId
1013         *              the ID of the channel
1014         * @param permName
1015         *              the name of the permission to revoke
1016         *
1017         * @throws TS3CommandFailedException
1018         *              if the execution of a command fails
1019         * @querycommands 1
1020         * @see Channel#getId()
1021         * @see Permission#getName()
1022         */
1023        public void deleteChannelPermission(int channelId, String permName) {
1024                asyncApi.deleteChannelPermission(channelId, permName).getUninterruptibly();
1025        }
1026
1027        /**
1028         * Removes a permission from a client.
1029         *
1030         * @param clientDBId
1031         *              the database ID of the client
1032         * @param permName
1033         *              the name of the permission to revoke
1034         *
1035         * @throws TS3CommandFailedException
1036         *              if the execution of a command fails
1037         * @querycommands 1
1038         * @see Client#getDatabaseId()
1039         * @see Permission#getName()
1040         */
1041        public void deleteClientPermission(int clientDBId, String permName) {
1042                asyncApi.deleteClientPermission(clientDBId, permName).getUninterruptibly();
1043        }
1044
1045        /**
1046         * Deletes the complaint about the client with database ID {@code targetClientDBId} submitted by
1047         * the client with database ID {@code fromClientDBId} from the server.
1048         *
1049         * @param targetClientDBId
1050         *              the database ID of the client the complaint is about
1051         * @param fromClientDBId
1052         *              the database ID of the client who added the complaint
1053         *
1054         * @throws TS3CommandFailedException
1055         *              if the execution of a command fails
1056         * @querycommands 1
1057         * @see Complaint
1058         * @see Client#getDatabaseId()
1059         */
1060        public void deleteComplaint(int targetClientDBId, int fromClientDBId) {
1061                asyncApi.deleteComplaint(targetClientDBId, fromClientDBId).getUninterruptibly();
1062        }
1063
1064        /**
1065         * Removes the {@code key} custom client property from a client.
1066         *
1067         * @param clientDBId
1068         *              the database ID of the target client
1069         * @param key
1070         *              the key of the custom property to delete, cannot be {@code null}
1071         *
1072         * @throws TS3CommandFailedException
1073         *              if the execution of a command fails
1074         * @querycommands 1
1075         * @see Client#getDatabaseId()
1076         */
1077        public void deleteCustomClientProperty(int clientDBId, String key) {
1078                asyncApi.deleteCustomClientProperty(clientDBId, key).getUninterruptibly();
1079        }
1080
1081        /**
1082         * Removes all stored database information about the specified client.
1083         * Please note that this data is also automatically removed after a configured time (usually 90 days).
1084         * <p>
1085         * See {@link DatabaseClientInfo} for a list of stored information about a client.
1086         * </p>
1087         *
1088         * @param clientDBId
1089         *              the database ID of the client
1090         *
1091         * @throws TS3CommandFailedException
1092         *              if the execution of a command fails
1093         * @querycommands 1
1094         * @see Client#getDatabaseId()
1095         * @see #getDatabaseClientInfo(int)
1096         * @see DatabaseClientInfo
1097         */
1098        public void deleteDatabaseClientProperties(int clientDBId) {
1099                asyncApi.deleteDatabaseClientProperties(clientDBId).getUninterruptibly();
1100        }
1101
1102        /**
1103         * Deletes a file or directory from the file repository in the specified channel.
1104         *
1105         * @param filePath
1106         *              the path to the file or directory
1107         * @param channelId
1108         *              the ID of the channel the file or directory resides in
1109         *
1110         * @throws TS3CommandFailedException
1111         *              if the execution of a command fails
1112         * @querycommands 1
1113         * @see FileInfo#getPath()
1114         * @see Channel#getId()
1115         */
1116        public void deleteFile(String filePath, int channelId) {
1117                asyncApi.deleteFile(filePath, channelId).getUninterruptibly();
1118        }
1119
1120        /**
1121         * Deletes a file or directory from the file repository in the specified channel.
1122         *
1123         * @param filePath
1124         *              the path to the file or directory
1125         * @param channelId
1126         *              the ID of the channel the file or directory resides in
1127         * @param channelPassword
1128         *              the password of that channel
1129         *
1130         * @throws TS3CommandFailedException
1131         *              if the execution of a command fails
1132         * @querycommands 1
1133         * @see FileInfo#getPath()
1134         * @see Channel#getId()
1135         */
1136        public void deleteFile(String filePath, int channelId, String channelPassword) {
1137                asyncApi.deleteFile(filePath, channelId, channelPassword).getUninterruptibly();
1138        }
1139
1140        /**
1141         * Deletes multiple files or directories from the file repository in the specified channel.
1142         *
1143         * @param filePaths
1144         *              the paths to the files or directories
1145         * @param channelId
1146         *              the ID of the channel the file or directory resides in
1147         *
1148         * @throws TS3CommandFailedException
1149         *              if the execution of a command fails
1150         * @querycommands 1
1151         * @see FileInfo#getPath()
1152         * @see Channel#getId()
1153         */
1154        public void deleteFiles(String[] filePaths, int channelId) {
1155                asyncApi.deleteFiles(filePaths, channelId).getUninterruptibly();
1156        }
1157
1158        /**
1159         * Deletes multiple files or directories from the file repository in the specified channel.
1160         *
1161         * @param filePaths
1162         *              the paths to the files or directories
1163         * @param channelId
1164         *              the ID of the channel the file or directory resides in
1165         * @param channelPassword
1166         *              the password of that channel
1167         *
1168         * @throws TS3CommandFailedException
1169         *              if the execution of a command fails
1170         * @querycommands 1
1171         * @see FileInfo#getPath()
1172         * @see Channel#getId()
1173         */
1174        public void deleteFiles(String[] filePaths, int channelId, String channelPassword) {
1175                asyncApi.deleteFiles(filePaths, channelId, channelPassword).getUninterruptibly();
1176        }
1177
1178        /**
1179         * Deletes an icon from the icon directory in the file repository.
1180         *
1181         * @param iconId
1182         *              the ID of the icon to delete
1183         *
1184         * @throws TS3CommandFailedException
1185         *              if the execution of a command fails
1186         * @querycommands 1
1187         * @see IconFile#getIconId()
1188         */
1189        public void deleteIcon(long iconId) {
1190                asyncApi.deleteIcon(iconId).getUninterruptibly();
1191        }
1192
1193        /**
1194         * Deletes multiple icons from the icon directory in the file repository.
1195         *
1196         * @param iconIds
1197         *              the IDs of the icons to delete
1198         *
1199         * @throws TS3CommandFailedException
1200         *              if the execution of a command fails
1201         * @querycommands 1
1202         * @see IconFile#getIconId()
1203         */
1204        public void deleteIcons(long... iconIds) {
1205                asyncApi.deleteIcons(iconIds).getUninterruptibly();
1206        }
1207
1208        /**
1209         * Deletes the offline message with the specified ID.
1210         *
1211         * @param messageId
1212         *              the ID of the offline message to delete
1213         *
1214         * @throws TS3CommandFailedException
1215         *              if the execution of a command fails
1216         * @querycommands 1
1217         * @see Message#getId()
1218         */
1219        public void deleteOfflineMessage(int messageId) {
1220                asyncApi.deleteOfflineMessage(messageId).getUninterruptibly();
1221        }
1222
1223        /**
1224         * Removes a specified permission from all server groups of the type specified by {@code type} on all virtual servers.
1225         *
1226         * @param type
1227         *              the kind of server group this permission should be removed from
1228         * @param permName
1229         *              the name of the permission to remove
1230         *
1231         * @throws TS3CommandFailedException
1232         *              if the execution of a command fails
1233         * @querycommands 1
1234         * @see ServerGroupType
1235         * @see Permission#getName()
1236         */
1237        public void deletePermissionFromAllServerGroups(ServerGroupType type, String permName) {
1238                asyncApi.deletePermissionFromAllServerGroups(type, permName).getUninterruptibly();
1239        }
1240
1241        /**
1242         * Deletes the privilege key with the given token.
1243         *
1244         * @param token
1245         *              the token of the privilege key
1246         *
1247         * @throws TS3CommandFailedException
1248         *              if the execution of a command fails
1249         * @querycommands 1
1250         * @see PrivilegeKey
1251         */
1252        public void deletePrivilegeKey(String token) {
1253                asyncApi.deletePrivilegeKey(token).getUninterruptibly();
1254        }
1255
1256        /**
1257         * Deletes the virtual server with the specified ID.
1258         * <p>
1259         * Only stopped virtual servers can be deleted.
1260         * </p>
1261         *
1262         * @param serverId
1263         *              the ID of the virtual server
1264         *
1265         * @throws TS3CommandFailedException
1266         *              if the execution of a command fails
1267         * @querycommands 1
1268         * @see VirtualServer#getId()
1269         * @see #stopServer(int)
1270         */
1271        public void deleteServer(int serverId) {
1272                asyncApi.deleteServer(serverId).getUninterruptibly();
1273        }
1274
1275        /**
1276         * Deletes the server group with the specified ID, even if the server group still contains clients.
1277         *
1278         * @param groupId
1279         *              the ID of the server group
1280         *
1281         * @throws TS3CommandFailedException
1282         *              if the execution of a command fails
1283         * @querycommands 1
1284         * @see ServerGroup#getId()
1285         */
1286        public void deleteServerGroup(int groupId) {
1287                asyncApi.deleteServerGroup(groupId).getUninterruptibly();
1288        }
1289
1290        /**
1291         * Deletes a server group with the specified ID.
1292         * <p>
1293         * If {@code force} is true, the server group will be deleted even if it contains clients,
1294         * else the command will fail in this situation.
1295         * </p>
1296         *
1297         * @param groupId
1298         *              the ID of the server group
1299         * @param force
1300         *              whether the server group should be deleted if it still contains clients
1301         *
1302         * @throws TS3CommandFailedException
1303         *              if the execution of a command fails
1304         * @querycommands 1
1305         * @see ServerGroup#getId()
1306         */
1307        public void deleteServerGroup(int groupId, boolean force) {
1308                asyncApi.deleteServerGroup(groupId, force).getUninterruptibly();
1309        }
1310
1311        /**
1312         * Removes a permission from the server group with the given ID.
1313         *
1314         * @param groupId
1315         *              the ID of the server group
1316         * @param permName
1317         *              the name of the permission to revoke
1318         *
1319         * @throws TS3CommandFailedException
1320         *              if the execution of a command fails
1321         * @querycommands 1
1322         * @see ServerGroup#getId()
1323         * @see Permission#getName()
1324         */
1325        public void deleteServerGroupPermission(int groupId, String permName) {
1326                asyncApi.deleteServerGroupPermission(groupId, permName).getUninterruptibly();
1327        }
1328
1329        /**
1330         * Deletes the server query login with the specified client database ID.
1331         * <p>
1332         * If you only know the name of the server query login, use {@link #getServerQueryLoginsByName(String)} first.
1333         * </p>
1334         *
1335         * @param clientDBId
1336         *              the client database ID of the server query login (usually the ID of the associated client)
1337         *
1338         * @throws TS3CommandFailedException
1339         *              if the execution of a command fails
1340         * @querycommands 1
1341         * @see #addServerQueryLogin(String, int)
1342         * @see #getServerQueryLogins()
1343         * @see #updateServerQueryLogin(String)
1344         */
1345        public void deleteServerQueryLogin(int clientDBId) {
1346                asyncApi.deleteServerQueryLogin(clientDBId).getUninterruptibly();
1347        }
1348
1349        /**
1350         * Restores the selected virtual servers configuration using the data from a
1351         * previously created server snapshot.
1352         *
1353         * @param snapshot
1354         *              the snapshot to restore
1355         *
1356         * @throws TS3CommandFailedException
1357         *              if the execution of a command fails
1358         * @querycommands 1
1359         * @see #createServerSnapshot()
1360         */
1361        public void deployServerSnapshot(Snapshot snapshot) {
1362                asyncApi.deployServerSnapshot(snapshot).getUninterruptibly();
1363        }
1364
1365        /**
1366         * Restores the configuration of the selected virtual server using the data from a
1367         * previously created server snapshot.
1368         *
1369         * @param snapshot
1370         *              the snapshot to restore
1371         *
1372         * @throws TS3CommandFailedException
1373         *              if the execution of a command fails
1374         * @querycommands 1
1375         * @see #createServerSnapshot()
1376         */
1377        public void deployServerSnapshot(String snapshot) {
1378                asyncApi.deployServerSnapshot(snapshot).getUninterruptibly();
1379        }
1380
1381        /**
1382         * Downloads a file from the file repository at a given path and channel
1383         * and writes the file's bytes to an open {@link OutputStream}.
1384         * <p>
1385         * It is the user's responsibility to ensure that the given {@code OutputStream} is
1386         * open and to close the stream again once the download has finished.
1387         * </p><p>
1388         * Note that this method will not read the entire file to memory and can thus
1389         * download arbitrarily sized files from the file repository.
1390         * </p>
1391         *
1392         * @param dataOut
1393         *              a stream that the downloaded data should be written to
1394         * @param filePath
1395         *              the path of the file on the file repository
1396         * @param channelId
1397         *              the ID of the channel to download the file from
1398         *
1399         * @return how many bytes were downloaded
1400         *
1401         * @throws TS3CommandFailedException
1402         *              if the execution of a command fails
1403         * @throws TS3FileTransferFailedException
1404         *              if the file transfer fails for any reason
1405         * @querycommands 1
1406         * @see FileInfo#getPath()
1407         * @see Channel#getId()
1408         * @see #downloadFileDirect(String, int)
1409         */
1410        public long downloadFile(OutputStream dataOut, String filePath, int channelId) {
1411                return asyncApi.downloadFile(dataOut, filePath, channelId).getUninterruptibly();
1412        }
1413
1414        /**
1415         * Downloads a file from the file repository at a given path and channel
1416         * and writes the file's bytes to an open {@link OutputStream}.
1417         * <p>
1418         * It is the user's responsibility to ensure that the given {@code OutputStream} is
1419         * open and to close the stream again once the download has finished.
1420         * </p><p>
1421         * Note that this method will not read the entire file to memory and can thus
1422         * download arbitrarily sized files from the file repository.
1423         * </p>
1424         *
1425         * @param dataOut
1426         *              a stream that the downloaded data should be written to
1427         * @param filePath
1428         *              the path of the file on the file repository
1429         * @param channelId
1430         *              the ID of the channel to download the file from
1431         * @param channelPassword
1432         *              that channel's password
1433         *
1434         * @return how many bytes were downloaded
1435         *
1436         * @throws TS3CommandFailedException
1437         *              if the execution of a command fails
1438         * @throws TS3FileTransferFailedException
1439         *              if the file transfer fails for any reason
1440         * @querycommands 1
1441         * @see FileInfo#getPath()
1442         * @see Channel#getId()
1443         * @see #downloadFileDirect(String, int, String)
1444         */
1445        public long downloadFile(OutputStream dataOut, String filePath, int channelId, String channelPassword) {
1446                return asyncApi.downloadFile(dataOut, filePath, channelId, channelPassword).getUninterruptibly();
1447        }
1448
1449        /**
1450         * Downloads a file from the file repository at a given path and channel
1451         * and returns the file's bytes as a byte array.
1452         * <p>
1453         * Note that this method <strong>will read the entire file to memory</strong>.
1454         * That means that if a file is larger than 2<sup>31</sup>-1 bytes in size,
1455         * the download will fail.
1456         * </p>
1457         *
1458         * @param filePath
1459         *              the path of the file on the file repository
1460         * @param channelId
1461         *              the ID of the channel to download the file from
1462         *
1463         * @return a byte array containing the file's data
1464         *
1465         * @throws TS3CommandFailedException
1466         *              if the execution of a command fails
1467         * @throws TS3FileTransferFailedException
1468         *              if the file transfer fails for any reason
1469         * @querycommands 1
1470         * @see FileInfo#getPath()
1471         * @see Channel#getId()
1472         * @see #downloadFile(OutputStream, String, int)
1473         */
1474        public byte[] downloadFileDirect(String filePath, int channelId) {
1475                return asyncApi.downloadFileDirect(filePath, channelId).getUninterruptibly();
1476        }
1477
1478        /**
1479         * Downloads a file from the file repository at a given path and channel
1480         * and returns the file's bytes as a byte array.
1481         * <p>
1482         * Note that this method <strong>will read the entire file to memory</strong>.
1483         * That means that if a file is larger than 2<sup>31</sup>-1 bytes in size,
1484         * the download will fail.
1485         * </p>
1486         *
1487         * @param filePath
1488         *              the path of the file on the file repository
1489         * @param channelId
1490         *              the ID of the channel to download the file from
1491         * @param channelPassword
1492         *              that channel's password
1493         *
1494         * @return a byte array containing the file's data
1495         *
1496         * @throws TS3CommandFailedException
1497         *              if the execution of a command fails
1498         * @throws TS3FileTransferFailedException
1499         *              if the file transfer fails for any reason
1500         * @querycommands 1
1501         * @see FileInfo#getPath()
1502         * @see Channel#getId()
1503         * @see #downloadFile(OutputStream, String, int, String)
1504         */
1505        public byte[] downloadFileDirect(String filePath, int channelId, String channelPassword) {
1506                return asyncApi.downloadFileDirect(filePath, channelId, channelPassword).getUninterruptibly();
1507        }
1508
1509        /**
1510         * Downloads an icon from the icon directory in the file repository
1511         * and writes the file's bytes to an open {@link OutputStream}.
1512         * <p>
1513         * It is the user's responsibility to ensure that the given {@code OutputStream} is
1514         * open and to close the stream again once the download has finished.
1515         * </p>
1516         *
1517         * @param dataOut
1518         *              a stream that the downloaded data should be written to
1519         * @param iconId
1520         *              the ID of the icon that should be downloaded
1521         *
1522         * @return a byte array containing the icon file's data
1523         *
1524         * @throws TS3CommandFailedException
1525         *              if the execution of a command fails
1526         * @throws TS3FileTransferFailedException
1527         *              if the file transfer fails for any reason
1528         * @querycommands 1
1529         * @see IconFile#getIconId()
1530         * @see #downloadIconDirect(long)
1531         * @see #uploadIcon(InputStream, long)
1532         */
1533        public long downloadIcon(OutputStream dataOut, long iconId) {
1534                return asyncApi.downloadIcon(dataOut, iconId).getUninterruptibly();
1535        }
1536
1537        /**
1538         * Downloads an icon from the icon directory in the file repository
1539         * and returns the file's bytes as a byte array.
1540         * <p>
1541         * Note that this method <strong>will read the entire file to memory</strong>.
1542         * </p>
1543         *
1544         * @param iconId
1545         *              the ID of the icon that should be downloaded
1546         *
1547         * @return a byte array containing the icon file's data
1548         *
1549         * @throws TS3CommandFailedException
1550         *              if the execution of a command fails
1551         * @throws TS3FileTransferFailedException
1552         *              if the file transfer fails for any reason
1553         * @querycommands 1
1554         * @see IconFile#getIconId()
1555         * @see #downloadIcon(OutputStream, long)
1556         * @see #uploadIconDirect(byte[])
1557         */
1558        public byte[] downloadIconDirect(long iconId) {
1559                return asyncApi.downloadIconDirect(iconId).getUninterruptibly();
1560        }
1561
1562        /**
1563         * Changes a channel's configuration using the given properties.
1564         *
1565         * @param channelId
1566         *              the ID of the channel to edit
1567         * @param options
1568         *              the map of properties to modify
1569         *
1570         * @throws TS3CommandFailedException
1571         *              if the execution of a command fails
1572         * @querycommands 1
1573         * @see Channel#getId()
1574         */
1575        public void editChannel(int channelId, Map<ChannelProperty, String> options) {
1576                asyncApi.editChannel(channelId, options).getUninterruptibly();
1577        }
1578
1579        /**
1580         * Changes a single property of the given channel.
1581         * <p>
1582         * Note that one can set many properties at once with the overloaded method that
1583         * takes a map of channel properties and strings.
1584         * </p>
1585         *
1586         * @param channelId
1587         *              the ID of the channel to edit
1588         * @param property
1589         *              the channel property to modify, make sure it is editable
1590         * @param value
1591         *              the new value of the property
1592         *
1593         * @throws TS3CommandFailedException
1594         *              if the execution of a command fails
1595         * @querycommands 1
1596         * @see Channel#getId()
1597         * @see #editChannel(int, Map)
1598         */
1599        public void editChannel(int channelId, ChannelProperty property, String value) {
1600                asyncApi.editChannel(channelId, property, value).getUninterruptibly();
1601        }
1602
1603        /**
1604         * Changes a client's configuration using given properties.
1605         * <p>
1606         * Only {@link ClientProperty#CLIENT_DESCRIPTION} can be changed for other clients.
1607         * To update the current client's properties, use {@link #updateClient(Map)}
1608         * or {@link #updateClient(ClientProperty, String)}.
1609         * </p>
1610         *
1611         * @param clientId
1612         *              the ID of the client to edit
1613         * @param options
1614         *              the map of properties to modify
1615         *
1616         * @throws TS3CommandFailedException
1617         *              if the execution of a command fails
1618         * @querycommands 1
1619         * @see Client#getId()
1620         * @see #updateClient(Map)
1621         */
1622        public void editClient(int clientId, Map<ClientProperty, String> options) {
1623                asyncApi.editClient(clientId, options).getUninterruptibly();
1624        }
1625
1626        /**
1627         * Changes a single property of the given client.
1628         * <p>
1629         * Only {@link ClientProperty#CLIENT_DESCRIPTION} can be changed for other clients.
1630         * To update the current client's properties, use {@link #updateClient(Map)}
1631         * or {@link #updateClient(ClientProperty, String)}.
1632         * </p>
1633         *
1634         * @param clientId
1635         *              the ID of the client to edit
1636         * @param property
1637         *              the client property to modify, make sure it is editable
1638         * @param value
1639         *              the new value of the property
1640         *
1641         * @throws TS3CommandFailedException
1642         *              if the execution of a command fails
1643         * @querycommands 1
1644         * @see Client#getId()
1645         * @see #editClient(int, Map)
1646         * @see #updateClient(Map)
1647         */
1648        public void editClient(int clientId, ClientProperty property, String value) {
1649                asyncApi.editClient(clientId, property, value).getUninterruptibly();
1650        }
1651
1652        /**
1653         * Changes a client's database settings using given properties.
1654         *
1655         * @param clientDBId
1656         *              the database ID of the client to edit
1657         * @param options
1658         *              the map of properties to modify
1659         *
1660         * @throws TS3CommandFailedException
1661         *              if the execution of a command fails
1662         * @querycommands 1
1663         * @see DatabaseClientInfo
1664         * @see Client#getDatabaseId()
1665         */
1666        public void editDatabaseClient(int clientDBId, Map<ClientProperty, String> options) {
1667                asyncApi.editDatabaseClient(clientDBId, options).getUninterruptibly();
1668        }
1669
1670        /**
1671         * Changes the server instance configuration using given properties.
1672         * If the given property is not changeable, {@code IllegalArgumentException} will be thrown.
1673         *
1674         * @param property
1675         *              the property to edit, must be changeable
1676         * @param value
1677         *              the new value for the edit
1678         *
1679         * @throws IllegalArgumentException
1680         *              if {@code property} is not changeable
1681         * @throws TS3CommandFailedException
1682         *              if the execution of a command fails
1683         * @querycommands 1
1684         * @see ServerInstanceProperty#isChangeable()
1685         */
1686        public void editInstance(ServerInstanceProperty property, String value) {
1687                asyncApi.editInstance(property, value).getUninterruptibly();
1688        }
1689
1690        /**
1691         * Changes the configuration of the selected virtual server using given properties.
1692         *
1693         * @param options
1694         *              the map of properties to edit
1695         *
1696         * @throws TS3CommandFailedException
1697         *              if the execution of a command fails
1698         * @querycommands 1
1699         * @see VirtualServerProperty
1700         */
1701        public void editServer(Map<VirtualServerProperty, String> options) {
1702                asyncApi.editServer(options).getUninterruptibly();
1703        }
1704
1705        /**
1706         * Gets a list of all bans on the selected virtual server.
1707         *
1708         * @return a list of all bans on the virtual server
1709         *
1710         * @throws TS3CommandFailedException
1711         *              if the execution of a command fails
1712         * @querycommands 1
1713         * @see Ban
1714         */
1715        public List<Ban> getBans() {
1716                return asyncApi.getBans().getUninterruptibly();
1717        }
1718
1719        /**
1720         * Gets a list of IP addresses used by the server instance.
1721         *
1722         * @return the list of bound IP addresses
1723         *
1724         * @throws TS3CommandFailedException
1725         *              if the execution of a command fails
1726         * @querycommands 1
1727         * @see Binding
1728         */
1729        public List<Binding> getBindings() {
1730                return asyncApi.getBindings().getUninterruptibly();
1731        }
1732
1733        /**
1734         * Finds and returns the channel matching the given name exactly.
1735         *
1736         * @param name
1737         *              the name of the channel
1738         * @param ignoreCase
1739         *              whether the case of the name should be ignored
1740         *
1741         * @return the found channel or {@code null} if no channel was found
1742         *
1743         * @throws TS3CommandFailedException
1744         *              if the execution of a command fails
1745         * @querycommands 1
1746         * @see Channel
1747         * @see #getChannelsByName(String)
1748         */
1749        public Channel getChannelByNameExact(String name, boolean ignoreCase) {
1750                return asyncApi.getChannelByNameExact(name, ignoreCase).getUninterruptibly();
1751        }
1752
1753        /**
1754         * Gets a list of channels whose names contain the given search string.
1755         *
1756         * @param name
1757         *              the name to search
1758         *
1759         * @return a list of all channels with names matching the search pattern
1760         *
1761         * @throws TS3CommandFailedException
1762         *              if the execution of a command fails
1763         * @querycommands 2
1764         * @see Channel
1765         * @see #getChannelByNameExact(String, boolean)
1766         */
1767        public List<Channel> getChannelsByName(String name) {
1768                return asyncApi.getChannelsByName(name).getUninterruptibly();
1769        }
1770
1771        /**
1772         * Displays a list of permissions defined for a client in a specific channel.
1773         *
1774         * @param channelId
1775         *              the ID of the channel
1776         * @param clientDBId
1777         *              the database ID of the client
1778         *
1779         * @return a list of permissions for the user in the specified channel
1780         *
1781         * @throws TS3CommandFailedException
1782         *              if the execution of a command fails
1783         * @querycommands 1
1784         * @see Channel#getId()
1785         * @see Client#getDatabaseId()
1786         * @see Permission
1787         */
1788        public List<Permission> getChannelClientPermissions(int channelId, int clientDBId) {
1789                return asyncApi.getChannelClientPermissions(channelId, clientDBId).getUninterruptibly();
1790        }
1791
1792        /**
1793         * Gets all client / channel ID combinations currently assigned to channel groups.
1794         * All three parameters are optional and can be turned off by setting it to {@code -1}.
1795         *
1796         * @param channelId
1797         *              restricts the search to the channel with a specified ID. Set to {@code -1} to ignore.
1798         * @param clientDBId
1799         *              restricts the search to the client with a specified database ID. Set to {@code -1} to ignore.
1800         * @param groupId
1801         *              restricts the search to the channel group with the specified ID. Set to {@code -1} to ignore.
1802         *
1803         * @return a list of combinations of channel ID, client database ID and channel group ID
1804         *
1805         * @throws TS3CommandFailedException
1806         *              if the execution of a command fails
1807         * @querycommands 1
1808         * @see Channel#getId()
1809         * @see Client#getDatabaseId()
1810         * @see ChannelGroup#getId()
1811         * @see ChannelGroupClient
1812         */
1813        public List<ChannelGroupClient> getChannelGroupClients(int channelId, int clientDBId, int groupId) {
1814                return asyncApi.getChannelGroupClients(channelId, clientDBId, groupId).getUninterruptibly();
1815        }
1816
1817        /**
1818         * Gets all client / channel ID combinations currently assigned to the specified channel group.
1819         *
1820         * @param groupId
1821         *              the ID of the channel group whose client / channel assignments should be returned.
1822         *
1823         * @return a list of combinations of channel ID, client database ID and channel group ID
1824         *
1825         * @throws TS3CommandFailedException
1826         *              if the execution of a command fails
1827         * @querycommands 1
1828         * @see ChannelGroup#getId()
1829         * @see ChannelGroupClient
1830         * @see #getChannelGroupClients(int, int, int)
1831         */
1832        public List<ChannelGroupClient> getChannelGroupClientsByChannelGroupId(int groupId) {
1833                return asyncApi.getChannelGroupClientsByChannelGroupId(groupId).getUninterruptibly();
1834        }
1835
1836        /**
1837         * Gets all channel group assignments in the specified channel.
1838         *
1839         * @param channelId
1840         *              the ID of the channel whose channel group assignments should be returned.
1841         *
1842         * @return a list of combinations of channel ID, client database ID and channel group ID
1843         *
1844         * @throws TS3CommandFailedException
1845         *              if the execution of a command fails
1846         * @querycommands 1
1847         * @see Channel#getId()
1848         * @see ChannelGroupClient
1849         * @see #getChannelGroupClients(int, int, int)
1850         */
1851        public List<ChannelGroupClient> getChannelGroupClientsByChannelId(int channelId) {
1852                return asyncApi.getChannelGroupClientsByChannelId(channelId).getUninterruptibly();
1853        }
1854
1855        /**
1856         * Gets all channel group assignments for the specified client.
1857         *
1858         * @param clientDBId
1859         *              the database ID of the client whose channel group
1860         *
1861         * @return a list of combinations of channel ID, client database ID and channel group ID
1862         *
1863         * @throws TS3CommandFailedException
1864         *              if the execution of a command fails
1865         * @querycommands 1
1866         * @see Client#getDatabaseId()
1867         * @see ChannelGroupClient
1868         * @see #getChannelGroupClients(int, int, int)
1869         */
1870        public List<ChannelGroupClient> getChannelGroupClientsByClientDBId(int clientDBId) {
1871                return asyncApi.getChannelGroupClientsByClientDBId(clientDBId).getUninterruptibly();
1872        }
1873
1874        /**
1875         * Gets a list of all permissions assigned to the specified channel group.
1876         *
1877         * @param groupId
1878         *              the ID of the channel group.
1879         *
1880         * @return a list of permissions assigned to the channel group
1881         *
1882         * @throws TS3CommandFailedException
1883         *              if the execution of a command fails
1884         * @querycommands 1
1885         * @see ChannelGroup#getId()
1886         * @see Permission
1887         */
1888        public List<Permission> getChannelGroupPermissions(int groupId) {
1889                return asyncApi.getChannelGroupPermissions(groupId).getUninterruptibly();
1890        }
1891
1892        /**
1893         * Gets a list of all channel groups on the selected virtual server.
1894         *
1895         * @return a list of all channel groups on the virtual server
1896         *
1897         * @throws TS3CommandFailedException
1898         *              if the execution of a command fails
1899         * @querycommands 1
1900         * @see ChannelGroup
1901         */
1902        public List<ChannelGroup> getChannelGroups() {
1903                return asyncApi.getChannelGroups().getUninterruptibly();
1904        }
1905
1906        /**
1907         * Gets detailed configuration information about the channel specified channel.
1908         *
1909         * @param channelId
1910         *              the ID of the channel
1911         *
1912         * @return information about the channel
1913         *
1914         * @throws TS3CommandFailedException
1915         *              if the execution of a command fails
1916         * @querycommands 1
1917         * @see Channel#getId()
1918         * @see ChannelInfo
1919         */
1920        public ChannelInfo getChannelInfo(int channelId) {
1921                return asyncApi.getChannelInfo(channelId).getUninterruptibly();
1922        }
1923
1924        /**
1925         * Gets a list of all permissions assigned to the specified channel.
1926         *
1927         * @param channelId
1928         *              the ID of the channel
1929         *
1930         * @return a list of all permissions assigned to the channel
1931         *
1932         * @throws TS3CommandFailedException
1933         *              if the execution of a command fails
1934         * @querycommands 1
1935         * @see Channel#getId()
1936         * @see Permission
1937         */
1938        public List<Permission> getChannelPermissions(int channelId) {
1939                return asyncApi.getChannelPermissions(channelId).getUninterruptibly();
1940        }
1941
1942        /**
1943         * Gets a list of all channels on the selected virtual server.
1944         *
1945         * @return a list of all channels on the virtual server
1946         *
1947         * @throws TS3CommandFailedException
1948         *              if the execution of a command fails
1949         * @querycommands 1
1950         * @see Channel
1951         */
1952        public List<Channel> getChannels() {
1953                return asyncApi.getChannels().getUninterruptibly();
1954        }
1955
1956        /**
1957         * Finds and returns the client whose nickname matches the given name exactly.
1958         *
1959         * @param name
1960         *              the name of the client
1961         * @param ignoreCase
1962         *              whether the case of the name should be ignored
1963         *
1964         * @return the found client or {@code null} if no client was found
1965         *
1966         * @throws TS3CommandFailedException
1967         *              if the execution of a command fails
1968         * @querycommands 1
1969         * @see Client
1970         * @see #getClientsByName(String)
1971         */
1972        public Client getClientByNameExact(String name, boolean ignoreCase) {
1973                return asyncApi.getClientByNameExact(name, ignoreCase).getUninterruptibly();
1974        }
1975
1976        /**
1977         * Gets a list of clients whose nicknames contain the given search string.
1978         *
1979         * @param name
1980         *              the name to search
1981         *
1982         * @return a list of all clients with nicknames matching the search pattern
1983         *
1984         * @throws TS3CommandFailedException
1985         *              if the execution of a command fails
1986         * @querycommands 2
1987         * @see Client
1988         * @see #getClientByNameExact(String, boolean)
1989         */
1990        public List<Client> getClientsByName(String name) {
1991                return asyncApi.getClientsByName(name).getUninterruptibly();
1992        }
1993
1994        /**
1995         * Gets information about the client with the specified unique identifier.
1996         *
1997         * @param clientUId
1998         *              the unique identifier of the client
1999         *
2000         * @return information about the client
2001         *
2002         * @throws TS3CommandFailedException
2003         *              if the execution of a command fails
2004         * @querycommands 2
2005         * @see Client#getUniqueIdentifier()
2006         * @see ClientInfo
2007         */
2008        public ClientInfo getClientByUId(String clientUId) {
2009                return asyncApi.getClientByUId(clientUId).getUninterruptibly();
2010        }
2011
2012        /**
2013         * Gets information about the client with the specified client ID.
2014         *
2015         * @param clientId
2016         *              the client ID of the client
2017         *
2018         * @return information about the client
2019         *
2020         * @throws TS3CommandFailedException
2021         *              if the execution of a command fails
2022         * @querycommands 1
2023         * @see Client#getId()
2024         * @see ClientInfo
2025         */
2026        public ClientInfo getClientInfo(int clientId) {
2027                return asyncApi.getClientInfo(clientId).getUninterruptibly();
2028        }
2029
2030        /**
2031         * Gets a list of all permissions assigned to the specified client.
2032         *
2033         * @param clientDBId
2034         *              the database ID of the client
2035         *
2036         * @return a list of all permissions assigned to the client
2037         *
2038         * @throws TS3CommandFailedException
2039         *              if the execution of a command fails
2040         * @querycommands 1
2041         * @see Client#getDatabaseId()
2042         * @see Permission
2043         */
2044        public List<Permission> getClientPermissions(int clientDBId) {
2045                return asyncApi.getClientPermissions(clientDBId).getUninterruptibly();
2046        }
2047
2048        /**
2049         * Gets a list of all clients on the selected virtual server.
2050         *
2051         * @return a list of all clients on the virtual server
2052         *
2053         * @throws TS3CommandFailedException
2054         *              if the execution of a command fails
2055         * @querycommands 1
2056         * @see Client
2057         */
2058        public List<Client> getClients() {
2059                return asyncApi.getClients().getUninterruptibly();
2060        }
2061
2062        /**
2063         * Gets a list of all complaints on the selected virtual server.
2064         *
2065         * @return a list of all complaints on the virtual server
2066         *
2067         * @throws TS3CommandFailedException
2068         *              if the execution of a command fails
2069         * @querycommands 1
2070         * @see Complaint
2071         * @see #getComplaints(int)
2072         */
2073        public List<Complaint> getComplaints() {
2074                return asyncApi.getComplaints().getUninterruptibly();
2075        }
2076
2077        /**
2078         * Gets a list of all complaints about the specified client.
2079         *
2080         * @param clientDBId
2081         *              the database ID of the client
2082         *
2083         * @return a list of all complaints about the specified client
2084         *
2085         * @throws TS3CommandFailedException
2086         *              if the execution of a command fails
2087         * @querycommands 1
2088         * @see Client#getDatabaseId()
2089         * @see Complaint
2090         */
2091        public List<Complaint> getComplaints(int clientDBId) {
2092                return asyncApi.getComplaints(clientDBId).getUninterruptibly();
2093        }
2094
2095        /**
2096         * Gets detailed connection information about the selected virtual server.
2097         *
2098         * @return connection information about the selected virtual server
2099         *
2100         * @throws TS3CommandFailedException
2101         *              if the execution of a command fails
2102         * @querycommands 1
2103         * @see ConnectionInfo
2104         * @see #getServerInfo()
2105         */
2106        public ConnectionInfo getConnectionInfo() {
2107                return asyncApi.getConnectionInfo().getUninterruptibly();
2108        }
2109
2110        /**
2111         * Gets a map of all custom client properties and their values
2112         * assigned to the client with database ID {@code clientDBId}.
2113         *
2114         * @param clientDBId
2115         *              the database ID of the target client
2116         *
2117         * @return a map of the client's custom client property assignments
2118         *
2119         * @throws TS3CommandFailedException
2120         *              if the execution of a command fails
2121         * @querycommands 1
2122         * @see Client#getDatabaseId()
2123         * @see #searchCustomClientProperty(String)
2124         * @see #searchCustomClientProperty(String, String)
2125         */
2126        public Map<String, String> getCustomClientProperties(int clientDBId) {
2127                return asyncApi.getCustomClientProperties(clientDBId).getUninterruptibly();
2128        }
2129
2130        /**
2131         * Gets all clients in the database whose last nickname matches the specified name <b>exactly</b>.
2132         *
2133         * @param name
2134         *              the nickname for the clients to match
2135         *
2136         * @return a list of all clients with a matching nickname
2137         *
2138         * @throws TS3CommandFailedException
2139         *              if the execution of a command fails
2140         * @querycommands 1 + n,
2141         * where n is the amount of database clients with a matching nickname
2142         * @see Client#getNickname()
2143         */
2144        public List<DatabaseClientInfo> getDatabaseClientsByName(String name) {
2145                return asyncApi.getDatabaseClientsByName(name).getUninterruptibly();
2146        }
2147
2148        /**
2149         * Gets information about the client with the specified unique identifier in the server database.
2150         *
2151         * @param clientUId
2152         *              the unique identifier of the client
2153         *
2154         * @return the database client or {@code null} if no client was found
2155         *
2156         * @throws TS3CommandFailedException
2157         *              if the execution of a command fails
2158         * @querycommands 2
2159         * @see Client#getUniqueIdentifier()
2160         * @see DatabaseClientInfo
2161         */
2162        public DatabaseClientInfo getDatabaseClientByUId(String clientUId) {
2163                return asyncApi.getDatabaseClientByUId(clientUId).getUninterruptibly();
2164        }
2165
2166        /**
2167         * Gets information about the client with the specified database ID in the server database.
2168         *
2169         * @param clientDBId
2170         *              the database ID of the client
2171         *
2172         * @return the database client or {@code null} if no client was found
2173         *
2174         * @throws TS3CommandFailedException
2175         *              if the execution of a command fails
2176         * @querycommands 1
2177         * @see Client#getDatabaseId()
2178         * @see DatabaseClientInfo
2179         */
2180        public DatabaseClientInfo getDatabaseClientInfo(int clientDBId) {
2181                return asyncApi.getDatabaseClientInfo(clientDBId).getUninterruptibly();
2182        }
2183
2184        /**
2185         * Gets information about all clients in the server database.
2186         * <p>
2187         * As this method uses internal commands which can only return 200 clients at once,
2188         * this method can take quite some time to execute.
2189         * </p><p>
2190         * Also keep in mind that the client database can easily accumulate several thousand entries.
2191         * </p>
2192         *
2193         * @return a {@link List} of all database clients
2194         *
2195         * @throws TS3CommandFailedException
2196         *              if the execution of a command fails
2197         * @querycommands 1 + n,
2198         * where n = Math.ceil([amount of database clients] / 200)
2199         * @see DatabaseClient
2200         */
2201        public List<DatabaseClient> getDatabaseClients() {
2202                return asyncApi.getDatabaseClients().getUninterruptibly();
2203        }
2204
2205        /**
2206         * Gets information about a set number of clients in the server database, starting at {@code offset}.
2207         *
2208         * @param offset
2209         *              the index of the first database client to be returned.
2210         *              Note that this is <b>not</b> a database ID, but an arbitrary, 0-based index.
2211         * @param count
2212         *              the number of database clients that should be returned.
2213         *              Any integer greater than 200 might cause problems with the connection
2214         *
2215         * @return a {@link List} of database clients
2216         *
2217         * @throws TS3CommandFailedException
2218         *              if the execution of a command fails
2219         * @querycommands 1
2220         * @see DatabaseClient
2221         */
2222        public List<DatabaseClient> getDatabaseClients(int offset, int count) {
2223                return asyncApi.getDatabaseClients(offset, count).getUninterruptibly();
2224        }
2225
2226        /**
2227         * Gets information about a file on the file repository in the specified channel.
2228         * <p>
2229         * Note that this method does not work on directories and the information returned by this
2230         * method is identical to the one returned by {@link #getFileList(String, int, String)}
2231         * </p>
2232         *
2233         * @param filePath
2234         *              the path to the file
2235         * @param channelId
2236         *              the ID of the channel the file resides in
2237         *
2238         * @return some information about the file
2239         *
2240         * @throws TS3CommandFailedException
2241         *              if the execution of a command fails
2242         * @querycommands 1
2243         * @see FileInfo#getPath()
2244         * @see Channel#getId()
2245         */
2246        public FileInfo getFileInfo(String filePath, int channelId) {
2247                return asyncApi.getFileInfo(filePath, channelId).getUninterruptibly();
2248        }
2249
2250        /**
2251         * Gets information about a file on the file repository in the specified channel.
2252         * <p>
2253         * Note that this method does not work on directories and the information returned by this
2254         * method is identical to the one returned by {@link #getFileList(String, int, String)}
2255         * </p>
2256         *
2257         * @param filePath
2258         *              the path to the file
2259         * @param channelId
2260         *              the ID of the channel the file resides in
2261         * @param channelPassword
2262         *              the password of that channel
2263         *
2264         * @return some information about the file
2265         *
2266         * @throws TS3CommandFailedException
2267         *              if the execution of a command fails
2268         * @querycommands 1
2269         * @see FileInfo#getPath()
2270         * @see Channel#getId()
2271         */
2272        public FileInfo getFileInfo(String filePath, int channelId, String channelPassword) {
2273                return asyncApi.getFileInfo(filePath, channelId, channelPassword).getUninterruptibly();
2274        }
2275
2276        /**
2277         * Gets information about multiple files on the file repository in the specified channel.
2278         * <p>
2279         * Note that this method does not work on directories and the information returned by this
2280         * method is identical to the one returned by {@link #getFileList(String, int, String)}
2281         * </p>
2282         *
2283         * @param filePaths
2284         *              the paths to the files
2285         * @param channelId
2286         *              the ID of the channel the file resides in
2287         *
2288         * @return some information about the file
2289         *
2290         * @throws TS3CommandFailedException
2291         *              if the execution of a command fails
2292         * @querycommands 1
2293         * @see FileInfo#getPath()
2294         * @see Channel#getId()
2295         */
2296        public List<FileInfo> getFileInfos(String[] filePaths, int channelId) {
2297                return asyncApi.getFileInfos(filePaths, channelId).getUninterruptibly();
2298        }
2299
2300        /**
2301         * Gets information about multiple files on the file repository in the specified channel.
2302         * <p>
2303         * Note that this method does not work on directories and the information returned by this
2304         * method is identical to the one returned by {@link #getFileList(String, int, String)}
2305         * </p>
2306         *
2307         * @param filePaths
2308         *              the paths to the files
2309         * @param channelId
2310         *              the ID of the channel the file resides in
2311         * @param channelPassword
2312         *              the password of that channel
2313         *
2314         * @return some information about the file
2315         *
2316         * @throws TS3CommandFailedException
2317         *              if the execution of a command fails
2318         * @querycommands 1
2319         * @see FileInfo#getPath()
2320         * @see Channel#getId()
2321         */
2322        public List<FileInfo> getFileInfos(String[] filePaths, int channelId, String channelPassword) {
2323                return asyncApi.getFileInfos(filePaths, channelId, channelPassword).getUninterruptibly();
2324        }
2325
2326        /**
2327         * Gets information about multiple files on the file repository in multiple channels.
2328         * <p>
2329         * Note that this method does not work on directories and the information returned by this
2330         * method is identical to the one returned by {@link #getFileList(String, int, String)}
2331         * </p>
2332         *
2333         * @param filePaths
2334         *              the paths to the files, may not be {@code null} and may not contain {@code null} elements
2335         * @param channelIds
2336         *              the IDs of the channels the file resides in, may not be {@code null}
2337         * @param channelPasswords
2338         *              the passwords of those channels, may be {@code null} and may contain {@code null} elements
2339         *
2340         * @return some information about the files
2341         *
2342         * @throws IllegalArgumentException
2343         *              if the dimensions of {@code filePaths}, {@code channelIds} and {@code channelPasswords} don't match
2344         * @throws TS3CommandFailedException
2345         *              if the execution of a command fails
2346         * @querycommands 1
2347         * @see FileInfo#getPath()
2348         * @see Channel#getId()
2349         */
2350        public List<FileInfo> getFileInfos(String[] filePaths, int[] channelIds, String[] channelPasswords) {
2351                return asyncApi.getFileInfos(filePaths, channelIds, channelPasswords).getUninterruptibly();
2352        }
2353
2354        /**
2355         * Gets a list of files and directories in the specified parent directory and channel.
2356         *
2357         * @param directoryPath
2358         *              the path to the parent directory
2359         * @param channelId
2360         *              the ID of the channel the directory resides in
2361         *
2362         * @return the files and directories in the parent directory
2363         *
2364         * @throws TS3CommandFailedException
2365         *              if the execution of a command fails
2366         * @querycommands 1
2367         * @see FileInfo#getPath()
2368         * @see Channel#getId()
2369         */
2370        public List<FileListEntry> getFileList(String directoryPath, int channelId) {
2371                return asyncApi.getFileList(directoryPath, channelId).getUninterruptibly();
2372        }
2373
2374        /**
2375         * Gets a list of files and directories in the specified parent directory and channel.
2376         *
2377         * @param directoryPath
2378         *              the path to the parent directory
2379         * @param channelId
2380         *              the ID of the channel the directory resides in
2381         * @param channelPassword
2382         *              the password of that channel
2383         *
2384         * @return the files and directories in the parent directory
2385         *
2386         * @throws TS3CommandFailedException
2387         *              if the execution of a command fails
2388         * @querycommands 1
2389         * @see FileInfo#getPath()
2390         * @see Channel#getId()
2391         */
2392        public List<FileListEntry> getFileList(String directoryPath, int channelId, String channelPassword) {
2393                return asyncApi.getFileList(directoryPath, channelId, channelPassword).getUninterruptibly();
2394        }
2395
2396        /**
2397         * Gets a list of active or recently active file transfers.
2398         *
2399         * @return a list of file transfers
2400         *
2401         * @throws TS3CommandFailedException
2402         *              if the execution of a command fails
2403         * @querycommands 1
2404         */
2405        public List<FileTransfer> getFileTransfers() {
2406                return asyncApi.getFileTransfers().getUninterruptibly();
2407        }
2408
2409        /**
2410         * Displays detailed configuration information about the server instance including
2411         * uptime, number of virtual servers online, traffic information, etc.
2412         *
2413         * @return information about the host
2414         *
2415         * @throws TS3CommandFailedException
2416         *              if the execution of a command fails
2417         * @querycommands 1
2418         */
2419        public HostInfo getHostInfo() {
2420                return asyncApi.getHostInfo().getUninterruptibly();
2421        }
2422
2423        /**
2424         * Gets a list of all icon files on this virtual server.
2425         *
2426         * @return a list of all icons
2427         */
2428        public List<IconFile> getIconList() {
2429                return asyncApi.getIconList().getUninterruptibly();
2430        }
2431
2432        /**
2433         * Displays the server instance configuration including database revision number,
2434         * the file transfer port, default group IDs, etc.
2435         *
2436         * @return information about the TeamSpeak server instance.
2437         *
2438         * @throws TS3CommandFailedException
2439         *              if the execution of a command fails
2440         * @querycommands 1
2441         */
2442        public InstanceInfo getInstanceInfo() {
2443                return asyncApi.getInstanceInfo().getUninterruptibly();
2444        }
2445
2446        /**
2447         * Fetches the specified amount of log entries from the server log.
2448         *
2449         * @param lines
2450         *              the amount of log entries to fetch, in the range between 1 and 100.
2451         *              Returns 100 entries if the argument is not in range
2452         *
2453         * @return a list of the latest log entries
2454         *
2455         * @throws TS3CommandFailedException
2456         *              if the execution of a command fails
2457         * @querycommands 1
2458         */
2459        public List<String> getInstanceLogEntries(int lines) {
2460                return asyncApi.getInstanceLogEntries(lines).getUninterruptibly();
2461        }
2462
2463        /**
2464         * Fetches the last 100 log entries from the server log.
2465         *
2466         * @return a list of up to 100 log entries
2467         *
2468         * @throws TS3CommandFailedException
2469         *              if the execution of a command fails
2470         * @querycommands 1
2471         */
2472        public List<String> getInstanceLogEntries() {
2473                return asyncApi.getInstanceLogEntries().getUninterruptibly();
2474        }
2475
2476        /**
2477         * Reads the message body of a message. This will not set the read flag, though.
2478         *
2479         * @param messageId
2480         *              the ID of the message to be read
2481         *
2482         * @return the body of the message with the specified ID or {@code null} if there was no message with that ID
2483         *
2484         * @throws TS3CommandFailedException
2485         *              if the execution of a command fails
2486         * @querycommands 1
2487         * @see Message#getId()
2488         * @see #setMessageRead(int)
2489         */
2490        public String getOfflineMessage(int messageId) {
2491                return asyncApi.getOfflineMessage(messageId).getUninterruptibly();
2492        }
2493
2494        /**
2495         * Reads the message body of a message. This will not set the read flag, though.
2496         *
2497         * @param message
2498         *              the message to be read
2499         *
2500         * @return the body of the message with the specified ID or {@code null} if there was no message with that ID
2501         *
2502         * @throws TS3CommandFailedException
2503         *              if the execution of a command fails
2504         * @querycommands 1
2505         * @see Message#getId()
2506         * @see #setMessageRead(Message)
2507         */
2508        public String getOfflineMessage(Message message) {
2509                return asyncApi.getOfflineMessage(message).getUninterruptibly();
2510        }
2511
2512        /**
2513         * Gets a list of all offline messages for the server query.
2514         * The returned messages lack their message body, though.
2515         * To read the actual message, use {@link #getOfflineMessage(int)} or {@link #getOfflineMessage(Message)}.
2516         *
2517         * @return a list of all offline messages this server query has received
2518         *
2519         * @throws TS3CommandFailedException
2520         *              if the execution of a command fails
2521         * @querycommands 1
2522         */
2523        public List<Message> getOfflineMessages() {
2524                return asyncApi.getOfflineMessages().getUninterruptibly();
2525        }
2526
2527        /**
2528         * Displays detailed information about all assignments of the permission specified
2529         * with {@code permName}. The output includes the type and the ID of the client,
2530         * channel or group associated with the permission.
2531         *
2532         * @param permName
2533         *              the name of the permission
2534         *
2535         * @return a list of permission assignments
2536         *
2537         * @throws TS3CommandFailedException
2538         *              if the execution of a command fails
2539         * @querycommands 1
2540         * @see #getPermissionOverview(int, int)
2541         */
2542        public List<PermissionAssignment> getPermissionAssignments(String permName) {
2543                return asyncApi.getPermissionAssignments(permName).getUninterruptibly();
2544        }
2545
2546        /**
2547         * Gets the ID of the permission specified by {@code permName}.
2548         * <p>
2549         * Note that the use of numeric permission IDs is deprecated
2550         * and that this API only uses the string variant of the IDs.
2551         * </p>
2552         *
2553         * @param permName
2554         *              the name of the permission
2555         *
2556         * @return the numeric ID of the specified permission
2557         *
2558         * @throws TS3CommandFailedException
2559         *              if the execution of a command fails
2560         * @querycommands 1
2561         */
2562        public int getPermissionIdByName(String permName) {
2563                return asyncApi.getPermissionIdByName(permName).getUninterruptibly();
2564        }
2565
2566        /**
2567         * Gets the IDs of the permissions specified by {@code permNames}.
2568         * <p>
2569         * Note that the use of numeric permission IDs is deprecated
2570         * and that this API only uses the string variant of the IDs.
2571         * </p>
2572         *
2573         * @param permNames
2574         *              the names of the permissions
2575         *
2576         * @return the numeric IDs of the specified permission
2577         *
2578         * @throws IllegalArgumentException
2579         *              if {@code permNames} is {@code null}
2580         * @throws TS3CommandFailedException
2581         *              if the execution of a command fails
2582         * @querycommands 1
2583         */
2584        public int[] getPermissionIdsByName(String... permNames) {
2585                return asyncApi.getPermissionIdsByName(permNames).getUninterruptibly();
2586        }
2587
2588        /**
2589         * Gets a list of all assigned permissions for a client in a specified channel.
2590         * If you do not care about channel permissions, set {@code channelId} to {@code 0}.
2591         *
2592         * @param channelId
2593         *              the ID of the channel
2594         * @param clientDBId
2595         *              the database ID of the client to create the overview for
2596         *
2597         * @return a list of all permission assignments for the client in the specified channel
2598         *
2599         * @throws TS3CommandFailedException
2600         *              if the execution of a command fails
2601         * @querycommands 1
2602         * @see Channel#getId()
2603         * @see Client#getDatabaseId()
2604         */
2605        public List<PermissionAssignment> getPermissionOverview(int channelId, int clientDBId) {
2606                return asyncApi.getPermissionOverview(channelId, clientDBId).getUninterruptibly();
2607        }
2608
2609        /**
2610         * Displays a list of all permissions, including ID, name and description.
2611         *
2612         * @return a list of all permissions
2613         *
2614         * @throws TS3CommandFailedException
2615         *              if the execution of a command fails
2616         * @querycommands 1
2617         */
2618        public List<PermissionInfo> getPermissions() {
2619                return asyncApi.getPermissions().getUninterruptibly();
2620        }
2621
2622        /**
2623         * Displays the current value of the specified permission for this server query instance.
2624         *
2625         * @param permName
2626         *              the name of the permission
2627         *
2628         * @return the permission value, usually ranging from 0 to 100
2629         *
2630         * @throws TS3CommandFailedException
2631         *              if the execution of a command fails
2632         * @querycommands 1
2633         */
2634        public int getPermissionValue(String permName) {
2635                return asyncApi.getPermissionValue(permName).getUninterruptibly();
2636        }
2637
2638        /**
2639         * Displays the current values of the specified permissions for this server query instance.
2640         *
2641         * @param permNames
2642         *              the names of the permissions
2643         *
2644         * @return the permission values, usually ranging from 0 to 100
2645         *
2646         * @throws IllegalArgumentException
2647         *              if {@code permNames} is {@code null}
2648         * @throws TS3CommandFailedException
2649         *              if the execution of a command fails
2650         * @querycommands 1
2651         */
2652        public int[] getPermissionValues(String... permNames) {
2653                return asyncApi.getPermissionValues(permNames).getUninterruptibly();
2654        }
2655
2656        /**
2657         * Gets a list of all available tokens to join channel or server groups,
2658         * including their type and group IDs.
2659         *
2660         * @return a list of all generated, but still unclaimed privilege keys
2661         *
2662         * @throws TS3CommandFailedException
2663         *              if the execution of a command fails
2664         * @querycommands 1
2665         * @see #addPrivilegeKey(PrivilegeKeyType, int, int, String)
2666         * @see #usePrivilegeKey(String)
2667         */
2668        public List<PrivilegeKey> getPrivilegeKeys() {
2669                return asyncApi.getPrivilegeKeys().getUninterruptibly();
2670        }
2671
2672        /**
2673         * Gets a list of all clients in the specified server group.
2674         *
2675         * @param serverGroupId
2676         *              the ID of the server group for which the clients should be looked up
2677         *
2678         * @return a list of all clients in the server group
2679         *
2680         * @throws TS3CommandFailedException
2681         *              if the execution of a command fails
2682         * @querycommands 1
2683         */
2684        public List<ServerGroupClient> getServerGroupClients(int serverGroupId) {
2685                return asyncApi.getServerGroupClients(serverGroupId).getUninterruptibly();
2686        }
2687
2688        /**
2689         * Gets a list of all clients in the specified server group.
2690         *
2691         * @param serverGroup
2692         *              the server group for which the clients should be looked up
2693         *
2694         * @return a list of all clients in the server group
2695         *
2696         * @throws TS3CommandFailedException
2697         *              if the execution of a command fails
2698         * @querycommands 1
2699         */
2700        public List<ServerGroupClient> getServerGroupClients(ServerGroup serverGroup) {
2701                return asyncApi.getServerGroupClients(serverGroup).getUninterruptibly();
2702        }
2703
2704        /**
2705         * Gets a list of all permissions assigned to the specified server group.
2706         *
2707         * @param serverGroupId
2708         *              the ID of the server group for which the permissions should be looked up
2709         *
2710         * @return a list of all permissions assigned to the server group
2711         *
2712         * @throws TS3CommandFailedException
2713         *              if the execution of a command fails
2714         * @querycommands 1
2715         * @see ServerGroup#getId()
2716         * @see #getServerGroupPermissions(ServerGroup)
2717         */
2718        public List<Permission> getServerGroupPermissions(int serverGroupId) {
2719                return asyncApi.getServerGroupPermissions(serverGroupId).getUninterruptibly();
2720        }
2721
2722        /**
2723         * Gets a list of all permissions assigned to the specified server group.
2724         *
2725         * @param serverGroup
2726         *              the server group for which the permissions should be looked up
2727         *
2728         * @return a list of all permissions assigned to the server group
2729         *
2730         * @throws TS3CommandFailedException
2731         *              if the execution of a command fails
2732         * @querycommands 1
2733         */
2734        public List<Permission> getServerGroupPermissions(ServerGroup serverGroup) {
2735                return asyncApi.getServerGroupPermissions(serverGroup).getUninterruptibly();
2736        }
2737
2738        /**
2739         * Gets a list of all server groups on the virtual server.
2740         * <p>
2741         * Depending on your permissions, the output may also contain
2742         * global server query groups and template groups.
2743         * </p>
2744         *
2745         * @return a list of all server groups
2746         *
2747         * @throws TS3CommandFailedException
2748         *              if the execution of a command fails
2749         * @querycommands 1
2750         */
2751        public List<ServerGroup> getServerGroups() {
2752                return asyncApi.getServerGroups().getUninterruptibly();
2753        }
2754
2755        /**
2756         * Gets a list of all server groups set for a client.
2757         *
2758         * @param clientDatabaseId
2759         *              the database ID of the client for which the server groups should be looked up
2760         *
2761         * @return a list of all server groups set for the client
2762         *
2763         * @throws TS3CommandFailedException
2764         *              if the execution of a command fails
2765         * @querycommands 2
2766         * @see Client#getDatabaseId()
2767         * @see #getServerGroupsByClient(Client)
2768         */
2769        public List<ServerGroup> getServerGroupsByClientId(int clientDatabaseId) {
2770                return asyncApi.getServerGroupsByClientId(clientDatabaseId).getUninterruptibly();
2771        }
2772
2773        /**
2774         * Gets a list of all server groups set for a client.
2775         *
2776         * @param client
2777         *              the client for which the server groups should be looked up
2778         *
2779         * @return a list of all server group set for the client
2780         *
2781         * @throws TS3CommandFailedException
2782         *              if the execution of a command fails
2783         * @querycommands 2
2784         * @see #getServerGroupsByClientId(int)
2785         */
2786        public List<ServerGroup> getServerGroupsByClient(Client client) {
2787                return asyncApi.getServerGroupsByClient(client).getUninterruptibly();
2788        }
2789
2790        /**
2791         * Gets the ID of a virtual server by its port.
2792         *
2793         * @param port
2794         *              the port of a virtual server
2795         *
2796         * @return the ID of the virtual server
2797         *
2798         * @throws TS3CommandFailedException
2799         *              if the execution of a command fails
2800         * @querycommands 1
2801         * @see VirtualServer#getPort()
2802         * @see VirtualServer#getId()
2803         */
2804        public int getServerIdByPort(int port) {
2805                return asyncApi.getServerIdByPort(port).getUninterruptibly();
2806        }
2807
2808        /**
2809         * Gets detailed information about the virtual server the server query is currently in.
2810         *
2811         * @return information about the current virtual server
2812         *
2813         * @throws TS3CommandFailedException
2814         *              if the execution of a command fails
2815         * @querycommands 1
2816         */
2817        public VirtualServerInfo getServerInfo() {
2818                return asyncApi.getServerInfo().getUninterruptibly();
2819        }
2820
2821        /**
2822         * Gets a list of all server query logins (containing login name, virtual server ID, and client database ID).
2823         * If a virtual server is selected, only the server query logins of the selected virtual server are returned.
2824         *
2825         * @return a list of {@code QueryLogin} objects describing existing server query logins
2826         *
2827         * @throws TS3CommandFailedException
2828         *              if the execution of a command fails
2829         * @querycommands 1
2830         * @see #addServerQueryLogin(String, int)
2831         * @see #deleteServerQueryLogin(int)
2832         * @see #getServerQueryLoginsByName(String)
2833         * @see #updateServerQueryLogin(String)
2834         */
2835        public List<QueryLogin> getServerQueryLogins() {
2836                return asyncApi.getServerQueryLogins().getUninterruptibly();
2837        }
2838
2839        /**
2840         * Gets a list of all server query logins (containing login name, virtual server ID, and client database ID)
2841         * whose login name matches the specified SQL-like pattern.
2842         * If a virtual server is selected, only the server query logins of the selected virtual server are returned.
2843         *
2844         * @param pattern
2845         *              the SQL-like pattern to match the server query login name against
2846         *
2847         * @return a list of {@code QueryLogin} objects describing existing server query logins
2848         *
2849         * @throws TS3CommandFailedException
2850         *              if the execution of a command fails
2851         * @querycommands 1
2852         * @see #addServerQueryLogin(String, int)
2853         * @see #deleteServerQueryLogin(int)
2854         * @see #getServerQueryLogins()
2855         * @see #updateServerQueryLogin(String)
2856         */
2857        public List<QueryLogin> getServerQueryLoginsByName(String pattern) {
2858                return asyncApi.getServerQueryLoginsByName(pattern).getUninterruptibly();
2859        }
2860
2861        /**
2862         * Gets the version, build number and platform of the TeamSpeak3 server.
2863         *
2864         * @return the version information of the server
2865         *
2866         * @throws TS3CommandFailedException
2867         *              if the execution of a command fails
2868         * @querycommands 1
2869         */
2870        public Version getVersion() {
2871                return asyncApi.getVersion().getUninterruptibly();
2872        }
2873
2874        /**
2875         * Gets a list of all virtual servers including their ID, status, number of clients online, etc.
2876         *
2877         * @return a list of all virtual servers
2878         *
2879         * @throws TS3CommandFailedException
2880         *              if the execution of a command fails
2881         * @querycommands 1
2882         */
2883        public List<VirtualServer> getVirtualServers() {
2884                return asyncApi.getVirtualServers().getUninterruptibly();
2885        }
2886
2887        /**
2888         * Fetches the specified amount of log entries from the currently selected virtual server.
2889         * If no virtual server is selected, the entries will be read from the server log instead.
2890         *
2891         * @param lines
2892         *              the amount of log entries to fetch, in the range between 1 and 100.
2893         *              Returns 100 entries if the argument is not in range
2894         *
2895         * @return a list of the latest log entries
2896         *
2897         * @throws TS3CommandFailedException
2898         *              if the execution of a command fails
2899         * @querycommands 1
2900         */
2901        public List<String> getVirtualServerLogEntries(int lines) {
2902                return asyncApi.getVirtualServerLogEntries(lines).getUninterruptibly();
2903        }
2904
2905        /**
2906         * Fetches the last 100 log entries from the currently selected virtual server.
2907         * If no virtual server is selected, the entries will be read from the server log instead.
2908         *
2909         * @return a list of up to 100 log entries
2910         *
2911         * @throws TS3CommandFailedException
2912         *              if the execution of a command fails
2913         * @querycommands 1
2914         */
2915        public List<String> getVirtualServerLogEntries() {
2916                return asyncApi.getVirtualServerLogEntries().getUninterruptibly();
2917        }
2918
2919        /**
2920         * Checks whether the client with the specified client ID is online.
2921         * <p>
2922         * Please note that there is no guarantee that the client will still be
2923         * online by the time the next command is executed.
2924         * </p>
2925         *
2926         * @param clientId
2927         *              the ID of the client
2928         *
2929         * @return {@code true} if the client is online, {@code false} otherwise
2930         *
2931         * @querycommands 1
2932         * @see #getClientInfo(int)
2933         */
2934        public boolean isClientOnline(int clientId) {
2935                return asyncApi.isClientOnline(clientId).getUninterruptibly();
2936        }
2937
2938        /**
2939         * Checks whether the client with the specified unique identifier is online.
2940         * <p>
2941         * Please note that there is no guarantee that the client will still be
2942         * online by the time the next command is executed.
2943         * </p>
2944         *
2945         * @param clientUId
2946         *              the unique ID of the client
2947         *
2948         * @return {@code true} if the client is online, {@code false} otherwise
2949         *
2950         * @querycommands 1
2951         * @see #getClientByUId(String)
2952         */
2953        public boolean isClientOnline(String clientUId) {
2954                return asyncApi.isClientOnline(clientUId).getUninterruptibly();
2955        }
2956
2957        /**
2958         * Kicks one or more clients from their current channels.
2959         * This will move the kicked clients into the default channel and
2960         * won't do anything if the clients are already in the default channel.
2961         *
2962         * @param clientIds
2963         *              the IDs of the clients to kick
2964         *
2965         * @throws TS3CommandFailedException
2966         *              if the execution of a command fails
2967         * @querycommands 1
2968         * @see #kickClientFromChannel(Client...)
2969         * @see #kickClientFromChannel(String, int...)
2970         */
2971        public void kickClientFromChannel(int... clientIds) {
2972                asyncApi.kickClientFromChannel(clientIds).getUninterruptibly();
2973        }
2974
2975        /**
2976         * Kicks one or more clients from their current channels.
2977         * This will move the kicked clients into the default channel and
2978         * won't do anything if the clients are already in the default channel.
2979         *
2980         * @param clients
2981         *              the clients to kick
2982         *
2983         * @throws TS3CommandFailedException
2984         *              if the execution of a command fails
2985         * @querycommands 1
2986         * @see #kickClientFromChannel(int...)
2987         * @see #kickClientFromChannel(String, Client...)
2988         */
2989        public void kickClientFromChannel(Client... clients) {
2990                asyncApi.kickClientFromChannel(clients).getUninterruptibly();
2991        }
2992
2993        /**
2994         * Kicks one or more clients from their current channels for the specified reason.
2995         * This will move the kicked clients into the default channel and
2996         * won't do anything if the clients are already in the default channel.
2997         *
2998         * @param message
2999         *              the reason message to display to the clients
3000         * @param clientIds
3001         *              the IDs of the clients to kick
3002         *
3003         * @throws TS3CommandFailedException
3004         *              if the execution of a command fails
3005         * @querycommands 1
3006         * @see Client#getId()
3007         * @see #kickClientFromChannel(int...)
3008         * @see #kickClientFromChannel(String, Client...)
3009         */
3010        public void kickClientFromChannel(String message, int... clientIds) {
3011                asyncApi.kickClientFromChannel(message, clientIds).getUninterruptibly();
3012        }
3013
3014        /**
3015         * Kicks one or more clients from their current channels for the specified reason.
3016         * This will move the kicked clients into the default channel and
3017         * won't do anything if the clients are already in the default channel.
3018         *
3019         * @param message
3020         *              the reason message to display to the clients
3021         * @param clients
3022         *              the clients to kick
3023         *
3024         * @throws TS3CommandFailedException
3025         *              if the execution of a command fails
3026         * @querycommands 1
3027         * @see #kickClientFromChannel(Client...)
3028         * @see #kickClientFromChannel(String, int...)
3029         */
3030        public void kickClientFromChannel(String message, Client... clients) {
3031                asyncApi.kickClientFromChannel(message, clients).getUninterruptibly();
3032        }
3033
3034        /**
3035         * Kicks one or more clients from the server.
3036         *
3037         * @param clientIds
3038         *              the IDs of the clients to kick
3039         *
3040         * @throws TS3CommandFailedException
3041         *              if the execution of a command fails
3042         * @querycommands 1
3043         * @see Client#getId()
3044         * @see #kickClientFromServer(Client...)
3045         * @see #kickClientFromServer(String, int...)
3046         */
3047        public void kickClientFromServer(int... clientIds) {
3048                asyncApi.kickClientFromServer(clientIds).getUninterruptibly();
3049        }
3050
3051        /**
3052         * Kicks one or more clients from the server.
3053         *
3054         * @param clients
3055         *              the clients to kick
3056         *
3057         * @throws TS3CommandFailedException
3058         *              if the execution of a command fails
3059         * @querycommands 1
3060         * @see #kickClientFromServer(int...)
3061         * @see #kickClientFromServer(String, Client...)
3062         */
3063        public void kickClientFromServer(Client... clients) {
3064                asyncApi.kickClientFromServer(clients).getUninterruptibly();
3065        }
3066
3067        /**
3068         * Kicks one or more clients from the server for the specified reason.
3069         *
3070         * @param message
3071         *              the reason message to display to the clients
3072         * @param clientIds
3073         *              the IDs of the clients to kick
3074         *
3075         * @throws TS3CommandFailedException
3076         *              if the execution of a command fails
3077         * @querycommands 1
3078         * @see Client#getId()
3079         * @see #kickClientFromServer(int...)
3080         * @see #kickClientFromServer(String, Client...)
3081         */
3082        public void kickClientFromServer(String message, int... clientIds) {
3083                asyncApi.kickClientFromServer(message, clientIds).getUninterruptibly();
3084        }
3085
3086        /**
3087         * Kicks one or more clients from the server for the specified reason.
3088         *
3089         * @param message
3090         *              the reason message to display to the clients
3091         * @param clients
3092         *              the clients to kick
3093         *
3094         * @throws TS3CommandFailedException
3095         *              if the execution of a command fails
3096         * @querycommands 1
3097         * @see #kickClientFromServer(Client...)
3098         * @see #kickClientFromServer(String, int...)
3099         */
3100        public void kickClientFromServer(String message, Client... clients) {
3101                asyncApi.kickClientFromServer(message, clients).getUninterruptibly();
3102        }
3103
3104        /**
3105         * Logs the server query in using the specified username and password.
3106         * <p>
3107         * Note that you can also set the login in the {@link TS3Config},
3108         * so that you will be logged in right after the connection is established.
3109         * </p>
3110         *
3111         * @param username
3112         *              the username of the server query
3113         * @param password
3114         *              the password to use
3115         *
3116         * @throws TS3CommandFailedException
3117         *              if the execution of a command fails
3118         * @querycommands 1
3119         * @see #logout()
3120         */
3121        public void login(String username, String password) {
3122                asyncApi.login(username, password).getUninterruptibly();
3123        }
3124
3125        /**
3126         * Logs the server query out and deselects the current virtual server.
3127         *
3128         * @throws TS3CommandFailedException
3129         *              if the execution of a command fails
3130         * @querycommands 1
3131         * @see #login(String, String)
3132         */
3133        public void logout() {
3134                asyncApi.logout().getUninterruptibly();
3135        }
3136
3137        /**
3138         * Moves a channel to a new parent channel specified by its ID.
3139         * To move a channel to root level, set {@code channelTargetId} to {@code 0}.
3140         * <p>
3141         * This will move the channel right below the specified parent channel, above all other child channels.
3142         * This command will fail if the channel already has the specified target channel as the parent channel.
3143         * </p>
3144         *
3145         * @param channelId
3146         *              the channel to move
3147         * @param channelTargetId
3148         *              the new parent channel for the specified channel
3149         *
3150         * @throws TS3CommandFailedException
3151         *              if the execution of a command fails
3152         * @querycommands 1
3153         * @see Channel#getId()
3154         * @see #moveChannel(int, int, int)
3155         */
3156        public void moveChannel(int channelId, int channelTargetId) {
3157                asyncApi.moveChannel(channelId, channelTargetId).getUninterruptibly();
3158        }
3159
3160        /**
3161         * Moves a channel to a new parent channel specified by its ID.
3162         * To move a channel to root level, set {@code channelTargetId} to {@code 0}.
3163         * <p>
3164         * The channel will be ordered below the channel with the ID specified by {@code order}.
3165         * To move the channel right below the parent channel, set {@code order} to {@code 0}.
3166         * </p><p>
3167         * Note that you can't re-order a channel without also changing its parent channel with this method.
3168         * Use {@link #editChannel(int, ChannelProperty, String)} to change {@link ChannelProperty#CHANNEL_ORDER} instead.
3169         * </p>
3170         *
3171         * @param channelId
3172         *              the channel to move
3173         * @param channelTargetId
3174         *              the new parent channel for the specified channel
3175         * @param order
3176         *              the channel to sort the specified channel below
3177         *
3178         * @throws TS3CommandFailedException
3179         *              if the execution of a command fails
3180         * @querycommands 1
3181         * @see Channel#getId()
3182         * @see #moveChannel(int, int)
3183         */
3184        public void moveChannel(int channelId, int channelTargetId, int order) {
3185                asyncApi.moveChannel(channelId, channelTargetId, order).getUninterruptibly();
3186        }
3187
3188        /**
3189         * Moves a single client into a channel.
3190         * <p>
3191         * Consider using {@link #moveClients(int[], int)} to move multiple clients.
3192         * </p>
3193         *
3194         * @param clientId
3195         *              the ID of the client to move
3196         * @param channelId
3197         *              the ID of the channel to move the client into
3198         *
3199         * @throws TS3CommandFailedException
3200         *              if the execution of a command fails
3201         * @querycommands 1
3202         * @see Client#getId()
3203         * @see Channel#getId()
3204         */
3205        public void moveClient(int clientId, int channelId) {
3206                asyncApi.moveClient(clientId, channelId).getUninterruptibly();
3207        }
3208
3209        /**
3210         * Moves multiple clients into a channel.
3211         * Immediately returns {@code true} for an empty client ID array.
3212         * <p>
3213         * Use this method instead of {@link #moveClient(int, int)} for moving
3214         * several clients as this will only send 1 command to the server and thus complete faster.
3215         * </p>
3216         *
3217         * @param clientIds
3218         *              the IDs of the clients to move, cannot be {@code null}
3219         * @param channelId
3220         *              the ID of the channel to move the clients into
3221         *
3222         * @throws IllegalArgumentException
3223         *              if {@code clientIds} is {@code null}
3224         * @throws TS3CommandFailedException
3225         *              if the execution of a command fails
3226         * @querycommands 1
3227         * @see Client#getId()
3228         * @see Channel#getId()
3229         */
3230        public void moveClients(int[] clientIds, int channelId) {
3231                asyncApi.moveClients(clientIds, channelId).getUninterruptibly();
3232        }
3233
3234        /**
3235         * Moves a single client into a channel.
3236         * <p>
3237         * Consider using {@link #moveClients(Client[], ChannelBase)} to move multiple clients.
3238         * </p>
3239         *
3240         * @param client
3241         *              the client to move, cannot be {@code null}
3242         * @param channel
3243         *              the channel to move the client into, cannot be {@code null}
3244         *
3245         * @throws IllegalArgumentException
3246         *              if {@code client} or {@code channel} is {@code null}
3247         * @throws TS3CommandFailedException
3248         *              if the execution of a command fails
3249         * @querycommands 1
3250         */
3251        public void moveClient(Client client, ChannelBase channel) {
3252                asyncApi.moveClient(client, channel).getUninterruptibly();
3253        }
3254
3255        /**
3256         * Moves multiple clients into a channel.
3257         * Immediately returns {@code true} for an empty client array.
3258         * <p>
3259         * Use this method instead of {@link #moveClient(Client, ChannelBase)} for moving
3260         * several clients as this will only send 1 command to the server and thus complete faster.
3261         * </p>
3262         *
3263         * @param clients
3264         *              the clients to move, cannot be {@code null}
3265         * @param channel
3266         *              the channel to move the clients into, cannot be {@code null}
3267         *
3268         * @throws IllegalArgumentException
3269         *              if {@code clients} or {@code channel} is {@code null}
3270         * @throws TS3CommandFailedException
3271         *              if the execution of a command fails
3272         * @querycommands 1
3273         */
3274        public void moveClients(Client[] clients, ChannelBase channel) {
3275                asyncApi.moveClients(clients, channel).getUninterruptibly();
3276        }
3277
3278        /**
3279         * Moves a single client into a channel using the specified password.
3280         * <p>
3281         * Consider using {@link #moveClients(int[], int, String)} to move multiple clients.
3282         * </p>
3283         *
3284         * @param clientId
3285         *              the ID of the client to move
3286         * @param channelId
3287         *              the ID of the channel to move the client into
3288         * @param channelPassword
3289         *              the password of the channel, can be {@code null}
3290         *
3291         * @throws TS3CommandFailedException
3292         *              if the execution of a command fails
3293         * @querycommands 1
3294         * @see Client#getId()
3295         * @see Channel#getId()
3296         */
3297        public void moveClient(int clientId, int channelId, String channelPassword) {
3298                asyncApi.moveClient(clientId, channelId, channelPassword).getUninterruptibly();
3299        }
3300
3301        /**
3302         * Moves multiple clients into a channel using the specified password.
3303         * Immediately returns {@code true} for an empty client ID array.
3304         * <p>
3305         * Use this method instead of {@link #moveClient(int, int, String)} for moving
3306         * several clients as this will only send 1 command to the server and thus complete faster.
3307         * </p>
3308         *
3309         * @param clientIds
3310         *              the IDs of the clients to move, cannot be {@code null}
3311         * @param channelId
3312         *              the ID of the channel to move the clients into
3313         * @param channelPassword
3314         *              the password of the channel, can be {@code null}
3315         *
3316         * @throws IllegalArgumentException
3317         *              if {@code clientIds} is {@code null}
3318         * @throws TS3CommandFailedException
3319         *              if the execution of a command fails
3320         * @querycommands 1
3321         * @see Client#getId()
3322         * @see Channel#getId()
3323         */
3324        public void moveClients(int[] clientIds, int channelId, String channelPassword) {
3325                asyncApi.moveClients(clientIds, channelId, channelPassword).getUninterruptibly();
3326        }
3327
3328        /**
3329         * Moves a single client into a channel using the specified password.
3330         * <p>
3331         * Consider using {@link #moveClients(Client[], ChannelBase, String)} to move multiple clients.
3332         * </p>
3333         *
3334         * @param client
3335         *              the client to move, cannot be {@code null}
3336         * @param channel
3337         *              the channel to move the client into, cannot be {@code null}
3338         * @param channelPassword
3339         *              the password of the channel, can be {@code null}
3340         *
3341         * @throws IllegalArgumentException
3342         *              if {@code client} or {@code channel} is {@code null}
3343         * @throws TS3CommandFailedException
3344         *              if the execution of a command fails
3345         * @querycommands 1
3346         */
3347        public void moveClient(Client client, ChannelBase channel, String channelPassword) {
3348                asyncApi.moveClient(client, channel, channelPassword).getUninterruptibly();
3349        }
3350
3351        /**
3352         * Moves multiple clients into a channel using the specified password.
3353         * Immediately returns {@code true} for an empty client array.
3354         * <p>
3355         * Use this method instead of {@link #moveClient(Client, ChannelBase, String)} for moving
3356         * several clients as this will only send 1 command to the server and thus complete faster.
3357         * </p>
3358         *
3359         * @param clients
3360         *              the clients to move, cannot be {@code null}
3361         * @param channel
3362         *              the channel to move the clients into, cannot be {@code null}
3363         * @param channelPassword
3364         *              the password of the channel, can be {@code null}
3365         *
3366         * @throws IllegalArgumentException
3367         *              if {@code clients} or {@code channel} is {@code null}
3368         * @throws TS3CommandFailedException
3369         *              if the execution of a command fails
3370         * @querycommands 1
3371         */
3372        public void moveClients(Client[] clients, ChannelBase channel, String channelPassword) {
3373                asyncApi.moveClients(clients, channel, channelPassword).getUninterruptibly();
3374        }
3375
3376        /**
3377         * Moves and renames a file on the file repository within the same channel.
3378         *
3379         * @param oldPath
3380         *              the current path to the file
3381         * @param newPath
3382         *              the desired new path
3383         * @param channelId
3384         *              the ID of the channel the file resides in
3385         *
3386         * @throws TS3CommandFailedException
3387         *              if the execution of a command fails
3388         * @querycommands 1
3389         * @see FileInfo#getPath()
3390         * @see Channel#getId()
3391         * @see #moveFile(String, String, int, int) moveFile to a different channel
3392         */
3393        public void moveFile(String oldPath, String newPath, int channelId) {
3394                asyncApi.moveFile(oldPath, newPath, channelId).getUninterruptibly();
3395        }
3396
3397        /**
3398         * Renames a file on the file repository and moves it to a new path in a different channel.
3399         *
3400         * @param oldPath
3401         *              the current path to the file
3402         * @param newPath
3403         *              the desired new path
3404         * @param oldChannelId
3405         *              the ID of the channel the file currently resides in
3406         * @param newChannelId
3407         *              the ID of the channel the file should be moved to
3408         *
3409         * @throws TS3CommandFailedException
3410         *              if the execution of a command fails
3411         * @querycommands 1
3412         * @see FileInfo#getPath()
3413         * @see Channel#getId()
3414         * @see #moveFile(String, String, int) moveFile within the same channel
3415         */
3416        public void moveFile(String oldPath, String newPath, int oldChannelId, int newChannelId) {
3417                asyncApi.moveFile(oldPath, newPath, oldChannelId, newChannelId).getUninterruptibly();
3418        }
3419
3420        /**
3421         * Moves and renames a file on the file repository within the same channel.
3422         *
3423         * @param oldPath
3424         *              the current path to the file
3425         * @param newPath
3426         *              the desired new path
3427         * @param channelId
3428         *              the ID of the channel the file resides in
3429         * @param channelPassword
3430         *              the password of the channel
3431         *
3432         * @throws TS3CommandFailedException
3433         *              if the execution of a command fails
3434         * @querycommands 1
3435         * @see FileInfo#getPath()
3436         * @see Channel#getId()
3437         * @see #moveFile(String, String, int, String, int, String) moveFile to a different channel
3438         */
3439        public void moveFile(String oldPath, String newPath, int channelId, String channelPassword) {
3440                asyncApi.moveFile(oldPath, newPath, channelId, channelPassword).getUninterruptibly();
3441        }
3442
3443        /**
3444         * Renames a file on the file repository and moves it to a new path in a different channel.
3445         *
3446         * @param oldPath
3447         *              the current path to the file
3448         * @param newPath
3449         *              the desired new path
3450         * @param oldChannelId
3451         *              the ID of the channel the file currently resides in
3452         * @param oldPassword
3453         *              the password of the current channel
3454         * @param newChannelId
3455         *              the ID of the channel the file should be moved to
3456         * @param newPassword
3457         *              the password of the new channel
3458         *
3459         * @throws TS3CommandFailedException
3460         *              if the execution of a command fails
3461         * @querycommands 1
3462         * @see FileInfo#getPath()
3463         * @see Channel#getId()
3464         * @see #moveFile(String, String, int, String) moveFile within the same channel
3465         */
3466        public void moveFile(String oldPath, String newPath, int oldChannelId, String oldPassword, int newChannelId, String newPassword) {
3467                asyncApi.moveFile(oldPath, newPath, oldChannelId, oldPassword, newChannelId, newPassword).getUninterruptibly();
3468        }
3469
3470        /**
3471         * Moves the server query into a channel.
3472         *
3473         * @param channelId
3474         *              the ID of the channel to move the server query into
3475         *
3476         * @throws TS3CommandFailedException
3477         *              if the execution of a command fails
3478         * @querycommands 1
3479         * @see Channel#getId()
3480         */
3481        public void moveQuery(int channelId) {
3482                asyncApi.moveQuery(channelId).getUninterruptibly();
3483        }
3484
3485        /**
3486         * Moves the server query into a channel.
3487         *
3488         * @param channel
3489         *              the channel to move the server query into, cannot be {@code null}
3490         *
3491         * @throws IllegalArgumentException
3492         *              if {@code channel} is {@code null}
3493         * @throws TS3CommandFailedException
3494         *              if the execution of a command fails
3495         * @querycommands 1
3496         */
3497        public void moveQuery(ChannelBase channel) {
3498                asyncApi.moveQuery(channel).getUninterruptibly();
3499        }
3500
3501        /**
3502         * Moves the server query into a channel using the specified password.
3503         *
3504         * @param channelId
3505         *              the ID of the channel to move the client into
3506         * @param channelPassword
3507         *              the password of the channel, can be {@code null}
3508         *
3509         * @throws TS3CommandFailedException
3510         *              if the execution of a command fails
3511         * @querycommands 1
3512         * @see Channel#getId()
3513         */
3514        public void moveQuery(int channelId, String channelPassword) {
3515                asyncApi.moveQuery(channelId, channelPassword).getUninterruptibly();
3516        }
3517
3518        /**
3519         * Moves the server query into a channel using the specified password.
3520         *
3521         * @param channel
3522         *              the channel to move the client into, cannot be {@code null}
3523         * @param channelPassword
3524         *              the password of the channel, can be {@code null}
3525         *
3526         * @throws IllegalArgumentException
3527         *              if {@code channel} is {@code null}
3528         * @throws TS3CommandFailedException
3529         *              if the execution of a command fails
3530         * @querycommands 1
3531         */
3532        public void moveQuery(ChannelBase channel, String channelPassword) {
3533                asyncApi.moveQuery(channel, channelPassword).getUninterruptibly();
3534        }
3535
3536        /**
3537         * Pokes the client with the specified client ID.
3538         * This opens up a small popup window for the client containing your message and plays a sound.
3539         * The displayed message will be formatted like this: <br>
3540         * {@code hh:mm:ss - "Your Nickname" poked you: <your message in green color>}
3541         * <p>
3542         * The displayed message length is limited to 100 UTF-8 bytes.
3543         * If a client has already received a poke message, all subsequent pokes will simply add a line
3544         * to the already opened popup window and will still play a sound.
3545         * </p>
3546         *
3547         * @param clientId
3548         *              the ID of the client to poke
3549         * @param message
3550         *              the message to send, may contain BB codes
3551         *
3552         * @throws TS3CommandFailedException
3553         *              if the execution of a command fails
3554         * @querycommands 1
3555         * @see Client#getId()
3556         */
3557        public void pokeClient(int clientId, String message) {
3558                asyncApi.pokeClient(clientId, message).getUninterruptibly();
3559        }
3560
3561        /**
3562         * Terminates the connection with the TeamSpeak3 server.
3563         * <p>
3564         * This command should never be executed by a user of this API,
3565         * as it leaves the query in an undefined state. To terminate
3566         * a connection regularly, use {@link TS3Query#exit()}.
3567         * </p>
3568         *
3569         * @throws TS3CommandFailedException
3570         *              if the execution of a command fails
3571         * @querycommands 1
3572         */
3573        void quit() {
3574                asyncApi.quit().getUninterruptibly();
3575        }
3576
3577        /**
3578         * Registers the server query to receive notifications about all server events.
3579         * <p>
3580         * This means that the following actions will trigger event notifications:
3581         * </p>
3582         * <ul>
3583         * <li>A client joins the server or disconnects from it</li>
3584         * <li>A client switches channels</li>
3585         * <li>A client sends a server message</li>
3586         * <li>A client sends a channel message <b>in the channel the query is in</b></li>
3587         * <li>A client sends a private message to <b>the server query</b></li>
3588         * <li>A client uses a privilege key</li>
3589         * </ul>
3590         * <p>
3591         * The limitations to when the query receives notifications about chat events cannot be circumvented.
3592         * </p>
3593         * To be able to process these events in your application, register an event listener.
3594         *
3595         * @throws TS3CommandFailedException
3596         *              if the execution of a command fails
3597         * @querycommands 6
3598         * @see #addTS3Listeners(TS3Listener...)
3599         */
3600        public void registerAllEvents() {
3601                asyncApi.registerAllEvents().getUninterruptibly();
3602        }
3603
3604        /**
3605         * Registers the server query to receive notifications about a given event type.
3606         * <p>
3607         * If used with {@link TS3EventType#TEXT_CHANNEL}, this will listen to chat events in the current channel.
3608         * If used with {@link TS3EventType#CHANNEL}, this will listen to <b>all</b> channel events.
3609         * To specify a different channel for channel events, use {@link #registerEvent(TS3EventType, int)}.
3610         * </p>
3611         *
3612         * @param eventType
3613         *              the event type to be notified about
3614         *
3615         * @throws TS3CommandFailedException
3616         *              if the execution of a command fails
3617         * @querycommands 1
3618         * @see #addTS3Listeners(TS3Listener...)
3619         * @see #registerEvent(TS3EventType, int)
3620         * @see #registerAllEvents()
3621         */
3622        public void registerEvent(TS3EventType eventType) {
3623                asyncApi.registerEvent(eventType).getUninterruptibly();
3624        }
3625
3626        /**
3627         * Registers the server query to receive notifications about a given event type.
3628         *
3629         * @param eventType
3630         *              the event type to be notified about
3631         * @param channelId
3632         *              the ID of the channel to listen to, will be ignored if set to {@code -1}.
3633         *              Can be set to {@code 0} for {@link TS3EventType#CHANNEL} to receive notifications about all channel switches.
3634         *
3635         * @throws TS3CommandFailedException
3636         *              if the execution of a command fails
3637         * @querycommands 1
3638         * @see Channel#getId()
3639         * @see #addTS3Listeners(TS3Listener...)
3640         * @see #registerAllEvents()
3641         */
3642        public void registerEvent(TS3EventType eventType, int channelId) {
3643                asyncApi.registerEvent(eventType, channelId).getUninterruptibly();
3644        }
3645
3646        /**
3647         * Registers the server query to receive notifications about multiple given event types.
3648         * <p>
3649         * If used with {@link TS3EventType#TEXT_CHANNEL}, this will listen to chat events in the current channel.
3650         * If used with {@link TS3EventType#CHANNEL}, this will listen to <b>all</b> channel events.
3651         * To specify a different channel for channel events, use {@link #registerEvent(TS3EventType, int)}.
3652         * </p>
3653         *
3654         * @param eventTypes
3655         *              the event types to be notified about
3656         *
3657         * @throws TS3CommandFailedException
3658         *              if the execution of a command fails
3659         * @querycommands n, one command per TS3EventType
3660         * @see #addTS3Listeners(TS3Listener...)
3661         * @see #registerEvent(TS3EventType, int)
3662         * @see #registerAllEvents()
3663         */
3664        public void registerEvents(TS3EventType... eventTypes) {
3665                asyncApi.registerEvents(eventTypes).getUninterruptibly();
3666        }
3667
3668        /**
3669         * Removes the client specified by its database ID from the specified server group.
3670         *
3671         * @param serverGroupId
3672         *              the ID of the server group
3673         * @param clientDatabaseId
3674         *              the database ID of the client
3675         *
3676         * @throws TS3CommandFailedException
3677         *              if the execution of a command fails
3678         * @querycommands 1
3679         * @see ServerGroup#getId()
3680         * @see Client#getDatabaseId()
3681         * @see #removeClientFromServerGroup(ServerGroup, Client)
3682         */
3683        public void removeClientFromServerGroup(int serverGroupId, int clientDatabaseId) {
3684                asyncApi.removeClientFromServerGroup(serverGroupId, clientDatabaseId).getUninterruptibly();
3685        }
3686
3687        /**
3688         * Removes the specified client from the specified server group.
3689         *
3690         * @param serverGroup
3691         *              the server group to remove the client from
3692         * @param client
3693         *              the client to remove from the server group
3694         *
3695         * @throws TS3CommandFailedException
3696         *              if the execution of a command fails
3697         * @querycommands 1
3698         * @see #removeClientFromServerGroup(int, int)
3699         */
3700        public void removeClientFromServerGroup(ServerGroup serverGroup, Client client) {
3701                asyncApi.removeClientFromServerGroup(serverGroup, client).getUninterruptibly();
3702        }
3703
3704        /**
3705         * Removes one or more {@link TS3Listener}s to the event manager of the query.
3706         * <p>
3707         * If a listener was not actually registered, it will be ignored and no exception will be thrown.
3708         * </p>
3709         *
3710         * @param listeners
3711         *              one or more listeners to remove
3712         *
3713         * @see #addTS3Listeners(TS3Listener...)
3714         * @see TS3Listener
3715         * @see TS3EventType
3716         */
3717        public void removeTS3Listeners(TS3Listener... listeners) {
3718                asyncApi.removeTS3Listeners(listeners);
3719        }
3720
3721        /**
3722         * Renames the channel group with the specified ID.
3723         *
3724         * @param channelGroupId
3725         *              the ID of the channel group to rename
3726         * @param name
3727         *              the new name for the channel group
3728         *
3729         * @throws TS3CommandFailedException
3730         *              if the execution of a command fails
3731         * @querycommands 1
3732         * @see ChannelGroup#getId()
3733         * @see #renameChannelGroup(ChannelGroup, String)
3734         */
3735        public void renameChannelGroup(int channelGroupId, String name) {
3736                asyncApi.renameChannelGroup(channelGroupId, name).getUninterruptibly();
3737        }
3738
3739        /**
3740         * Renames the specified channel group.
3741         *
3742         * @param channelGroup
3743         *              the channel group to rename
3744         * @param name
3745         *              the new name for the channel group
3746         *
3747         * @throws TS3CommandFailedException
3748         *              if the execution of a command fails
3749         * @querycommands 1
3750         * @see #renameChannelGroup(int, String)
3751         */
3752        public void renameChannelGroup(ChannelGroup channelGroup, String name) {
3753                asyncApi.renameChannelGroup(channelGroup, name).getUninterruptibly();
3754        }
3755
3756        /**
3757         * Renames the server group with the specified ID.
3758         *
3759         * @param serverGroupId
3760         *              the ID of the server group to rename
3761         * @param name
3762         *              the new name for the server group
3763         *
3764         * @throws TS3CommandFailedException
3765         *              if the execution of a command fails
3766         * @querycommands 1
3767         * @see ServerGroup#getId()
3768         * @see #renameServerGroup(ServerGroup, String)
3769         */
3770        public void renameServerGroup(int serverGroupId, String name) {
3771                asyncApi.renameServerGroup(serverGroupId, name).getUninterruptibly();
3772        }
3773
3774        /**
3775         * Renames the specified server group.
3776         *
3777         * @param serverGroup
3778         *              the server group to rename
3779         * @param name
3780         *              the new name for the server group
3781         *
3782         * @throws TS3CommandFailedException
3783         *              if the execution of a command fails
3784         * @querycommands 1
3785         * @see #renameServerGroup(int, String)
3786         */
3787        public void renameServerGroup(ServerGroup serverGroup, String name) {
3788                asyncApi.renameServerGroup(serverGroup, name).getUninterruptibly();
3789        }
3790
3791        /**
3792         * Resets all permissions and deletes all server / channel groups. Use carefully.
3793         *
3794         * @return a token for a new administrator account
3795         *
3796         * @throws TS3CommandFailedException
3797         *              if the execution of a command fails
3798         * @querycommands 1
3799         */
3800        public String resetPermissions() {
3801                return asyncApi.resetPermissions().getUninterruptibly();
3802        }
3803
3804        /**
3805         * Finds all clients that have any value associated with the {@code key} custom client property,
3806         * and returns the client's database ID and the key and value of the matching custom property.
3807         *
3808         * @param key
3809         *              the key to search for, cannot be {@code null}
3810         *
3811         * @return a list of client database IDs and their matching custom client properties
3812         *
3813         * @throws TS3CommandFailedException
3814         *              if the execution of a command fails
3815         * @querycommands 1
3816         * @see Client#getDatabaseId()
3817         * @see #searchCustomClientProperty(String, String)
3818         * @see #getCustomClientProperties(int)
3819         */
3820        public List<CustomPropertyAssignment> searchCustomClientProperty(String key) {
3821                return asyncApi.searchCustomClientProperty(key).getUninterruptibly();
3822        }
3823
3824        /**
3825         * Finds all clients whose value associated with the {@code key} custom client property matches the
3826         * SQL-like pattern {@code valuePattern}, and returns the client's database ID and the key and value
3827         * of the matching custom property.
3828         * <p>
3829         * Patterns are case insensitive. They support the wildcard characters {@code %}, which matches any sequence of
3830         * zero or more characters, and {@code _}, which matches exactly one arbitrary character.
3831         * </p>
3832         *
3833         * @param key
3834         *              the key to search for, cannot be {@code null}
3835         * @param valuePattern
3836         *              the pattern that values need to match to be included
3837         *
3838         * @return a list of client database IDs and their matching custom client properties
3839         *
3840         * @throws TS3CommandFailedException
3841         *              if the execution of a command fails
3842         * @querycommands 1
3843         * @see Client#getDatabaseId()
3844         * @see #searchCustomClientProperty(String)
3845         * @see #getCustomClientProperties(int)
3846         */
3847        public List<CustomPropertyAssignment> searchCustomClientProperty(String key, String valuePattern) {
3848                return asyncApi.searchCustomClientProperty(key, valuePattern).getUninterruptibly();
3849        }
3850
3851        /**
3852         * Moves the server query into the virtual server with the specified ID.
3853         *
3854         * @param id
3855         *              the ID of the virtual server
3856         *
3857         * @throws TS3CommandFailedException
3858         *              if the execution of a command fails
3859         * @querycommands 1
3860         * @see VirtualServer#getId()
3861         * @see #selectVirtualServerById(int, String)
3862         * @see #selectVirtualServerByPort(int)
3863         * @see #selectVirtualServer(VirtualServer)
3864         */
3865        public void selectVirtualServerById(int id) {
3866                asyncApi.selectVirtualServerById(id).getUninterruptibly();
3867        }
3868
3869        /**
3870         * Moves the server query into the virtual server with the specified ID
3871         * and sets the server query's nickname.
3872         * <p>
3873         * The nickname must be between 3 and 30 UTF-8 bytes long. BB codes will be ignored.
3874         * </p>
3875         *
3876         * @param id
3877         *              the ID of the virtual server
3878         * @param nickname
3879         *              the nickname, or {@code null} if the nickname should not be set
3880         *
3881         * @throws TS3CommandFailedException
3882         *              if the execution of a command fails
3883         * @querycommands 1
3884         * @see VirtualServer#getId()
3885         * @see #selectVirtualServerById(int)
3886         * @see #selectVirtualServerByPort(int, String)
3887         * @see #selectVirtualServer(VirtualServer, String)
3888         */
3889        public void selectVirtualServerById(int id, String nickname) {
3890                asyncApi.selectVirtualServerById(id, nickname).getUninterruptibly();
3891        }
3892
3893        /**
3894         * Moves the server query into the virtual server with the specified voice port.
3895         *
3896         * @param port
3897         *              the voice port of the virtual server
3898         *
3899         * @throws TS3CommandFailedException
3900         *              if the execution of a command fails
3901         * @querycommands 1
3902         * @see VirtualServer#getPort()
3903         * @see #selectVirtualServerById(int)
3904         * @see #selectVirtualServerByPort(int, String)
3905         * @see #selectVirtualServer(VirtualServer)
3906         */
3907        public void selectVirtualServerByPort(int port) {
3908                asyncApi.selectVirtualServerByPort(port).getUninterruptibly();
3909        }
3910
3911        /**
3912         * Moves the server query into the virtual server with the specified voice port
3913         * and sets the server query's nickname.
3914         * <p>
3915         * The nickname must be between 3 and 30 UTF-8 bytes long. BB codes will be ignored.
3916         * </p>
3917         *
3918         * @param port
3919         *              the voice port of the virtual server
3920         * @param nickname
3921         *              the nickname, or {@code null} if the nickname should not be set
3922         *
3923         * @throws TS3CommandFailedException
3924         *              if the execution of a command fails
3925         * @querycommands 1
3926         * @see VirtualServer#getPort()
3927         * @see #selectVirtualServerById(int, String)
3928         * @see #selectVirtualServerByPort(int)
3929         * @see #selectVirtualServer(VirtualServer, String)
3930         */
3931        public void selectVirtualServerByPort(int port, String nickname) {
3932                asyncApi.selectVirtualServerByPort(port, nickname).getUninterruptibly();
3933        }
3934
3935        /**
3936         * Moves the server query into the specified virtual server.
3937         *
3938         * @param server
3939         *              the virtual server to move into
3940         *
3941         * @throws TS3CommandFailedException
3942         *              if the execution of a command fails
3943         * @querycommands 1
3944         * @see #selectVirtualServerById(int)
3945         * @see #selectVirtualServerByPort(int)
3946         * @see #selectVirtualServer(VirtualServer, String)
3947         */
3948        public void selectVirtualServer(VirtualServer server) {
3949                asyncApi.selectVirtualServer(server).getUninterruptibly();
3950        }
3951
3952        /**
3953         * Moves the server query into the specified virtual server
3954         * and sets the server query's nickname.
3955         * <p>
3956         * The nickname must be between 3 and 30 UTF-8 bytes long. BB codes will be ignored.
3957         * </p>
3958         *
3959         * @param server
3960         *              the virtual server to move into
3961         * @param nickname
3962         *              the nickname, or {@code null} if the nickname should not be set
3963         *
3964         * @throws TS3CommandFailedException
3965         *              if the execution of a command fails
3966         * @querycommands 1
3967         * @see #selectVirtualServerById(int, String)
3968         * @see #selectVirtualServerByPort(int, String)
3969         * @see #selectVirtualServer(VirtualServer)
3970         */
3971        public void selectVirtualServer(VirtualServer server, String nickname) {
3972                asyncApi.selectVirtualServer(server, nickname).getUninterruptibly();
3973        }
3974
3975        /**
3976         * Sends an offline message to the client with the given unique identifier.
3977         * <p>
3978         * The message subject's length is limited to 200 UTF-8 bytes and BB codes in it will be ignored.
3979         * The message body's length is limited to 4096 UTF-8 bytes and accepts BB codes
3980         * </p>
3981         *
3982         * @param clientUId
3983         *              the unique identifier of the client to send the message to
3984         * @param subject
3985         *              the subject for the message, may not contain BB codes
3986         * @param message
3987         *              the actual message body, may contain BB codes
3988         *
3989         * @throws TS3CommandFailedException
3990         *              if the execution of a command fails
3991         * @querycommands 1
3992         * @see Client#getUniqueIdentifier()
3993         * @see Message
3994         */
3995        public void sendOfflineMessage(String clientUId, String subject, String message) {
3996                asyncApi.sendOfflineMessage(clientUId, subject, message).getUninterruptibly();
3997        }
3998
3999        /**
4000         * Sends a text message either to the whole virtual server, a channel or specific client.
4001         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4002         * <p>
4003         * To send a message to all virtual servers, use {@link #broadcast(String)}.
4004         * To send an offline message, use {@link #sendOfflineMessage(String, String, String)}.
4005         * </p>
4006         *
4007         * @param targetMode
4008         *              where the message should be sent to
4009         * @param targetId
4010         *              the client ID of the recipient of this message. This value is ignored unless {@code targetMode} is {@code CLIENT}
4011         * @param message
4012         *              the text message to send
4013         *
4014         * @throws TS3CommandFailedException
4015         *              if the execution of a command fails
4016         * @querycommands 1
4017         * @see Client#getId()
4018         */
4019        public void sendTextMessage(TextMessageTargetMode targetMode, int targetId, String message) {
4020                asyncApi.sendTextMessage(targetMode, targetId, message).getUninterruptibly();
4021        }
4022
4023        /**
4024         * Sends a text message to the channel with the specified ID.
4025         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4026         * <p>
4027         * This will move the client into the channel with the specified channel ID,
4028         * <b>but will not move it back to the original channel!</b>
4029         * </p>
4030         *
4031         * @param channelId
4032         *              the ID of the channel to which the message should be sent to
4033         * @param message
4034         *              the text message to send
4035         *
4036         * @throws TS3CommandFailedException
4037         *              if the execution of a command fails
4038         * @querycommands 1
4039         * @see #sendChannelMessage(String)
4040         * @see Channel#getId()
4041         */
4042        public void sendChannelMessage(int channelId, String message) {
4043                asyncApi.sendChannelMessage(channelId, message).getUninterruptibly();
4044        }
4045
4046        /**
4047         * Sends a text message to the channel the server query is currently in.
4048         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4049         *
4050         * @param message
4051         *              the text message to send
4052         *
4053         * @throws TS3CommandFailedException
4054         *              if the execution of a command fails
4055         * @querycommands 1
4056         */
4057        public void sendChannelMessage(String message) {
4058                asyncApi.sendChannelMessage(message).getUninterruptibly();
4059        }
4060
4061        /**
4062         * Sends a text message to the virtual server with the specified ID.
4063         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4064         * <p>
4065         * This will move the client to the virtual server with the specified server ID,
4066         * <b>but will not move it back to the original virtual server!</b>
4067         * </p>
4068         *
4069         * @param serverId
4070         *              the ID of the virtual server to which the message should be sent to
4071         * @param message
4072         *              the text message to send
4073         *
4074         * @throws TS3CommandFailedException
4075         *              if the execution of a command fails
4076         * @querycommands 1
4077         * @see #sendServerMessage(String)
4078         * @see VirtualServer#getId()
4079         */
4080        public void sendServerMessage(int serverId, String message) {
4081                asyncApi.sendServerMessage(serverId, message).getUninterruptibly();
4082        }
4083
4084        /**
4085         * Sends a text message to the virtual server the server query is currently in.
4086         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4087         *
4088         * @param message
4089         *              the text message to send
4090         *
4091         * @throws TS3CommandFailedException
4092         *              if the execution of a command fails
4093         * @querycommands 1
4094         */
4095        public void sendServerMessage(String message) {
4096                asyncApi.sendServerMessage(message).getUninterruptibly();
4097        }
4098
4099        /**
4100         * Sends a private message to the client with the specified client ID.
4101         * Your message may contain BB codes, but its length is limited to 1024 UTF-8 bytes.
4102         *
4103         * @param clientId
4104         *              the ID of the client to send the message to
4105         * @param message
4106         *              the text message to send
4107         *
4108         * @throws TS3CommandFailedException
4109         *              if the execution of a command fails
4110         * @querycommands 1
4111         * @see Client#getId()
4112         */
4113        public void sendPrivateMessage(int clientId, String message) {
4114                asyncApi.sendPrivateMessage(clientId, message).getUninterruptibly();
4115        }
4116
4117        /**
4118         * Sets a channel group for a client in a specific channel.
4119         *
4120         * @param groupId
4121         *              the ID of the group the client should join
4122         * @param channelId
4123         *              the ID of the channel where the channel group should be assigned
4124         * @param clientDBId
4125         *              the database ID of the client for which the channel group should be set
4126         *
4127         * @throws TS3CommandFailedException
4128         *              if the execution of a command fails
4129         * @querycommands 1
4130         * @see ChannelGroup#getId()
4131         * @see Channel#getId()
4132         * @see Client#getDatabaseId()
4133         */
4134        public void setClientChannelGroup(int groupId, int channelId, int clientDBId) {
4135                asyncApi.setClientChannelGroup(groupId, channelId, clientDBId).getUninterruptibly();
4136        }
4137
4138        /**
4139         * Sets the value of the multiple custom client properties for a client.
4140         * <p>
4141         * If any key present in the map already has a value assigned for this client,
4142         * the existing value will be overwritten.
4143         * This method does not delete keys not present in the map.
4144         * </p><p>
4145         * If {@code properties} contains an entry with {@code null} as its key,
4146         * that entry will be ignored and no exception will be thrown.
4147         * </p>
4148         *
4149         * @param clientDBId
4150         *              the database ID of the target client
4151         * @param properties
4152         *              the map of properties to set, cannot be {@code null}
4153         *
4154         * @throws TS3CommandFailedException
4155         *              if the execution of a command fails
4156         * @querycommands properties.size()
4157         * @see Client#getDatabaseId()
4158         * @see #setCustomClientProperty(int, String, String)
4159         * @see #deleteCustomClientProperty(int, String)
4160         */
4161        public void setCustomClientProperties(int clientDBId, Map<String, String> properties) {
4162                asyncApi.setCustomClientProperties(clientDBId, properties).getUninterruptibly();
4163        }
4164
4165        /**
4166         * Sets the value of the {@code key} custom client property for a client.
4167         * <p>
4168         * If there is already an assignment of the {@code key} custom client property
4169         * for this client, the existing value will be overwritten.
4170         * </p>
4171         *
4172         * @param clientDBId
4173         *              the database ID of the target client
4174         * @param key
4175         *              the key of the custom property to set, cannot be {@code null}
4176         * @param value
4177         *              the (new) value of the custom property to set
4178         *
4179         * @throws TS3CommandFailedException
4180         *              if the execution of a command fails
4181         * @querycommands 1
4182         * @see Client#getDatabaseId()
4183         * @see #setCustomClientProperties(int, Map)
4184         * @see #deleteCustomClientProperty(int, String)
4185         */
4186        public void setCustomClientProperty(int clientDBId, String key, String value) {
4187                asyncApi.setCustomClientProperty(clientDBId, key, value).getUninterruptibly();
4188        }
4189
4190        /**
4191         * Sets the read flag to {@code true} for a given message. This will not delete the message.
4192         *
4193         * @param messageId
4194         *              the ID of the message for which the read flag should be set
4195         *
4196         * @throws TS3CommandFailedException
4197         *              if the execution of a command fails
4198         * @querycommands 1
4199         * @see #setMessageReadFlag(int, boolean)
4200         */
4201        public void setMessageRead(int messageId) {
4202                asyncApi.setMessageRead(messageId).getUninterruptibly();
4203        }
4204
4205        /**
4206         * Sets the read flag to {@code true} for a given message. This will not delete the message.
4207         *
4208         * @param message
4209         *              the message for which the read flag should be set
4210         *
4211         * @throws TS3CommandFailedException
4212         *              if the execution of a command fails
4213         * @querycommands 1
4214         * @see #setMessageRead(int)
4215         * @see #setMessageReadFlag(Message, boolean)
4216         * @see #deleteOfflineMessage(int)
4217         */
4218        public void setMessageRead(Message message) {
4219                asyncApi.setMessageRead(message).getUninterruptibly();
4220        }
4221
4222        /**
4223         * Sets the read flag for a given message. This will not delete the message.
4224         *
4225         * @param messageId
4226         *              the ID of the message for which the read flag should be set
4227         * @param read
4228         *              the boolean value to which the read flag should be set
4229         *
4230         * @throws TS3CommandFailedException
4231         *              if the execution of a command fails
4232         * @querycommands 1
4233         * @see #setMessageRead(int)
4234         * @see #setMessageReadFlag(Message, boolean)
4235         * @see #deleteOfflineMessage(int)
4236         */
4237        public void setMessageReadFlag(int messageId, boolean read) {
4238                asyncApi.setMessageReadFlag(messageId, read).getUninterruptibly();
4239        }
4240
4241        /**
4242         * Sets the read flag for a given message. This will not delete the message.
4243         *
4244         * @param message
4245         *              the message for which the read flag should be set
4246         * @param read
4247         *              the boolean value to which the read flag should be set
4248         *
4249         * @throws TS3CommandFailedException
4250         *              if the execution of a command fails
4251         * @querycommands 1
4252         * @see #setMessageRead(Message)
4253         * @see #setMessageReadFlag(int, boolean)
4254         * @see #deleteOfflineMessage(int)
4255         */
4256        public void setMessageReadFlag(Message message, boolean read) {
4257                asyncApi.setMessageReadFlag(message, read).getUninterruptibly();
4258        }
4259
4260        /**
4261         * Sets the nickname of the server query client.
4262         * <p>
4263         * The nickname must be between 3 and 30 UTF-8 bytes long. BB codes will be ignored.
4264         * </p>
4265         *
4266         * @param nickname
4267         *              the new nickname, may not be {@code null}
4268         *
4269         * @throws TS3CommandFailedException
4270         *              if the execution of a command fails
4271         * @querycommands 1
4272         * @see #updateClient(Map)
4273         */
4274        public void setNickname(String nickname) {
4275                asyncApi.setNickname(nickname).getUninterruptibly();
4276        }
4277
4278        /**
4279         * Starts the virtual server with the specified ID.
4280         *
4281         * @param serverId
4282         *              the ID of the virtual server
4283         *
4284         * @throws TS3CommandFailedException
4285         *              if the execution of a command fails
4286         * @querycommands 1
4287         */
4288        public void startServer(int serverId) {
4289                asyncApi.startServer(serverId).getUninterruptibly();
4290        }
4291
4292        /**
4293         * Starts the specified virtual server.
4294         *
4295         * @param virtualServer
4296         *              the virtual server to start
4297         *
4298         * @throws TS3CommandFailedException
4299         *              if the execution of a command fails
4300         * @querycommands 1
4301         */
4302        public void startServer(VirtualServer virtualServer) {
4303                asyncApi.startServer(virtualServer).getUninterruptibly();
4304        }
4305
4306        /**
4307         * Stops the virtual server with the specified ID.
4308         *
4309         * @param serverId
4310         *              the ID of the virtual server
4311         *
4312         * @throws TS3CommandFailedException
4313         *              if the execution of a command fails
4314         * @querycommands 1
4315         */
4316        public void stopServer(int serverId) {
4317                asyncApi.stopServer(serverId).getUninterruptibly();
4318        }
4319
4320        /**
4321         * Stops the virtual server with the specified ID.
4322         *
4323         * @param serverId
4324         *              the ID of the virtual server
4325         * @param reason
4326         *              the reason message to display to clients when they are disconnected
4327         *
4328         * @throws TS3CommandFailedException
4329         *              if the execution of a command fails
4330         * @querycommands 1
4331         */
4332        public void stopServer(int serverId, String reason) {
4333                asyncApi.stopServer(serverId, reason).getUninterruptibly();
4334        }
4335
4336        /**
4337         * Stops the specified virtual server.
4338         *
4339         * @param virtualServer
4340         *              the virtual server to stop
4341         *
4342         * @throws TS3CommandFailedException
4343         *              if the execution of a command fails
4344         * @querycommands 1
4345         */
4346        public void stopServer(VirtualServer virtualServer) {
4347                asyncApi.stopServer(virtualServer).getUninterruptibly();
4348        }
4349
4350        /**
4351         * Stops the specified virtual server.
4352         *
4353         * @param virtualServer
4354         *              the virtual server to stop
4355         * @param reason
4356         *              the reason message to display to clients when they are disconnected
4357         *
4358         * @throws TS3CommandFailedException
4359         *              if the execution of a command fails
4360         * @querycommands 1
4361         */
4362        public void stopServer(VirtualServer virtualServer, String reason) {
4363                asyncApi.stopServer(virtualServer, reason).getUninterruptibly();
4364        }
4365
4366        /**
4367         * Stops the entire TeamSpeak 3 Server instance by shutting down the process.
4368         * <p>
4369         * To have permission to use this command, you need to use the server query admin login.
4370         * </p>
4371         *
4372         * @throws TS3CommandFailedException
4373         *              if the execution of a command fails
4374         * @querycommands 1
4375         */
4376        public void stopServerProcess() {
4377                asyncApi.stopServerProcess().getUninterruptibly();
4378        }
4379
4380        /**
4381         * Stops the entire TeamSpeak 3 Server instance by shutting down the process.
4382         * <p>
4383         * To have permission to use this command, you need to use the server query admin login.
4384         * </p>
4385         *
4386         * @param reason
4387         *              the reason message to display to clients when they are disconnected
4388         *
4389         * @throws TS3CommandFailedException
4390         *              if the execution of a command fails
4391         * @querycommands 1
4392         */
4393        public void stopServerProcess(String reason) {
4394                asyncApi.stopServerProcess(reason).getUninterruptibly();
4395        }
4396
4397        /**
4398         * Unregisters the server query from receiving any event notifications.
4399         *
4400         * @throws TS3CommandFailedException
4401         *              if the execution of a command fails
4402         * @querycommands 1
4403         */
4404        public void unregisterAllEvents() {
4405                asyncApi.unregisterAllEvents().getUninterruptibly();
4406        }
4407
4408        /**
4409         * Updates several client properties for this server query instance.
4410         *
4411         * @param options
4412         *              the map of properties to update
4413         *
4414         * @throws TS3CommandFailedException
4415         *              if the execution of a command fails
4416         * @querycommands 1
4417         * @see #updateClient(ClientProperty, String)
4418         * @see #editClient(int, Map)
4419         */
4420        public void updateClient(Map<ClientProperty, String> options) {
4421                asyncApi.updateClient(options).getUninterruptibly();
4422        }
4423
4424        /**
4425         * Changes a single client property for this server query instance.
4426         * <p>
4427         * Note that one can set many properties at once with the overloaded method that
4428         * takes a map of client properties and strings.
4429         * </p>
4430         *
4431         * @param property
4432         *              the client property to modify, make sure it is editable
4433         * @param value
4434         *              the new value of the property
4435         *
4436         * @throws TS3CommandFailedException
4437         *              if the execution of a command fails
4438         * @querycommands 1
4439         * @see #updateClient(Map)
4440         * @see #editClient(int, Map)
4441         */
4442        public void updateClient(ClientProperty property, String value) {
4443                asyncApi.updateClient(property, value).getUninterruptibly();
4444        }
4445
4446        /**
4447         * Generates new login credentials for the currently connected server query instance, using the given name.
4448         * <p>
4449         * <b>This will remove the current login credentials!</b> You won't be logged out, but after disconnecting,
4450         * the old credentials will no longer work. Make sure to not lock yourselves out!
4451         * </p>
4452         *
4453         * @param loginName
4454         *              the name for the server query login
4455         *
4456         * @return the generated password for the server query login
4457         *
4458         * @throws TS3CommandFailedException
4459         *              if the execution of a command fails
4460         * @querycommands 1
4461         * @see #addServerQueryLogin(String, int)
4462         * @see #deleteServerQueryLogin(int)
4463         * @see #getServerQueryLogins()
4464         */
4465        public String updateServerQueryLogin(String loginName) {
4466                return asyncApi.updateServerQueryLogin(loginName).getUninterruptibly();
4467        }
4468
4469        /**
4470         * Uploads a file to the file repository at a given path and channel
4471         * by reading {@code dataLength} bytes from an open {@link InputStream}.
4472         * <p>
4473         * It is the user's responsibility to ensure that the given {@code InputStream} is
4474         * open and that {@code dataLength} bytes can eventually be read from it. The user is
4475         * also responsible for closing the stream once the upload has finished.
4476         * </p><p>
4477         * Note that this method will not read the entire file to memory and can thus
4478         * upload arbitrarily sized files to the file repository.
4479         * </p>
4480         *
4481         * @param dataIn
4482         *              a stream that contains the data that should be uploaded
4483         * @param dataLength
4484         *              how many bytes should be read from the stream
4485         * @param filePath
4486         *              the path the file should have after being uploaded
4487         * @param overwrite
4488         *              if {@code false}, fails if there's already a file at {@code filePath}
4489         * @param channelId
4490         *              the ID of the channel to upload the file to
4491         *
4492         * @throws TS3CommandFailedException
4493         *              if the execution of a command fails
4494         * @throws TS3FileTransferFailedException
4495         *              if the file transfer fails for any reason
4496         * @querycommands 1
4497         * @see FileInfo#getPath()
4498         * @see Channel#getId()
4499         * @see #uploadFileDirect(byte[], String, boolean, int, String)
4500         */
4501        public void uploadFile(InputStream dataIn, long dataLength, String filePath, boolean overwrite, int channelId) {
4502                asyncApi.uploadFile(dataIn, dataLength, filePath, overwrite, channelId).getUninterruptibly();
4503        }
4504
4505        /**
4506         * Uploads a file to the file repository at a given path and channel
4507         * by reading {@code dataLength} bytes from an open {@link InputStream}.
4508         * <p>
4509         * It is the user's responsibility to ensure that the given {@code InputStream} is
4510         * open and that {@code dataLength} bytes can eventually be read from it. The user is
4511         * also responsible for closing the stream once the upload has finished.
4512         * </p><p>
4513         * Note that this method will not read the entire file to memory and can thus
4514         * upload arbitrarily sized files to the file repository.
4515         * </p>
4516         *
4517         * @param dataIn
4518         *              a stream that contains the data that should be uploaded
4519         * @param dataLength
4520         *              how many bytes should be read from the stream
4521         * @param filePath
4522         *              the path the file should have after being uploaded
4523         * @param overwrite
4524         *              if {@code false}, fails if there's already a file at {@code filePath}
4525         * @param channelId
4526         *              the ID of the channel to upload the file to
4527         * @param channelPassword
4528         *              that channel's password
4529         *
4530         * @throws TS3CommandFailedException
4531         *              if the execution of a command fails
4532         * @throws TS3FileTransferFailedException
4533         *              if the file transfer fails for any reason
4534         * @querycommands 1
4535         * @see FileInfo#getPath()
4536         * @see Channel#getId()
4537         * @see #uploadFileDirect(byte[], String, boolean, int, String)
4538         */
4539        public void uploadFile(InputStream dataIn, long dataLength, String filePath, boolean overwrite, int channelId, String channelPassword) {
4540                asyncApi.uploadFile(dataIn, dataLength, filePath, overwrite, channelId, channelPassword).getUninterruptibly();
4541        }
4542
4543        /**
4544         * Uploads a file that is already stored in memory to the file repository
4545         * at a given path and channel.
4546         *
4547         * @param data
4548         *              the file's data as a byte array
4549         * @param filePath
4550         *              the path the file should have after being uploaded
4551         * @param overwrite
4552         *              if {@code false}, fails if there's already a file at {@code filePath}
4553         * @param channelId
4554         *              the ID of the channel to upload the file to
4555         *
4556         * @throws TS3CommandFailedException
4557         *              if the execution of a command fails
4558         * @throws TS3FileTransferFailedException
4559         *              if the file transfer fails for any reason
4560         * @querycommands 1
4561         * @see FileInfo#getPath()
4562         * @see Channel#getId()
4563         * @see #uploadFile(InputStream, long, String, boolean, int)
4564         */
4565        public void uploadFileDirect(byte[] data, String filePath, boolean overwrite, int channelId) {
4566                asyncApi.uploadFileDirect(data, filePath, overwrite, channelId).getUninterruptibly();
4567        }
4568
4569        /**
4570         * Uploads a file that is already stored in memory to the file repository
4571         * at a given path and channel.
4572         *
4573         * @param data
4574         *              the file's data as a byte array
4575         * @param filePath
4576         *              the path the file should have after being uploaded
4577         * @param overwrite
4578         *              if {@code false}, fails if there's already a file at {@code filePath}
4579         * @param channelId
4580         *              the ID of the channel to upload the file to
4581         * @param channelPassword
4582         *              that channel's password
4583         *
4584         * @throws TS3CommandFailedException
4585         *              if the execution of a command fails
4586         * @throws TS3FileTransferFailedException
4587         *              if the file transfer fails for any reason
4588         * @querycommands 1
4589         * @see FileInfo#getPath()
4590         * @see Channel#getId()
4591         * @see #uploadFile(InputStream, long, String, boolean, int, String)
4592         */
4593        public void uploadFileDirect(byte[] data, String filePath, boolean overwrite, int channelId, String channelPassword) {
4594                asyncApi.uploadFileDirect(data, filePath, overwrite, channelId, channelPassword).getUninterruptibly();
4595        }
4596
4597        /**
4598         * Uploads an icon to the icon directory in the file repository
4599         * by reading {@code dataLength} bytes from an open {@link InputStream}.
4600         * <p>
4601         * It is the user's responsibility to ensure that the given {@code InputStream} is
4602         * open and that {@code dataLength} bytes can eventually be read from it. The user is
4603         * also responsible for closing the stream once the upload has finished.
4604         * </p><p>
4605         * Note that unlike the file upload methods, this <strong>will read the entire file to memory</strong>.
4606         * This is because the CRC32 hash must be calculated before the icon can be uploaded.
4607         * That means that all icon files must be less than 2<sup>31</sup>-1 bytes in size.
4608         * </p>
4609         * Uploads  that is already stored in memory to the icon directory
4610         * in the file repository. If this icon has already been uploaded or
4611         * if a hash collision occurs (CRC32), this command will fail.
4612         *
4613         * @param dataIn
4614         *              a stream that contains the data that should be uploaded
4615         * @param dataLength
4616         *              how many bytes should be read from the stream
4617         *
4618         * @return the ID of the uploaded icon
4619         *
4620         * @throws TS3CommandFailedException
4621         *              if the execution of a command fails
4622         * @throws TS3FileTransferFailedException
4623         *              if the file transfer fails for any reason
4624         * @querycommands 1
4625         * @see IconFile#getIconId()
4626         * @see #uploadIconDirect(byte[])
4627         * @see #downloadIcon(OutputStream, long)
4628         */
4629        public long uploadIcon(InputStream dataIn, long dataLength) {
4630                return asyncApi.uploadIcon(dataIn, dataLength).getUninterruptibly();
4631        }
4632
4633        /**
4634         * Uploads an icon that is already stored in memory to the icon directory
4635         * in the file repository. If this icon has already been uploaded or
4636         * if a CRC32 hash collision occurs, this command will fail.
4637         *
4638         * @param data
4639         *              the icon's data as a byte array
4640         *
4641         * @return the ID of the uploaded icon
4642         *
4643         * @throws TS3CommandFailedException
4644         *              if the execution of a command fails
4645         * @throws TS3FileTransferFailedException
4646         *              if the file transfer fails for any reason
4647         * @querycommands 1
4648         * @see IconFile#getIconId()
4649         * @see #uploadIcon(InputStream, long)
4650         * @see #downloadIconDirect(long)
4651         */
4652        public long uploadIconDirect(byte[] data) {
4653                return asyncApi.uploadIconDirect(data).getUninterruptibly();
4654        }
4655
4656        /**
4657         * Uses an existing privilege key to join a server or channel group.
4658         *
4659         * @param token
4660         *              the privilege key to use
4661         *
4662         * @throws TS3CommandFailedException
4663         *              if the execution of a command fails
4664         * @querycommands 1
4665         * @see PrivilegeKey
4666         * @see #addPrivilegeKey(PrivilegeKeyType, int, int, String)
4667         * @see #usePrivilegeKey(PrivilegeKey)
4668         */
4669        public void usePrivilegeKey(String token) {
4670                asyncApi.usePrivilegeKey(token).getUninterruptibly();
4671        }
4672
4673        /**
4674         * Uses an existing privilege key to join a server or channel group.
4675         *
4676         * @param privilegeKey
4677         *              the privilege key to use
4678         *
4679         * @throws TS3CommandFailedException
4680         *              if the execution of a command fails
4681         * @querycommands 1
4682         * @see PrivilegeKey
4683         * @see #addPrivilegeKey(PrivilegeKeyType, int, int, String)
4684         * @see #usePrivilegeKey(String)
4685         */
4686        public void usePrivilegeKey(PrivilegeKey privilegeKey) {
4687                asyncApi.usePrivilegeKey(privilegeKey).getUninterruptibly();
4688        }
4689
4690        /**
4691         * Gets information about the current server query instance.
4692         *
4693         * @return information about the server query instance
4694         *
4695         * @throws TS3CommandFailedException
4696         *              if the execution of a command fails
4697         * @querycommands 1
4698         * @see #getClientInfo(int)
4699         */
4700        public ServerQueryInfo whoAmI() {
4701                return asyncApi.whoAmI().getUninterruptibly();
4702        }
4703}