Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
Splamy committed Apr 2, 2021
2 parents 4f17b29 + a9337cc commit 768c186
Show file tree
Hide file tree
Showing 282 changed files with 12,665 additions and 12,101 deletions.
51 changes: 51 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,63 @@ insert_final_newline = true
charset = utf-8

[*.cs]
# General Formatting
indent_style = tab
indent_size = tab
tab_width = 4
trim_trailing_whitespace = true

#### .NET Coding Conventions ####

# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false

# this. and Me. preferences
dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:silent

# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true
# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = true:suggestion

# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_methods = true:silent
csharp_style_expression_bodied_properties = true:silent

# Expression-level preferences
csharp_style_inlined_variable_declaration = true:suggestion

# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:suggestion

#### C# Formatting Rules ####

# Indentation preferences
csharp_indent_switch_labels = false

# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_parameter_list_parentheses = false

# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true

[*.{tt,ttinclude}]
insert_final_newline = false
8 changes: 0 additions & 8 deletions Directory.Build.targets

This file was deleted.

9 changes: 2 additions & 7 deletions GitVersion.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,14 @@ branches:
tag: ''
increment: Patch
prevent-increment-of-merged-branch-version: true
track-merge-target: false
regex: ^master$
tracks-release-branches: false
is-release-branch: false
is-mainline: true
develop:
mode: ContinuousDeployment
tag: alpha
increment: Minor
prevent-increment-of-merged-branch-version: false
track-merge-target: true
prevent-increment-of-merged-branch-version: true
regex: ^develop$
tracks-release-branches: true
is-release-branch: false
ignore:
sha: []
merge-message-formats: {}
31 changes: 20 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,14 @@ For an in-depth command tutorial see [here in the wiki](https://github.com/Splam

### Download
Download either one of the latest builds from our [nightly server](https://splamy.de/Nightly#ts3ab):
- [![Download](https://img.shields.io/badge/Download-master-green.svg)](https://splamy.de/api/nightly/ts3ab/master_dotnet_core/download)
- [![Download](https://img.shields.io/badge/Download-master-green.svg)](https://splamy.de/api/nightly/ts3ab/master_dotnet_core_3_1_preview/download)
Versions are mostly considered stable but won't get bigger features as fast.
- [![Download](https://img.shields.io/badge/Download-develop-green.svg)](https://splamy.de/api/nightly/ts3ab/develop_dotnet_core/download)
- [![Download](https://img.shields.io/badge/Download-develop-green.svg)](https://splamy.de/api/nightly/ts3ab/develop/download)
Will always have the latest and greatest but might not be fully stable or have broken features.
- [Docker](https://github.com/getdrunkonmovies-com/TS3AudioBot_docker) (NOTE: This build is community-maintained. It comes with all dependencies as well as youtube-dl preconfigured)
- [![Docker](https://img.shields.io/badge/Docker-0.11.0-0db7ed.svg)](https://github.com/getdrunkonmovies-com/TS3AudioBot_docker) (NOTE: This build is community-maintained. It comes with all dependencies as well as youtube-dl preconfigured)

#### Linux
1. dotnet core: Get the latest `dotnet core 2.2` version by following [this tutorial](https://dotnet.microsoft.com/download/linux-package-manager/ubuntu16-04/sdk-current) and follow the steps after choosing your platform
1. dotnet core: Get the latest `dotnet core 3.1` version by following [this tutorial](https://dotnet.microsoft.com/download/linux-package-manager/ubuntu16-04/sdk-current) and follow the steps after choosing your platform
1. Other dependencies:
* on **Ubuntu**/**Debian**:
Run `sudo apt-get install libopus-dev ffmpeg`
Expand All @@ -66,12 +66,12 @@ Run
1. Make sure you have a C compiler installed
1. Make the Opus script runnable with `chmod u+x InstallOpus.sh` and run it with `./InstallOpus.sh`
1. Get the ffmpeg [32bit](https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-i686-static.tar.xz) or [64bit](https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-amd64-static.tar.xz) binary.
1. Extract the ffmpeg archive with `tar -vxf ffmpeg-git-XXbit-static.tar.xz`
1. Get the ffmpeg binary from `ffmpeg-git-*DATE*-amd64-static/ffmpeg` and copy it to `TS3AudioBot/bin/Release/netcoreapp2.2`
1. Extract the ffmpeg archive with `tar -vxf ffmpeg-git-*XXbit*-static.tar.xz`
1. Get the ffmpeg binary from `ffmpeg-git-*DATE*-amd64-static/ffmpeg` and copy it to `TS3AudioBot/bin/Release/netcoreapp3.1`

#### Windows
1. Get the ffmpeg [32bit](https://ffmpeg.zeranoe.com/builds/win32/static/ffmpeg-latest-win32-static.zip) or [64bit](https://ffmpeg.zeranoe.com/builds/win64/static/ffmpeg-latest-win64-static.zip) binary.
1. Open the archive and copy the ffmpeg binary from `ffmpeg-latest-winXX-static/bin/ffmpeg.exe` to `TS3AudioBot/bin/Release/netcoreapp2.2`
1. Open the archive and copy the ffmpeg binary from `ffmpeg-latest-winXX-static/bin/ffmpeg.exe` to `TS3AudioBot/bin/Release/netcoreapp3.1`

### Optional Dependencies
If the bot can't play some youtube videos it might be due to some embedding restrictions which are blocking this.
Expand Down Expand Up @@ -99,15 +99,24 @@ For further reading check out the [CommandSystem](https://github.com/Splamy/TS3A
Download the git repository with `git clone --recurse-submodules https://github.com/Splamy/TS3AudioBot.git`.

#### Linux
1. Get the latest `dotnet core 2.2` version by following [this tutorial](https://dotnet.microsoft.com/download/linux-package-manager/ubuntu16-04/sdk-current) and choose your platform
1. Get the latest `dotnet core 3.1` version by following [this tutorial](https://docs.microsoft.com/dotnet/core/install/linux-package-managers) and choose your platform
1. Go into the directory of the repository with `cd TS3AudioBot`
1. Execute `dotnet build --framework netcoreapp2.2 --configuration Release TS3AudioBot` to build the AudioBot
1. The binary will be in `./TS3AudioBot/bin/Release/netcoreapp2.2` and can be run with `dotnet TS3AudioBot.dll`
1. Execute `dotnet build --framework netcoreapp3.1 --configuration Release TS3AudioBot` to build the AudioBot
1. The binary will be in `./TS3AudioBot/bin/Release/netcoreapp3.1` and can be run with `dotnet TS3AudioBot.dll`

#### Windows
1. Make sure you have installed `Visual Studio` with `.NET Framework 4.7.2` and the latest `dotnet core 2.2` or higher
1. Make sure you have `Visual Studio` with the `dotnet core 3.1` development toolchain installed
1. Build the AudioBot with Visual Studio.

### Building the WebInterface
1. Go with the console of your choice into the `./WebInterface` folder
1. Run `npm install` to restore or update all dependencies for this project
1. Run `npm run build` to build the project.
The built project will be in `./WebInterface/dist`.
Make sure to the set the webinterface path in the ts3audiobot.toml to this folder.
1. You can alternatively use `npm run start` for development.
This will use the webpack dev server with live reload instead of the ts3ab server.

## Community

### Localization
Expand Down
116 changes: 59 additions & 57 deletions TS3ABotUnitTests/BotCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
using TS3AudioBot.Algorithm;
using TS3AudioBot.CommandSystem;
using TS3AudioBot.CommandSystem.Ast;
using TS3AudioBot.CommandSystem.CommandResults;
using TS3AudioBot.CommandSystem.Commands;
using TS3AudioBot.Dependency;
using TS3AudioBot.Web.Api;
using TSLib;

#nullable enable
namespace TS3ABotUnitTests
{
[TestFixture]
Expand All @@ -23,23 +24,17 @@ public class BotCommandTests
public void BotCommandTest()
{
var execInfo = Utils.GetExecInfo("ic3");
string CallCommand(string command)
{
return CommandManager.ExecuteCommand(execInfo, command);
}
string? CallCommand(string command) => CommandManager.Execute(execInfo, command).GetAwaiter().GetResult().AsString();

var output = CallCommand("!help");
Assert.AreEqual(output, CallCommand("!h"));
Assert.AreEqual(output, CallCommand("!eval !h"));
Assert.AreEqual(output, CallCommand("!(!h)"));
output = CallCommand("!h help");
Assert.AreEqual(output, CallCommand("!(!h) help"));
Assert.Throws<CommandException>(() => CallCommand("!"));

// Test random
for (int i = 0; i < 1000; i++)
{
var r = int.Parse(CallCommand("!rng -10 100"));
var r = int.Parse(CallCommand("!rng -10 100")!);
Assert.GreaterOrEqual(r, -10);
Assert.Less(r, 100);
}
Expand Down Expand Up @@ -80,12 +75,9 @@ string CallCommand(string command)
public void TailStringTest()
{
var execInfo = Utils.GetExecInfo("ic3");
var group = execInfo.GetModule<CommandManager>().RootGroup;
string? CallCommand(string command) => CommandManager.Execute(execInfo, command).Result.AsString();
var group = execInfo.GetModule<CommandManager>()!.RootGroup;
group.AddCommand("cmd", new FunctionCommand(s => s));
string CallCommand(string command)
{
return CommandManager.ExecuteCommand(execInfo, command);
}

Assert.AreEqual("a", CallCommand("!cmd a"));
Assert.AreEqual("a b", CallCommand("!cmd a b"));
Expand All @@ -96,15 +88,15 @@ string CallCommand(string command)
[Test]
public void XCommandSystemFilterTest()
{
var filterList = new Dictionary<string, object>
var filterList = new Dictionary<string, object?>
{
{ "help", null },
{ "quit", null },
{ "play", null },
{ "ply", null }
};

var filter = Filter.GetFilterByName("ic3");
var filter = Filter.GetFilterByName("ic3")!;

// Exact match
var result = filter.Filter(filterList, "help");
Expand Down Expand Up @@ -140,35 +132,37 @@ public void XCommandSystemFilterTest()
Assert.IsTrue(result.Any(r => r.Key == "pla"));
}

private static string OptionalFunc(string s = null) => s is null ? "NULL" : "NOT NULL";
private static string OptionalFunc(string? s = null) => s is null ? "NULL" : "NOT NULL";

[Test]
public void XCommandSystemTest()
{
var execInfo = Utils.GetExecInfo("ic3", false);
var group = execInfo.GetModule<CommandManager>().RootGroup;
string? CallCommand(string command) => CommandManager.Execute(execInfo, command).GetAwaiter().GetResult().AsString();

var group = execInfo.GetModule<CommandManager>()!.RootGroup;
group.AddCommand("one", new FunctionCommand(() => "ONE"));
group.AddCommand("two", new FunctionCommand(() => "TWO"));
group.AddCommand("echo", new FunctionCommand(s => s));
group.AddCommand("optional", new FunctionCommand(GetType().GetMethod(nameof(OptionalFunc), BindingFlags.NonPublic | BindingFlags.Static)));
group.AddCommand("optional", new FunctionCommand(GetType().GetMethod(nameof(OptionalFunc), BindingFlags.NonPublic | BindingFlags.Static)!));

// Basic tests
Assert.AreEqual("ONE", CommandManager.ExecuteCommand(execInfo, new ICommand[] { new ResultCommand(new PrimitiveResult<string>("one")) }));
Assert.AreEqual("ONE", CommandManager.ExecuteCommand(execInfo, "!one"));
Assert.AreEqual("TWO", CommandManager.ExecuteCommand(execInfo, "!t"));
Assert.AreEqual("TEST", CommandManager.ExecuteCommand(execInfo, "!e TEST"));
Assert.AreEqual("ONE", CommandManager.ExecuteCommand(execInfo, "!o"));
Assert.AreEqual("ONE", CommandManager.Execute(execInfo, new ICommand[] { new ResultCommand("one") }).Result.AsString());
Assert.AreEqual("ONE", CallCommand("!one"));
Assert.AreEqual("TWO", CallCommand("!t"));
Assert.AreEqual("TEST", CallCommand("!e TEST"));
Assert.AreEqual("ONE", CallCommand("!o"));

// Optional parameters
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!e"));
Assert.AreEqual("NULL", CommandManager.ExecuteCommand(execInfo, "!op"));
Assert.AreEqual("NOT NULL", CommandManager.ExecuteCommand(execInfo, "!op 1"));
Assert.Throws<CommandException>(() => CallCommand("!e"));
Assert.AreEqual("NULL", CallCommand("!op"));
Assert.AreEqual("NOT NULL", CallCommand("!op 1"));

// Command chaining
Assert.AreEqual("TEST", CommandManager.ExecuteCommand(execInfo, "!e (!e TEST)"));
Assert.AreEqual("TWO", CommandManager.ExecuteCommand(execInfo, "!e (!t)"));
Assert.AreEqual("NOT NULL", CommandManager.ExecuteCommand(execInfo, "!op (!e TEST)"));
Assert.AreEqual("ONE", CommandManager.ExecuteCommand(execInfo, "!(!e on)"));
Assert.AreEqual("TEST", CallCommand("!e (!e TEST)"));
Assert.AreEqual("TWO", CallCommand("!e (!t)"));
Assert.AreEqual("NOT NULL", CallCommand("!op (!e TEST)"));
Assert.AreEqual("ONE", CallCommand("!(!e on)"));

// Command overloading
var intCom = new Func<int, string>(_ => "INT");
Expand All @@ -178,16 +172,24 @@ public void XCommandSystemTest()
new FunctionCommand(strCom.Method, strCom.Target)
}));

Assert.AreEqual("INT", CommandManager.ExecuteCommand(execInfo, "!overlord 1"));
Assert.AreEqual("STRING", CommandManager.ExecuteCommand(execInfo, "!overlord a"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!overlord"));
Assert.AreEqual("INT", CallCommand("!overlord 1"));
Assert.AreEqual("STRING", CallCommand("!overlord a"));
Assert.Throws<CommandException>(() => CallCommand("!overlord"));

// Return unwrap
var json = JsonValue.Create("WRAP");
group.AddCommand("wrapjson", new FunctionCommand(new Func<JsonValue>(() => json)));
Assert.AreEqual(json, CommandManager.Execute(execInfo, "!wrapjson").Result.AsRaw());
Assert.AreEqual("WRAP", CallCommand("!wrapjson")); // AsString()
Assert.AreEqual("WRAP", CallCommand("!echo (!wrapjson)"));
}

[Test]
public void XCommandSystemTest2()
{
var execInfo = Utils.GetExecInfo("exact");
var group = execInfo.GetModule<CommandManager>().RootGroup;
string? CallCommand(string command) => CommandManager.Execute(execInfo!, command).GetAwaiter().GetResult().AsString();
var group = execInfo.GetModule<CommandManager>()!.RootGroup;

var o1 = new OverloadedFunctionCommand();
o1.AddCommand(new FunctionCommand(new Action<int>((_) => { })));
Expand All @@ -201,25 +203,25 @@ public void XCommandSystemTest2()
o2.AddCommand("b", new FunctionCommand(new Action(() => { })));
group.AddCommand("three", o2);

Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!one"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!one \"\""));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!one (!print \"\")"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!one string"));
Assert.DoesNotThrow(() => CommandManager.ExecuteCommand(execInfo, "!one 42"));
Assert.DoesNotThrow(() => CommandManager.ExecuteCommand(execInfo, "!one 4200000000000"));

Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!two"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!two \"\""));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!two (!print \"\")"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!two 42"));
Assert.DoesNotThrow(() => CommandManager.ExecuteCommand(execInfo, "!two None"));

Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!three"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!three \"\""));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!three (!print \"\")"));
Assert.Throws<CommandException>(() => CommandManager.ExecuteCommand(execInfo, "!three c"));
Assert.DoesNotThrow(() => CommandManager.ExecuteCommand(execInfo, "!three a"));
Assert.DoesNotThrow(() => CommandManager.ExecuteCommand(execInfo, "!three b"));
Assert.Throws<CommandException>(() => CallCommand("!one"));
Assert.Throws<CommandException>(() => CallCommand("!one \"\""));
Assert.Throws<CommandException>(() => CallCommand("!one (!print \"\")"));
Assert.Throws<CommandException>(() => CallCommand("!one string"));
Assert.DoesNotThrow(() => CallCommand("!one 42"));
Assert.DoesNotThrow(() => CallCommand("!one 4200000000000"));

Assert.Throws<CommandException>(() => CallCommand("!two"));
Assert.Throws<CommandException>(() => CallCommand("!two \"\""));
Assert.Throws<CommandException>(() => CallCommand("!two (!print \"\")"));
Assert.Throws<CommandException>(() => CallCommand("!two 42"));
Assert.DoesNotThrow(() => CallCommand("!two None"));

Assert.Throws<CommandException>(() => CallCommand("!three"));
Assert.Throws<CommandException>(() => CallCommand("!three \"\""));
Assert.Throws<CommandException>(() => CallCommand("!three (!print \"\")"));
Assert.Throws<CommandException>(() => CallCommand("!three c"));
Assert.DoesNotThrow(() => CallCommand("!three a"));
Assert.DoesNotThrow(() => CallCommand("!three b"));
}

[Test]
Expand All @@ -229,7 +231,7 @@ public void EnsureAllCommandsHaveEnglishDocumentationEntry()
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en");

var execInfo = Utils.GetExecInfo("exact");
var cmdMgr = execInfo.GetModule<CommandManager>();
var cmdMgr = execInfo.GetModule<CommandManager>()!;
var errors = new List<string>();
foreach (var cmd in cmdMgr.AllCommands)
{
Expand Down Expand Up @@ -274,14 +276,14 @@ internal static class Utils
{
public static ExecutionInformation GetExecInfo(string matcher, bool addMainCommands = true)
{
var cmdMgr = new CommandManager(null);
var cmdMgr = new CommandManager(null!);
if (addMainCommands)
cmdMgr.RegisterCollection(MainCommands.Bag);

var execInfo = new ExecutionInformation();
execInfo.AddModule(new CallerInfo(false) { SkipRightsChecks = true, CommandComplexityMax = int.MaxValue });
execInfo.AddModule(new InvokerData((Uid)"InvokerUid"));
execInfo.AddModule(Filter.GetFilterByName(matcher));
execInfo.AddModule(Filter.GetFilterByName(matcher) ?? throw new Exception("Test filter not found"));
execInfo.AddModule(cmdMgr);
return execInfo;
}
Expand Down
Loading

0 comments on commit 768c186

Please sign in to comment.