Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 25 additions & 16 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!
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The library still only requires .NET Standard 1.3

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR contains changes that were merged to the ssh branch. Only the latest commits are relevant.


### NuGet
*This is currently not possible.*
```Shell
Install-Package TeamSpeak3QueryApi
# or
Expand All @@ -39,11 +41,18 @@ 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.UseServer(1); // Use the server with id '1'
await rc.ConnectAsync(); // connect to the server
await rc.LoginAsync(user, password); // login to do some stuff that requires permission
await rc.UseServerAsync(1); // Use the server with id '1'
var me = await rc.WhoAmIAsync(); // Get information about yourself!
```

```C# SSH query
var rc = new TeamSpeakClient(host, 10022, Protocol.SSH); // Create rich client instance
rc.Connect(user, password); // connect to the server with login data
await rc.UseServerAsync(1); // Use the server with id '1'
var me = await rc.WhoAmI(); // Get information about yourself!
```

Expand All @@ -52,10 +61,10 @@ You can receive notifications. The notification data is fully typed, so you can

```C#
// assuming connected
await rc.RegisterServerNotification(); // register notifications to receive server notifications
await rc.RegisterServerNotificationAsync(); // register notifications to receive server notifications

// register channel notifications to receive notifications for channel with id '30'
await rc.RegisterChannelNotification(30);
await rc.RegisterChannelNotificationAsync(30);

//Subscribe a callback to a notification:
rc.Subscribe<ClientEnterView>(data => {
Expand All @@ -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 All @@ -13,5 +13,6 @@ public enum GetClientOptions
Info = 1 << 5,
Icon = 1 << 6,
Country = 1 << 7,
Ip = 1 << 8
}
}
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
Loading