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