Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
aka Multi-Instance!
  • Loading branch information
Splamy committed Feb 22, 2018
2 parents cdc3ee3 + 25b19d7 commit 6162089
Show file tree
Hide file tree
Showing 166 changed files with 10,845 additions and 9,124 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "TS3Client/Declarations"]
path = TS3Client/Declarations
url = https://github.com/ReSpeak/tsdeclarations
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ after_success:
- export MAIN_DIR=`pwd`
- cd ./TS3AudioBot/bin/Release
- ls
- zip TS3AudioBot.zip TS3AudioBot.exe TS3Client.dll Nett.dll LiteDB.dll Heijden.Dns.dll BouncyCastle.Crypto.dll x64/* x86/*
- zip TS3AudioBot.zip NLog.config *.exe *.dll x64/* x86/*
- 'export version=`mono TS3AudioBot.exe --version | grep "Version: "`'
- "curl -I -H \"Content-Type: application/zip\" -X PUT \"https://splamy.de/api/nightly/ts3ab/${TRAVIS_BRANCH}?token=${uploadkey}&filename=TS3AudioBot.zip&commit=${TRAVIS_COMMIT}&version=${version:9}\" --upload-file ./TS3AudioBot.zip"
- cd "$MAIN_DIR"
Expand Down
21 changes: 13 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,17 @@ Done:
* (un)subscribe to the Bob to hear music in any channel
* (un)subscribe the Bob to certain channels
* Playlist management for all users
* *broken* | Basic plugin support

In progress:
* Advanced permission configuration
* Extensive plugin support
* Web API

In planning:
* Create multiple client instances automatically for different channels
* (Improved) Rights system
In progress:
* Own web-interface
* (Improved) Rights system
* Multi-instance

In planning:
*See issues*

## Bot Commands
All in all, the bot is fully operable only via chat (and actually only via chat).
Expand All @@ -61,7 +63,7 @@ You can add a [youtube-dl](https://github.com/rg3/youtube-dl/) binary or source
### Compilation
Before we start: _If you know what you are doing_ you can alternatively compile each dependency referenced here from source/git by yourself, but I won't add a tutorial for that.

Download the git repository with `git clone https://github.com/Splamy/TS3AudioBot.git`.
Download the git repository with `git clone --recurse-submodules https://github.com/Splamy/TS3AudioBot.git`.

#### Linux
1. See if you have NuGet by just executing `nuget`. If not, get `NuGet.exe` with `wget https://dist.nuget.org/win-x86-commandline/latest/nuget.exe`
Expand Down Expand Up @@ -95,7 +97,7 @@ or dive into the Rights syntax [here](https://github.com/Splamy/TS3AudioBot/wiki
1. Start the bot again.
1. Send the bot in a private message `!bot setup <key>` where `<key>` is the privilege key from a previous step.
1. Now you can move the process to the background or close the bot with `!quit` in teamspeak and run it in the background.
The recommended start from now on is `mono TS3AudioBot.exe -q` to disable writing to stdout since the bot logs everything to a log file anyway.
1. (optional) You can configure the logging levels and outputs in the `NLog.config` file, read [here](https://github.com/NLog/NLog/wiki/Configuration-file) to learn more.
1. Congratz, you're done! Enjoy listening to your favourite music, experimenting with the crazy command system or do whatever you whish to do ;).
For further reading check out the [CommandSystem](https://github.com/Splamy/TS3AudioBot/wiki/CommandSystem)

Expand All @@ -109,3 +111,6 @@ Why OSL-3.0:
- OSL allows you to link to our libraries without needing to disclose your own project, which might be useful if you want to use the TS3Client as a library.
- If you create plugins you do not have to make them public like in GPL. (Although we would be happier if you shared them :)
- With OSL we want to allow you providing the TS3AB as a service (even commercially). We do not want the software to be sold but the service. We want this software to be free for everyone.

# Badges
[![forthebadge](http://forthebadge.com/images/badges/60-percent-of-the-time-works-every-time.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/built-by-developers.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/built-with-love.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/contains-cat-gifs.svg)](http://forthebadge.com) [![forthebadge](http://forthebadge.com/images/badges/made-with-c-sharp.svg)](http://forthebadge.com)
24 changes: 16 additions & 8 deletions TS3ABotUnitTests/BotCommandTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,21 +24,18 @@ namespace TS3ABotUnitTests
[TestFixture]
public class BotCommandTests
{
private readonly MainBot bot;
private readonly CommandManager cmdMgr;

public BotCommandTests()
{
bot = new MainBot();
var prop = typeof(MainBot).GetProperty(nameof(MainBot.CommandManager));
if (prop != null)
prop.SetValue(bot, new CommandManager());
bot.CommandManager.RegisterMain(bot);
cmdMgr = new CommandManager();
cmdMgr.RegisterMain();
Utils.ExecInfo.AddDynamicObject(cmdMgr);
}

private string CallCommand(string command)
{
var info = new ExecutionInformation(null, new InvokerData("InvokerUid"), null) { SkipRightsChecks = true };
return bot.CommandManager.CommandSystem.ExecuteCommand(info, command);
return cmdMgr.CommandSystem.ExecuteCommand(Utils.ExecInfo, command);
}

[Test]
Expand Down Expand Up @@ -92,4 +89,15 @@ public void BotCommandTest()
Assert.Throws<CommandException>(() => CallCommand("!if a == b text (!)"));
}
}

static class Utils
{
static Utils()
{
ExecInfo = new ExecutionInformation();
ExecInfo.AddDynamicObject(new CallerInfo(new InvokerData("InvokerUid"), null) { SkipRightsChecks = true });
}

public static ExecutionInformation ExecInfo { get; }
}
}
188 changes: 77 additions & 111 deletions TS3ABotUnitTests/UnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,22 @@ public void HistoryFileIntergrityTest()
var data2 = new HistorySaveData(ar2, inv2.DatabaseId);
var data3 = new HistorySaveData(ar3, 103);

var hmf = new HistoryManagerData {HistoryFile = testFile, FillDeletedIds = false};
var db = new DbStore(hmf);
var hf = new HistoryManager(hmf, db);
var memcfg = ConfigFile.CreateDummy();
var hmf = memcfg.GetDataStruct<HistoryManagerData>("HistoryManager", true);
hmf.HistoryFile = testFile;
hmf.FillDeletedIds = false;

DbStore db;
HistoryManager hf;

void CreateDbStore()
{
db = new DbStore(hmf);
hf = new HistoryManager(hmf) { Database = db };
hf.Initialize();
}

CreateDbStore();

hf.LogAudioResource(data1);

Expand All @@ -71,8 +84,7 @@ public void HistoryFileIntergrityTest()

db.Dispose();

db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
lastXEntries = hf.GetLastXEntrys(1);
Assert.True(lastXEntries.Any());
lastEntry = lastXEntries.First();
Expand All @@ -89,8 +101,7 @@ public void HistoryFileIntergrityTest()
db.Dispose();

// store and order check
db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
var lastXEntriesArray = hf.GetLastXEntrys(2).ToArray();
Assert.AreEqual(2, lastXEntriesArray.Length);
Assert.AreEqual(ar2, lastXEntriesArray[0].AudioResource);
Expand All @@ -104,8 +115,7 @@ public void HistoryFileIntergrityTest()
db.Dispose();

// check entry renaming
db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
lastXEntriesArray = hf.GetLastXEntrys(2).ToArray();
Assert.AreEqual(2, lastXEntriesArray.Length);
Assert.AreEqual(ar1, lastXEntriesArray[0].AudioResource);
Expand All @@ -125,17 +135,15 @@ public void HistoryFileIntergrityTest()
db.Dispose();

// recheck order
db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
lastXEntriesArray = hf.GetLastXEntrys(2).ToArray();
Assert.AreEqual(2, lastXEntriesArray.Length);
Assert.AreEqual(ar2, lastXEntriesArray[0].AudioResource);
Assert.AreEqual(ar1, lastXEntriesArray[1].AudioResource);
db.Dispose();

// delete entry 1
db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
hf.RemoveEntry(hf.FindEntryByResource(ar1));

lastXEntriesArray = hf.GetLastXEntrys(3).ToArray();
Expand All @@ -149,8 +157,7 @@ public void HistoryFileIntergrityTest()
db.Dispose();

// delete entry 2
db = new DbStore(hmf);
hf = new HistoryManager(hmf, db);
CreateDbStore();
// .. check integrity from previous store
lastXEntriesArray = hf.GetLastXEntrys(3).ToArray();
Assert.AreEqual(2, lastXEntriesArray.Length);
Expand All @@ -167,81 +174,6 @@ public void HistoryFileIntergrityTest()
File.Delete(testFile);
}

[Test]
public void PositionedStreamReaderLineEndings()
{
using (var memStream = new MemoryStream())
{
// Setting streams up
var writer = new StreamWriter(memStream);
string[] values = {
"11\n",
"22\n",
"33\n",
"44\r",
"55\r",
"66\r",
"77\r\n",
"88\r\n",
"99\r\n",
"xx\n","\r",
"yy\n","\r",
"zz\n","\r",
"a\r",
"b\n",
"c\r\n",
"d\n","\r",
"e" };
foreach (var val in values)
writer.Write(val);
writer.Flush();

memStream.Seek(0, SeekOrigin.Begin);
var reader = new PositionedStreamReader(memStream);

int pos = 0;
foreach (var val in values)
{
var line = reader.ReadLine();
pos += val.Length;

Assert.AreEqual(val.TrimEnd('\r', '\n'), line);
Assert.AreEqual(pos, reader.ReadPosition);
}
}
}

[Test]
public void PositionedStreamReaderBufferSize()
{
using (var memStream = new MemoryStream())
{
// Setting streams up
var writer = new StreamWriter(memStream);
string[] values = {
new string('1', 1024) + '\n', // 1025: 1 over buffer size
new string('1', 1023) + '\n', // 1024: exactly the buffer size, but 1 over the 1024 line block due to the previous
new string('1', 1022) + '\n', // 1023: 1 less then the buffer size, should now match the line block again
new string('1', 1024) };
foreach (var val in values)
writer.Write(val);
writer.Flush();

memStream.Seek(0, SeekOrigin.Begin);
var reader = new PositionedStreamReader(memStream);

int pos = 0;
foreach (var val in values)
{
var line = reader.ReadLine();
pos += val.Length;

Assert.AreEqual(val.TrimEnd('\r', '\n'), line);
Assert.AreEqual(pos, reader.ReadPosition);
}
}
}

[Test]
public void UtilSeedTest()
{
Expand Down Expand Up @@ -310,26 +242,26 @@ public void XCommandSystemTest()
group.AddCommand("one", new FunctionCommand(() => "ONE"));
group.AddCommand("two", new FunctionCommand(() => "TWO"));
group.AddCommand("echo", new FunctionCommand(s => s));
group.AddCommand("optional", new FunctionCommand(new Func<string, string>(s => s == null ? "NULL" : "NOT NULL")).SetRequiredParameters(0));
group.AddCommand("optional", new FunctionCommand(new Func<string, string>(s => s == null ? "NULL" : "NOT NULL"), 0));

// Basic tests
Assert.AreEqual("ONE", ((StringCommandResult)commandSystem.Execute(ExecutionInformation.Debug,
Assert.AreEqual("ONE", ((StringCommandResult)commandSystem.Execute(Utils.ExecInfo,
new ICommand[] { new StringCommand("one") })).Content);
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!one"));
Assert.AreEqual("TWO", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!t"));
Assert.AreEqual("TEST", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!e TEST"));
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!o"));
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(Utils.ExecInfo, "!one"));
Assert.AreEqual("TWO", commandSystem.ExecuteCommand(Utils.ExecInfo, "!t"));
Assert.AreEqual("TEST", commandSystem.ExecuteCommand(Utils.ExecInfo, "!e TEST"));
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(Utils.ExecInfo, "!o"));

// Optional parameters
Assert.Throws<CommandException>(() => commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!e"));
Assert.AreEqual("NULL", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!op"));
Assert.AreEqual("NOT NULL", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!op 1"));
Assert.Throws<CommandException>(() => commandSystem.ExecuteCommand(Utils.ExecInfo, "!e"));
Assert.AreEqual("NULL", commandSystem.ExecuteCommand(Utils.ExecInfo, "!op"));
Assert.AreEqual("NOT NULL", commandSystem.ExecuteCommand(Utils.ExecInfo, "!op 1"));

// Command chaining
Assert.AreEqual("TEST", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!e (!e TEST)"));
Assert.AreEqual("TWO", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!e (!t)"));
Assert.AreEqual("NOT NULL", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!op (!e TEST)"));
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!(!e on)"));
Assert.AreEqual("TEST", commandSystem.ExecuteCommand(Utils.ExecInfo, "!e (!e TEST)"));
Assert.AreEqual("TWO", commandSystem.ExecuteCommand(Utils.ExecInfo, "!e (!t)"));
Assert.AreEqual("NOT NULL", commandSystem.ExecuteCommand(Utils.ExecInfo, "!op (!e TEST)"));
Assert.AreEqual("ONE", commandSystem.ExecuteCommand(Utils.ExecInfo, "!(!e on)"));

// Command overloading
var intCom = new Func<int, string>(i => "INT");
Expand All @@ -339,9 +271,9 @@ public void XCommandSystemTest()
new FunctionCommand(strCom.Method, strCom.Target)
}));

Assert.AreEqual("INT", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!overlord 1"));
Assert.AreEqual("STRING", commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!overlord a"));
Assert.Throws<CommandException>(() => commandSystem.ExecuteCommand(ExecutionInformation.Debug, "!overlord"));
Assert.AreEqual("INT", commandSystem.ExecuteCommand(Utils.ExecInfo, "!overlord 1"));
Assert.AreEqual("STRING", commandSystem.ExecuteCommand(Utils.ExecInfo, "!overlord a"));
Assert.Throws<CommandException>(() => commandSystem.ExecuteCommand(Utils.ExecInfo, "!overlord"));
}

[Test]
Expand Down Expand Up @@ -399,12 +331,11 @@ public void Factory_YoutubeFactoryTest()
[Test]
public void Ts3Client_RingQueueTest()
{
int ov;
var q = new RingQueue<int>(3, 5);

q.Set(0, 42);

Assert.True(q.TryPeekStart(0, out ov));
Assert.True(q.TryPeekStart(0, out int ov));
Assert.AreEqual(ov, 42);

q.Set(1, 43);
Expand Down Expand Up @@ -465,11 +396,12 @@ public void Ts3Client_RingQueueTest()
public void Ts3Client_RingQueueTest2()
{
var q = new RingQueue<int>(50, ushort.MaxValue + 1);

for (int i = 0; i < ushort.MaxValue - 10; i++)
{
q.Set(i, 42);
q.TryDequeue(out var _);
q.Set(i, i);
Assert.True(q.TryDequeue(out var iCheck));
Assert.AreEqual(iCheck, i);
}

var setStatus = q.IsSet(ushort.MaxValue - 20);
Expand All @@ -480,6 +412,40 @@ public void Ts3Client_RingQueueTest2()
q.Set(i % (ushort.MaxValue + 1), 42);
}
}

[Test]
public void Ts3Client_RingQueueTest3()
{
var q = new RingQueue<int>(100, ushort.MaxValue + 1);

int iSet = 0;
for (int blockSize = 1; blockSize < 100; blockSize++)
{
for (int i = 0; i < blockSize; i++)
{
q.Set(iSet++, i);
}
for (int i = 0; i < blockSize; i++)
{
Assert.True(q.TryDequeue(out var iCheck));
Assert.AreEqual(i, iCheck);
}
}

for (int blockSize = 1; blockSize < 100; blockSize++)
{
q = new RingQueue<int>(100, ushort.MaxValue + 1);
for (int i = 0; i < blockSize; i++)
{
q.Set(i, i);
}
for (int i = 0; i < blockSize; i++)
{
Assert.True(q.TryDequeue(out var iCheck));
Assert.AreEqual(i, iCheck);
}
}
}
}

static class Extensions
Expand Down
Loading

0 comments on commit 6162089

Please sign in to comment.