Skip to content
35 changes: 22 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# C# TeamSpeak3Query API [![Travis Build Status](https://travis-ci.org/nikeee/TeamSpeak3QueryAPI.svg?branch=master)](https://travis-ci.org/nikeee/TeamSpeak3QueryAPI) ![NuGet Downloads](https://img.shields.io/nuget/dt/TeamSpeak3QueryApi.svg)

An API wrapper for the TeamSpeak 3 Query API written in C#. Still work in progress.
An API wrapper for the TeamSpeak 3 Query API written in C#. **Still work in progress**.

Key features of this library:
- Built entirely with the .NET TAP pattern for perfect async/await usage opportunities
- Robust library architecture
- Query responses are fully mapped to .NET objects, including the naming style
- Usable via Middleware/Rich Client
- SSH and Telnet protocol will be supported

## Contents
1. [Documentation](#documentation)
Expand All @@ -26,9 +27,10 @@ The TeamSpeak 3 Query API is documented [here](http://media.teamspeak.com/ts3_li
This library has an online documentation which was created using [sharpDox](http://sharpdox.de). You can find the documentation on the [GitHub Page of this repository](https://nikeee.github.io/TeamSpeak3QueryAPI).

## Compatibility
This library requires .NET Standard `1.3`. You can look at [this table](https://docs.microsoft.com/en-us/dotnet/standard/net-standard#net-implementation-support) to see whether your platform is supported. If you find something that is missing (espacially in the `TeamSpeakClient` class), just submit a PR or an issue!
This library requires .NET Core `3.0`. You can look at [this table](https://docs.microsoft.com/en-us/dotnet/standard/net-standard#net-implementation-support) to see whether your platform is supported. If you find something that is missing (espacially in the `TeamSpeakClient` class), just submit a PR or an issue!

### NuGet
*This is currently not possible.*
```Shell
Install-Package TeamSpeak3QueryApi
# or
Expand All @@ -39,10 +41,17 @@ dotnet add package TeamSpeak3QueryApi
Using the rich client, you can connect to a TeamSpeak Query server like this:
### Connect and Login

```C#
```C# Telnet query
var rc = new TeamSpeakClient(host, port); // Create rich client instance
await rc.Connect(); // connect to the server
await rc.Login(user, password); // login to do some stuff that requires permission
await rc.ConnectAsync(); // connect to the server
await rc.LoginAsync(user, password); // login to do some stuff that requires permission
await rc.UseServer(1); // Use the server with id '1'
var me = await rc.WhoAmI(); // Get information about yourself!
```

```C# SSH query
var rc = new TeamSpeakClient(host, 10022, Protocol.SSH); // Create rich client instance
await rc.Connect(user, password); // connect to the server with login data
await rc.UseServer(1); // Use the server with id '1'
var me = await rc.WhoAmI(); // Get information about yourself!
```
Expand Down Expand Up @@ -70,15 +79,15 @@ rc.Subscribe<ClientEnterView>(data => {
Getting all clients and moving them to a specific channel is as simple as:

```C#
var currentClients = await rc.GetClients();
var currentClients = await rc.GetClientsAsync();
await rc.MoveClient(currentClients, 30); // Where 30 is the channel id
```
...and kick someone whose name is "Foobar".

```C#
var fooBar = currentClients.SingleOrDefault(c => c.NickName == "Foobar"); // Using linq to find our dude
if(fooBar != null) // Make sure we pass a valid reference
await rc.KickClient(fooBar, 30);
await rc.KickClientAsync(fooBar, 30);
```

### Exceptions
Expand All @@ -100,16 +109,16 @@ If you want to work more loose-typed, you can do this. This is possible using th

```C#
var qc = new QueryClient(host, port);
await qc.Connect();
await qc.ConnectAsync();

await qc.Send("login", new Parameter("client_login_name", userName), new Parameter("client_login_password", password));
await qc.SendAsync("login", new Parameter("client_login_name", userName), new Parameter("client_login_password", password));

await qc.Send("use", new Parameter("sid", "1"));
await qc.SendAsync("use", new Parameter("sid", "1"));

var me = await qc.Send("whoami");
var me = await qc.SendAsync("whoami");

await qc.Send("servernotifyregister", new Parameter("event", "server"));
await qc.Send("servernotifyregister", new Parameter("event", "channel"), new Parameter("id", channelId));
await qc.SendAsync("servernotifyregister", new Parameter("event", "server"));
await qc.SendAsync("servernotifyregister", new Parameter("event", "channel"), new Parameter("id", channelId));

// and so on.
```
Expand Down
39 changes: 22 additions & 17 deletions src/TeamSpeak3QueryApi.Demo/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using TeamSpeak3QueryApi.Net.Specialized;
using TeamSpeak3QueryApi.Net.Specialized.Notifications;
using TeamSpeak3QueryApi.Net.Query.Enums;
using TeamSpeak3QueryApi.Net.Query.Notifications;

namespace TeamSpeak3QueryApi.Net.Demo
{
Expand All @@ -19,29 +19,34 @@ static async Task Main(string[] args)
var user = loginData[1].Trim();
var password = loginData[2].Trim();

var rc = new TeamSpeakClient(host);

await rc.Connect();
// Ssh connection
//var rc = new TeamSpeakClient(host, 10022, Protocol.SSH);
//rc.Connect(user, password);

await rc.Login(user, password);
await rc.UseServer(1);
// Telnet connection
var rc = new TeamSpeakClient(host);
await rc.ConnectAsync();
await rc.LoginAsync(user, password);

await rc.WhoAmI();
await rc.LoginAsync(user, password);
await rc.UseServerAsync(1);

await rc.RegisterServerNotification();
await rc.RegisterChannelNotification(30);
await rc.WhoAmIAsync();

var serverGroups = await rc.GetServerGroups();
var firstNormalGroup = serverGroups?.FirstOrDefault(s => s.ServerGroupType == ServerGroupType.NormalGroup);
var groupClients = await rc.GetServerGroupClientList(firstNormalGroup.Id);
await rc.RegisterServerNotificationAsync();
await rc.RegisterAllChannelNotificationAsync();

var serverGroups = await rc.GetServerGroupsAsync();
var firstNormalGroup = serverGroups?.FirstOrDefault(s => s.ServerGroupType == ServerGroupType.NormalGroup && s.Id != 46); // Id 46 is default Servergroup

var currentClients = await rc.GetClients();
var groupClients = await rc.GetServerGroupClientListAsync(firstNormalGroup.Id);
var currentClients = await rc.GetClientsAsync();

var fullClients = currentClients.Where(c => c.Type == ClientType.FullClient).ToList();
await rc.KickClient(fullClients, KickOrigin.Channel);
await rc.KickClientAsync(fullClients, KickOrigin.Channel, "You're kicked from channel");

// await rc.MoveClient(1, 1);
// await rc.KickClient(1, KickTarget.Server);
// await rc.MoveClientAsync(1, 1);
// await rc.KickClientAsync(1, KickTarget.Server);

rc.Subscribe<ClientEnterView>(data => data.ForEach(c => Debug.WriteLine($"Client {c.NickName} joined.")));
rc.Subscribe<ClientLeftView>(data => data.ForEach(c => Debug.WriteLine($"Client with id {c.Id} left (kicked/banned/left).")));
Expand Down
2 changes: 1 addition & 1 deletion src/TeamSpeak3QueryApi.Demo/TeamSpeak3QueryApi.Demo.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp1.1</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using TeamSpeak3QueryApi.Net.Enums;
using TeamSpeak3QueryApi.Net.Interfaces;
using TeamSpeak3QueryApi.Net.Query;
using TeamSpeak3QueryApi.Net.Query.Enums;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net
{
internal static class DataProxy
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Enums
{
internal enum NotificationEventTarget
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Enums
{
///<remarks>http://redeemer.biz/medien/artikel/ts3-query-notify/</remarks>
public enum NotificationType
Expand Down
12 changes: 12 additions & 0 deletions src/TeamSpeak3QueryApi/Enums/Protocol.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;

namespace TeamSpeak3QueryApi.Net.Enums
{
public enum Protocol
{
Telnet = 0,
SSH = 1
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Linq;
using System.Collections.Generic;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Extensions
{
internal static class EnumExtensions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System.Collections.Generic;

namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.Extensions
{
internal static class ListExtensions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.Extensions
{
internal static class StringExtensions
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using System.Threading;
using System.Threading.Tasks;

namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.Extensions
{
internal static class TaskExtensions
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Text;
using System.Threading.Tasks;

namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.FileTransfer
{
internal class FileTransferClient
{
Expand All @@ -20,43 +20,43 @@ public int GetFileTransferId()
return _currentFileTransferId++;
}

public async Task SendFile(byte[] data, int port, string key)
public async Task SendFileAsync(byte[] data, int port, string key)
{
using var client = new TcpClient();
await client.ConnectAsync(_host, port).ConfigureAwait(false);
using var ns = client.GetStream();

// Send key
// SendAsync key
var keyBytes = Encoding.ASCII.GetBytes(key);
await ns.WriteAsync(keyBytes, 0, keyBytes.Length).ConfigureAwait(false);
await ns.FlushAsync().ConfigureAwait(false);

// Send data
// SendAsync data
await ns.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
}

public async Task SendFile(Stream dataStream, int port, string key)
public async Task SendFileAsync(Stream dataStream, int port, string key)
{
using var client = new TcpClient();
await client.ConnectAsync(_host, port).ConfigureAwait(false);
using var ns = client.GetStream();

// Send key
// SendAsync key
var keyBytes = Encoding.ASCII.GetBytes(key);
await ns.WriteAsync(keyBytes, 0, keyBytes.Length).ConfigureAwait(false);
await ns.FlushAsync().ConfigureAwait(false);

// Send data
// SendAsync data
await dataStream.CopyToAsync(ns).ConfigureAwait(false);
}

public async Task<Stream> ReceiveFile(int size, int port, string key)
public async Task<Stream> ReceiveFileAsync(int size, int port, string key)
{
using var client = new TcpClient();
await client.ConnectAsync(_host, port).ConfigureAwait(false);
using var ns = client.GetStream();

// Send key
// SendAsync key
var keyBytes = Encoding.ASCII.GetBytes(key);
await ns.WriteAsync(keyBytes, 0, keyBytes.Length).ConfigureAwait(false);
await ns.FlushAsync().ConfigureAwait(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
using System.Collections.Generic;
using System.Text;

namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.FileTransfer
{
/// <summary>Represents errors that occur during file transfers.</summary>
[Serializable]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Interfaces
{
interface ITeamSpeakSerializable
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using TeamSpeak3QueryApi.Net.Extensions;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Interfaces
{
interface ITypeCaster
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum ClientType
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
[Flags]
public enum GetChannelOptions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
[Flags]
public enum GetClientOptions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using System;

namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
[Flags]
public enum GetServerOptions
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum KickOrigin
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum HostMessageMode
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum MessageTarget
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum ReasonId
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized
namespace TeamSpeak3QueryApi.Net.Query.Enums
{
public enum ServerGroupType
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using TeamSpeak3QueryApi.Net.Query.Enums;

namespace TeamSpeak3QueryApi.Net.Specialized.Notifications
namespace TeamSpeak3QueryApi.Net.Query.Notifications
{
public class ChannelCreated : InvokerInformation
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized.Notifications
namespace TeamSpeak3QueryApi.Net.Query.Notifications
{
public class ChannelDeleted : InvokerInformation
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace TeamSpeak3QueryApi.Net.Specialized.Notifications
namespace TeamSpeak3QueryApi.Net.Query.Notifications
{
public class ChannelDescriptionChanged : Notification
{
Expand Down
Loading