├── .editorconfig ├── .gitattributes ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── feature_request.md │ └── setup_help.md ├── .gitignore ├── .gitmodules ├── GitVersion.yml ├── InstallOpus.sh ├── LICENSE ├── LICENSE_COMPLETE ├── README.md ├── TS3ABotUnitTests ├── BotCommandTests.cs ├── ColorGeneratorTests.cs ├── HistoryTests.cs ├── M3uParserTests.cs ├── ResourceFactoriesTests.cs ├── RingQueueTest.cs ├── ShuffleTests.cs ├── TS3ABotUnitTests.csproj ├── TS3MessageParserTests.cs ├── TextSplitterTests.cs └── UtilsTests.cs ├── TS3AudioBot.sln ├── TS3AudioBot ├── Algorithm │ ├── IFilterAlgorithm.cs │ ├── LruCache.cs │ └── TimedCache.cs ├── Audio │ ├── AudioValues.cs │ ├── CustomTargetPipe.cs │ ├── FfmpegProducer.cs │ ├── IPlayerSource.cs │ ├── IVoiceTarget.cs │ ├── PlayInfo.cs │ ├── PlayInfoEventArgs.cs │ ├── PlayManager.cs │ ├── Player.cs │ ├── SongEndEventArgs.cs │ ├── SongInfoChanged.cs │ ├── StallCheckPipe.cs │ └── StreamAudioPlayerSource.cs ├── Bot.cs ├── BotManager.cs ├── CallerInfo.cs ├── ClientCall.cs ├── CommandSystem │ ├── Ast │ │ ├── AstCommand.cs │ │ ├── AstError.cs │ │ ├── AstNode.cs │ │ ├── AstType.cs │ │ ├── AstValue.cs │ │ └── StringType.cs │ ├── BotCommand.cs │ ├── CommandAttribute.cs │ ├── CommandException.cs │ ├── CommandManager.cs │ ├── CommandParser.cs │ ├── CommandResults │ │ ├── IAudioResourceResult.cs │ │ ├── IWrappedResult.cs │ │ ├── PickObjectCommand.cs │ │ └── TailString.cs │ ├── CommandSystemExtensions.cs │ ├── CommandSystemTypes.cs │ ├── Commands │ │ ├── AliasCommand.cs │ │ ├── AppliedCommand.cs │ │ ├── CommandGroup.cs │ │ ├── FunctionCommand.cs │ │ ├── ICommand.cs │ │ ├── LazyCommand.cs │ │ ├── OverloadedFunctionCommand.cs │ │ ├── ResultCommand.cs │ │ └── RootCommand.cs │ ├── ExecutionInformation.cs │ ├── ICommandBag.cs │ ├── StaticList.cs │ └── Text │ │ ├── AppliedTextMod.cs │ │ ├── Color.cs │ │ ├── LongTextBehaviour.cs │ │ ├── LongTextTransform.cs │ │ ├── TextMod.cs │ │ ├── TextModBuilder.cs │ │ ├── TextModFlag.cs │ │ └── TextModHelper.cs ├── Config │ ├── Config.cs │ ├── ConfigArray.cs │ ├── ConfigDynamicTable.cs │ ├── ConfigEnumerable.cs │ ├── ConfigHelper.cs │ ├── ConfigPart.cs │ ├── ConfigStructs.cs │ ├── ConfigTable.cs │ ├── ConfigUpgrade2.cs │ └── ConfigValue.cs ├── Core.cs ├── DbStore.cs ├── Dependency │ ├── BasicInjector.cs │ ├── ChainedInjector.cs │ ├── DependencyBuilder.cs │ ├── IInjector.cs │ ├── InjectorExtensions.cs │ ├── Module.cs │ └── NullInjector.cs ├── Environment │ ├── Stats.cs │ ├── SystemData.cs │ └── SystemMonitor.cs ├── Error.cs ├── Helper │ ├── AttributeStrings.cs │ ├── Const.cs │ ├── Diagnose │ │ ├── SelfDiagnoseLevel.cs │ │ └── SelfDiagnoseMessage.cs │ ├── IJsonConfig.cs │ ├── ImageUtil.cs │ ├── Interactive.cs │ ├── LimitStream.cs │ ├── TextUtil.cs │ ├── TomlTools.cs │ ├── Util.cs │ └── WebWrapper.cs ├── History │ ├── AudioLogEntry.cs │ ├── HistoryManager.cs │ ├── HistorySaveData.cs │ ├── IHistoryFormatter.cs │ ├── SearchQuery.cs │ └── SmartHistoryFormatter.cs ├── InvokerData.cs ├── Limits.cs ├── Localization │ ├── DynamicResourceManager.cs │ ├── LocalStr.cs │ ├── LocalizationManager.cs │ ├── strings.Designer.cs │ └── strings.resx ├── MainCommands.cs ├── Media │ ├── SleepingKitty.png │ ├── SleepingKitty.svg │ └── favicon.ico ├── Playlists │ ├── LoopMode.cs │ ├── Parser │ │ └── JspfContent.cs │ ├── Playlist.cs │ ├── PlaylistApiExtensions.cs │ ├── PlaylistIO.cs │ ├── PlaylistItem.cs │ ├── PlaylistManager.cs │ └── Shuffle │ │ ├── IShuffleAlgorithm.cs │ │ ├── LinearFeedbackShiftRegister.cs │ │ ├── ListedShuffle.cs │ │ └── NormalOrder.cs ├── Plugins │ ├── ITabPlugin.cs │ ├── Plugin.cs │ ├── PluginCommandBag.cs │ ├── PluginExtensions.cs │ ├── PluginManager.cs │ ├── PluginObjects.cs │ ├── PluginResponse.cs │ └── PluginStatus.cs ├── Properties.cs ├── ResourceFactories │ ├── AudioResource.cs │ ├── AudioTags │ │ ├── AudioTagReader.cs │ │ ├── BinaryReaderBigEndianExtensions.cs │ │ └── M3uReader.cs │ ├── BandcampResolver.cs │ ├── IPlaylistResolver.cs │ ├── IResolver.cs │ ├── IResourceResolver.cs │ ├── ISearchResolver.cs │ ├── IThumbnailResolver.cs │ ├── MatchCertainty.cs │ ├── MediaResolver.cs │ ├── PlayResource.cs │ ├── ResolveContext.cs │ ├── ResourceResolver.cs │ ├── SongInfo.cs │ ├── SoundcloudResolver.cs │ ├── TwitchResolver.cs │ ├── Youtube │ │ ├── Json.cs │ │ ├── LoaderPriority.cs │ │ ├── VideoCodec.cs │ │ ├── VideoData.cs │ │ └── YoutubeResolver.cs │ └── YoutubeDlHelper.cs ├── Resources │ ├── DefaultRights.toml │ └── NLog.config ├── Rights │ ├── CreateFileSettings.cs │ ├── ExecuteContext.cs │ ├── Matchers │ │ ├── MatchApiCallerIp.cs │ │ ├── MatchBot.cs │ │ ├── MatchChannelGroupId.cs │ │ ├── MatchClientGroupId.cs │ │ ├── MatchClientUid.cs │ │ ├── MatchHost.cs │ │ ├── MatchIsApi.cs │ │ ├── MatchPermission.cs │ │ ├── MatchToken.cs │ │ ├── MatchVisibility.cs │ │ ├── Matcher.cs │ │ └── PermCompare.cs │ ├── ParseContext.cs │ ├── RightsDecl.cs │ ├── RightsGroup.cs │ ├── RightsManager.cs │ └── RightsRule.cs ├── Sessions │ ├── AnonymousSession.cs │ ├── ApiToken.cs │ ├── SessionManager.cs │ ├── TokenManager.cs │ └── UserSession.cs ├── Setup.cs ├── TS3AudioBot.csproj ├── Ts3Client.cs ├── Upgrader.cs ├── Web │ ├── Api │ │ ├── ApiCall.cs │ │ ├── DataStream.cs │ │ ├── JsonArray.cs │ │ ├── JsonEmpty.cs │ │ ├── JsonError.cs │ │ ├── JsonObject.cs │ │ ├── JsonValue.cs │ │ ├── OpenApiGenerator.cs │ │ ├── TimeSpanConverter.cs │ │ └── WebApi.cs │ ├── Model │ │ ├── CurrentSongInfo.cs │ │ ├── PlaylistInfo.cs │ │ ├── PlaylistItemGetData.cs │ │ └── QueueInfo.cs │ └── WebServer.cs ├── build.csx └── lib │ ├── x64 │ └── libopus.dll │ └── x86 │ └── libopus.dll ├── TSLib ├── Audio │ ├── AudioInterfaces.cs │ ├── AudioMeta.cs │ ├── AudioPacketReader.cs │ ├── AudioPipeExtensions.cs │ ├── AudioTools.cs │ ├── CheckActivePipe.cs │ ├── ClientMixdown.cs │ ├── DecoderPipe.cs │ ├── EncoderPipe.cs │ ├── Opus │ │ ├── LICENSE │ │ ├── NativeMethods.cs │ │ ├── OPUS_LICENSE │ │ ├── OpusDecoder.cs │ │ ├── OpusEncoder.cs │ │ └── README │ ├── PassiveMergePipe.cs │ ├── PassiveSplitterPipe.cs │ ├── PreciseAudioTimer.cs │ ├── PreciseTimedPipe.cs │ ├── StaticMetaPipe.cs │ ├── StreamAudioProducer.cs │ └── VolumePipe.cs ├── Commands │ ├── CommandMultiParameter.cs │ ├── CommandOption.cs │ ├── CommandParameter.cs │ ├── ICommandPart.cs │ ├── TsCommand.cs │ ├── TsCommand.gen.cs │ ├── TsCommand.gen.tt │ ├── TsConst.cs │ └── TsString.cs ├── ConnectionData.cs ├── DisconnectEventArgs.cs ├── EventDispatcher.cs ├── Full │ ├── Book │ │ ├── Book.cs │ │ └── SpecialTypes.cs │ ├── GenerationWindow.cs │ ├── IdentityData.cs │ ├── License.cs │ ├── NetworkStats.cs │ ├── Packet.cs │ ├── PacketHandler.cs │ ├── PacketType.cs │ ├── QuickerLz.cs │ ├── RingQueue.cs │ ├── TsCrypt.cs │ ├── TsFullClient.cs │ ├── TsFullClient.gen.cs │ └── TsFullClient.gen.tt ├── Generated │ ├── Book.cs │ ├── Book.tt │ ├── BookParser.ttinclude │ ├── ErrorParser.ttinclude │ ├── M2B.cs │ ├── M2B.tt │ ├── M2BParser.ttinclude │ ├── MessageParser.ttinclude │ ├── Messages.cs │ ├── Messages.tt │ ├── NotificationUtil.ttinclude │ ├── TsErrorCode.cs │ ├── TsErrorCode.tt │ ├── TsPermission.cs │ ├── TsPermission.tt │ ├── TsVersion.gen.cs │ ├── TsVersion.gen.tt │ └── Util.ttinclude ├── Helper │ ├── AsyncEventHandler.cs │ ├── CommandErrorExtensions.cs │ ├── DebugUtil.cs │ ├── LogId.cs │ ├── MissingEnumCaseException.cs │ ├── NativeLibraryLoader.cs │ ├── R.cs │ ├── SpanExtensions.cs │ ├── SpanSplitter.cs │ └── Tools.cs ├── LazyNotification.cs ├── MessageProcessor.cs ├── Messages │ ├── BaseTypes.cs │ ├── Deserializer.cs │ ├── MessageAdditions.cs │ ├── PermissionTransform.cs │ └── ResponseDictionary.cs ├── Properties.cs ├── Query │ ├── TsQueryClient.cs │ ├── TsQueryClient.gen.cs │ └── TsQueryClient.gen.tt ├── ReSpeak.png ├── Scheduler │ ├── DedicatedTaskScheduler.cs │ ├── DispatcherHelper.cs │ └── TickWorker.cs ├── TSLib.csproj ├── TsBaseFunctions.FileTransfer.cs ├── TsBaseFunctions.cs ├── TsBaseFunctions.gen.cs ├── TsBaseFunctions.gen.tt ├── TsDnsResolver.cs ├── TsEnums.cs ├── TsPermissionHelper.cs ├── TsVersion.cs ├── Types.cs ├── Types.gen.cs ├── Types.gen.tt ├── WaitBlock.cs └── dnc2_compat │ ├── Extensions.cs │ ├── Range.cs │ └── info.txt ├── Tools ├── pack_linux.csx ├── ts3notify.ps1 └── ts3notify.sh ├── WebInterface ├── package-lock.json ├── package.json ├── src │ ├── html │ │ ├── favicon.ico │ │ ├── index.html │ │ └── openapi │ │ │ ├── favicon-16x16.png │ │ │ ├── favicon-32x32.png │ │ │ ├── index.html │ │ │ ├── oauth2-redirect.html │ │ │ ├── swagger-ui-bundle.js │ │ │ ├── swagger-ui-bundle.js.map │ │ │ ├── swagger-ui-standalone-preset.js │ │ │ ├── swagger-ui-standalone-preset.js.map │ │ │ ├── swagger-ui.css │ │ │ ├── swagger-ui.css.map │ │ │ ├── swagger-ui.js │ │ │ └── swagger-ui.js.map │ ├── less │ │ └── styles_formdata.less │ └── ts │ │ ├── Api.ts │ │ ├── ApiAuth.ts │ │ ├── ApiObjects.ts │ │ ├── App.vue │ │ ├── Components │ │ ├── BotNavbarItem.vue │ │ ├── EditableText.vue │ │ ├── Hovercon.vue │ │ ├── Navbar.vue │ │ ├── PlayControls.vue │ │ ├── PlaybackInfo.vue │ │ ├── PlaylistEditor.vue │ │ ├── ServerTree.vue │ │ ├── ServerTreeNode.vue │ │ ├── ServerTreeUser.vue │ │ ├── SettingsField.vue │ │ ├── SettingsGroup.vue │ │ ├── SettingsPassword.vue │ │ └── VCanvas.vue │ │ ├── Graph.ts │ │ ├── Main.ts │ │ ├── Modals │ │ ├── CreateBotModal.vue │ │ ├── CreatePlaylistModal.vue │ │ ├── DeleteBotModal.vue │ │ ├── DeletePlaylistModal.vue │ │ ├── EnterPasswordModal.vue │ │ ├── QuickConnectModal.vue │ │ └── SiteSettingsModal.vue │ │ ├── Model │ │ ├── BotInfoSync.ts │ │ ├── BotStatus.ts │ │ ├── Languge.ts │ │ ├── PlayState.ts │ │ ├── RepeatKind.ts │ │ ├── SettingsLevel.ts │ │ ├── SpacerType.ts │ │ └── TargetSendMode.ts │ │ ├── Pages │ │ ├── Bot.vue │ │ ├── BotServer.vue │ │ ├── BotSettings.vue │ │ ├── Bots.vue │ │ ├── Commands.vue │ │ ├── Home.vue │ │ ├── OpenApi.d.ts │ │ ├── Overview.vue │ │ └── Playlists.vue │ │ ├── Timer.ts │ │ ├── Util.ts │ │ └── vue-shim.d.ts ├── tsconfig.json ├── tslint.json ├── webpack.config.js ├── webpack.development.config.js └── webpack.production.config.js └── appveyor.yml /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | patreon: Splamy 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is or what you expected to happen instead. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior (if possible) 12 | 13 | **Version** 14 | Which commit did you build or download? (mono TS3AudiBot.exe -V or !version in chat) 15 | 16 | **Platform** 17 | Which platform(-version) are you running on? (ubuntu 16.04, arch, windows,...) 18 | Which runtime(-version) are you using? (mono: mono -V, dotnet: dotnet --info) 19 | 20 | **Log** 21 | ``` 22 | Paste the important log parts from the ts3audiobot.log into this code block here. 23 | Try not to paste too little. 24 | At best from the first to last interaction from you which reproduces this problem. 25 | ``` 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/setup_help.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Setup help 3 | about: Problems setting up or running the bot 4 | 5 | --- 6 | 7 | **Describe the problem** 8 | A clear and concise description of what the problem is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior 12 | 13 | **System Information** 14 | - **Platform**: (Ubuntu 16.04, Debian 8, Arch, etc) 15 | 16 | - **Mono version**: (`mono -V`) 17 | 18 | - **Which commit did you download**: (or on prebuilt: `mono TS3AudioBot.exe -V`) 19 | 20 | (If all fields in the TS3AudioBot log header are correctly filled you can 21 | alternatively just post the header here.) 22 | 23 | **Additional Logs, Exceptions, etc** 24 | When applicable try to add relevant log excerpts here. 25 | 26 | ``` 27 | Put logs or code in triple backticks like here to properly format it. 28 | ``` 29 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "TSLib/Declarations"] 2 | path = TSLib/Declarations 3 | url = https://github.com/ReSpeak/tsdeclarations 4 | -------------------------------------------------------------------------------- /GitVersion.yml: -------------------------------------------------------------------------------- 1 | assembly-versioning-scheme: MajorMinorPatch 2 | mode: Mainline 3 | branches: 4 | master: 5 | tag: '' 6 | increment: Patch 7 | prevent-increment-of-merged-branch-version: true 8 | regex: ^master$ 9 | is-mainline: true 10 | develop: 11 | mode: ContinuousDeployment 12 | tag: alpha 13 | increment: Minor 14 | prevent-increment-of-merged-branch-version: true 15 | regex: ^develop$ 16 | ignore: 17 | sha: [] 18 | merge-message-formats: {} 19 | -------------------------------------------------------------------------------- /InstallOpus.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | baseDir=`pwd` 4 | 5 | OpusBaseName="opus-1.3.1" 6 | OpusFileName="$OpusBaseName.tar.gz" 7 | 8 | # Download the Opus library 9 | if [ ! -e "$OpusFileName" ]; then 10 | opusLink="http://downloads.xiph.org/releases/opus/$OpusFileName" 11 | echo "Downloading $opusLink" 12 | wget "$opusLink" 13 | else 14 | echo "Opus archive existing already" 15 | fi 16 | 17 | # Extract the archive 18 | tar -vxf "$OpusFileName" 19 | 20 | # Go into the extracted directory 21 | cd "$OpusBaseName" 22 | 23 | # Build the library 24 | ./configure && make && sudo make install 25 | 26 | # Move to global folder 27 | if [ ! -f /usr/lib/libopus.so ]; then 28 | sudo cp ".libs/libopus.so" "/usr/lib/" 29 | else 30 | echo "'/usr/lib/libopus.so' already exists, will not be overwritten" 31 | fi 32 | 33 | echo "Done" 34 | -------------------------------------------------------------------------------- /TS3ABotUnitTests/ResourceFactoriesTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using TS3AudioBot.Config; 3 | using TS3AudioBot.ResourceFactories; 4 | using TS3AudioBot.ResourceFactories.Youtube; 5 | 6 | namespace TS3ABotUnitTests 7 | { 8 | [TestFixture] 9 | public class ResourceFactoriesTests 10 | { 11 | [Test] 12 | public void Factory_YoutubeFactoryTest() 13 | { 14 | var ctx = new ResolveContext(null, null); 15 | using IResourceResolver rfac = new YoutubeResolver(new ConfResolverYoutube()); 16 | // matching links 17 | Assert.AreEqual(rfac.MatchResource(ctx, "https://www.youtube.com/watch?v=robqdGEhQWo"), MatchCertainty.Always); 18 | Assert.AreEqual(rfac.MatchResource(ctx, "https://youtu.be/robqdGEhQWo"), MatchCertainty.Always); 19 | Assert.AreEqual(rfac.MatchResource(ctx, "https://discarded-ideas.org/sites/discarded-ideas.org/files/music/darkforestkeep_symphonic.mp3"), MatchCertainty.Never); 20 | Assert.AreNotEqual(rfac.MatchResource(ctx, "http://splamy.de/youtube.com/youtu.be/fake.mp3"), MatchCertainty.Always); 21 | 22 | // restoring links 23 | Assert.AreEqual("https://youtu.be/robqdGEhQWo", rfac.RestoreLink(ctx, new AudioResource { ResourceId = "robqdGEhQWo" })); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TS3ABotUnitTests/ShuffleTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Collections; 3 | using TS3AudioBot.Playlists.Shuffle; 4 | 5 | namespace TS3ABotUnitTests 6 | { 7 | [TestFixture] 8 | public class ShuffleTests 9 | { 10 | [Test] 11 | public void NormalOrderTest() 12 | { 13 | TestShuffleAlgorithmBiDir(new NormalOrder()); 14 | } 15 | 16 | [Test] 17 | public void ListedShuffleTest() 18 | { 19 | TestShuffleAlgorithmBiDir(new ListedShuffle()); 20 | } 21 | 22 | [Test] 23 | public void LinearFeedbackShiftRegisterTest() 24 | { 25 | TestShuffleAlgorithmBiDir(new LinearFeedbackShiftRegister()); 26 | } 27 | 28 | private static void TestShuffleAlgorithmBiDir(IShuffleAlgorithm algo) 29 | { 30 | TestShuffleAlgorithm(algo, true); 31 | TestShuffleAlgorithm(algo, false); 32 | } 33 | 34 | private static void TestShuffleAlgorithm(IShuffleAlgorithm algo, bool forward) 35 | { 36 | for (int i = 1; i < 1000; i++) 37 | { 38 | var checkNumbers = new BitArray(i, false); 39 | 40 | algo.Length = i; 41 | algo.Seed = i; 42 | 43 | for (int j = 0; j < i; j++) 44 | { 45 | if (forward) algo.Next(); 46 | else algo.Prev(); 47 | int shufNum = algo.Index; 48 | if (checkNumbers.Get(shufNum)) 49 | Assert.Fail("Duplicate number"); 50 | checkNumbers.Set(shufNum, true); 51 | } 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /TS3ABotUnitTests/TS3ABotUnitTests.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Library 5 | netcoreapp3.1 6 | 7 | 8.0 8 | disable 9 | AnyCPU 10 | false 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /TS3ABotUnitTests/TextSplitterTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Linq; 3 | using TS3AudioBot.CommandSystem.Text; 4 | using TSLib.Commands; 5 | 6 | namespace TS3ABotUnitTests 7 | { 8 | [TestFixture] 9 | public class TextSplitterTests 10 | { 11 | public const string Str1 = "Playlist: \"[B]asdf2[/B]\" with 110 songs.\n0: 【nami】 One of Repetition -「繰り返し一粒 」を歌ってみた\n1: God knows... ''The Melancholy of Haruhi Suzumiya'' 【涼宮ハルヒの憂鬱】Kadokawa公認MAD【ベース 演奏】\n2: Noucome op Full\n3: 麻枝 准×やなぎなぎ「無敵のSoldier」\n4: Nisemonogatari Opening 3 - Platinum Disco (Yuka Iguchi) HD\n5: SAO II OP Courage Full\n6: SAO II OP Ignite Full\n7: 「Secret base~君がくれたもの~」cover by【Mesxmokonax冥月x洛】\n8: [HQ] Yousei Teikoku - Kokou no Sousei\n9: Yousei Teikoku - Kikai Shoujo Gensou\n10: Yousei Teikoku- Tasogare no Gekka\n11: Yousei Teikoku - Wahrheit\n12: 【Karaoke】IA IA ★ Night of Desire【on vocal】 samfree\n13: [1080P Full風] Luka Luka★Night Fever ルカルカ★ナイトフィーバー 巡音ルカ Project DIVA English lyrics romaji subtitles\n14: Vocaloid - Nekomura Iroha - Cat Cat ☆Super Fever Night\n15: [Piko] \"Piko Piko ☆Legend Of The Night \" english subbed [english / romaji in the description]\n16: 【MMD】 Pomp And Circumstance 【Yukari & Lily】\n17: 【MMD】 Two Faced Lovers (Nikoman Ver.) 【CUL】\n18: 【CUL】「Aokigahara -青木ヶ原-」【Vocaloidカバー】\n19: 【MMD】 LUVORATORRRRRY! 【Kagamine Rin & GUMI】\n"; 12 | public const int MaxSplit = 8192; 13 | 14 | [Test] 15 | public void Split() 16 | { 17 | for (int i = 4; i < MaxSplit; i++) 18 | { 19 | var parts = LongTextTransform.Split(Str1, LongTextBehaviour.SplitHard, maxMessageSize: i).ToArray(); 20 | foreach (var part in parts) 21 | { 22 | Assert.LessOrEqual(TsString.TokenLength(part), i); 23 | } 24 | var joined = string.Concat(parts); 25 | Assert.AreEqual(Str1, joined); 26 | } 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3ABotUnitTests/UtilsTests.cs: -------------------------------------------------------------------------------- 1 | using NUnit.Framework; 2 | using System.Text.RegularExpressions; 3 | using TS3AudioBot.Helper; 4 | using TSLib.Full; 5 | 6 | namespace TS3ABotUnitTests 7 | { 8 | [TestFixture] 9 | public class UtilsTests 10 | { 11 | [Test] 12 | public void UtilSeedTest() 13 | { 14 | var lowCaseRegex = new Regex("^[a-z]*$", Util.DefaultRegexConfig & ~RegexOptions.IgnoreCase); 15 | for (int i = 0; i < 100000; i++) 16 | { 17 | var str = Util.FromSeed(i); 18 | Assert.IsTrue(lowCaseRegex.IsMatch(str), "For seed: " + i); 19 | var roundtrip = Util.ToSeed(str); 20 | Assert.AreEqual(i, roundtrip); 21 | } 22 | } 23 | 24 | /* ======================= TSLib Tests ========================*/ 25 | 26 | [Test] 27 | public void VersionSelfCheck() 28 | { 29 | TsCrypt.VersionSelfCheck(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TS3AudioBot/Algorithm/TimedCache.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Concurrent; 12 | using System.Diagnostics.CodeAnalysis; 13 | using System.Linq; 14 | using TSLib.Helper; 15 | 16 | namespace TS3AudioBot.Algorithm 17 | { 18 | public class TimedCache where TK : notnull 19 | { 20 | public TimeSpan Timeout { get; } 21 | private readonly ConcurrentDictionary cachedData; 22 | 23 | public TimedCache() : this(TimeSpan.FromSeconds(3)) { } 24 | 25 | public TimedCache(TimeSpan timeout) 26 | { 27 | Timeout = timeout; 28 | cachedData = new ConcurrentDictionary(); 29 | } 30 | 31 | public bool TryGetValue(TK key, [MaybeNullWhen(false)] out TV value) 32 | { 33 | if (!cachedData.TryGetValue(key, out var data) 34 | || Tools.Now - Timeout > data.Timestamp) 35 | { 36 | CleanCache(); 37 | value = default!; 38 | return false; 39 | } 40 | value = data.Data; 41 | return true; 42 | } 43 | 44 | public void Set(TK key, TV value) 45 | { 46 | cachedData[key] = new TimedData { Data = value, Timestamp = Tools.Now }; 47 | } 48 | 49 | public void Clear() 50 | { 51 | cachedData.Clear(); 52 | } 53 | 54 | private void CleanCache() 55 | { 56 | var now = Tools.Now - Timeout; 57 | foreach (var item in cachedData.Where(kvp => now > kvp.Value.Timestamp).ToList()) 58 | { 59 | cachedData.TryRemove(item.Key, out _); 60 | } 61 | } 62 | 63 | private struct TimedData 64 | { 65 | public TV Data; 66 | public DateTime Timestamp; 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/AudioValues.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TSLib.Helper; 12 | 13 | namespace TS3AudioBot.Audio 14 | { 15 | public static class AudioValues 16 | { 17 | public const float MinVolume = 0; 18 | public const float MaxVolume = 100; 19 | 20 | // Reference explanation for the logarithmic scale 21 | // https://www.dr-lex.be/info-stuff/volumecontrols.html#table1 22 | // Adjusted values for 40dB 23 | 24 | private const float fact_a = 1e-2f; 25 | private const float fact_b = 4.61512f; 26 | 27 | public static float HumanVolumeToFactor(float value) 28 | { 29 | if (value < MinVolume) return 0; 30 | if (value > MaxVolume) return 1; 31 | 32 | // Map input values from [MinVolume, MaxVolume] to [0, 1] 33 | value = (value - MinVolume) / (MaxVolume - MinVolume); 34 | 35 | // Scale the value logarithmically 36 | return Tools.Clamp((float)(fact_a * Math.Exp(fact_b * value)) - fact_a, 0, 1); 37 | } 38 | 39 | public static float FactorToHumanVolume(float value) 40 | { 41 | if (value < 0) return MinVolume; 42 | if (value > 1) return MaxVolume; 43 | 44 | // Undo logarithmical scale 45 | value = Tools.Clamp((float)(Math.Log((value + fact_a) / fact_a) / fact_b), 0, 1); 46 | 47 | // Map input values from [0, 1] to [MinVolume, MaxVolume] 48 | return (value * (MaxVolume - MinVolume)) + MinVolume; 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/IPlayerSource.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Threading.Tasks; 12 | using TSLib.Audio; 13 | 14 | namespace TS3AudioBot.Audio 15 | { 16 | public interface IPlayerSource : IAudioPassiveProducer 17 | { 18 | event EventHandler OnSongEnd; 19 | event EventHandler OnSongUpdated; 20 | 21 | TimeSpan? Length { get; } 22 | TimeSpan? Position { get; } 23 | 24 | Task Seek(TimeSpan position); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/PlayInfo.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Diagnostics.CodeAnalysis; 12 | using TSLib; 13 | 14 | namespace TS3AudioBot.Audio 15 | { 16 | public sealed class PlayInfo 17 | { 18 | /// Defaults to: invoker.Uid - Can be set if the owner of a song differs from the invoker. 19 | public Uid? ResourceOwnerUid { get; set; } 20 | /// Starts the song at the specified time if set. 21 | public TimeSpan? StartOffset { get; set; } 22 | 23 | public PlayInfo(TimeSpan? startOffset = null) 24 | { 25 | StartOffset = startOffset; 26 | } 27 | 28 | public PlayInfo Merge(PlayInfo other) => Merge(this, other); 29 | 30 | [return: NotNullIfNotNull("self")] 31 | [return: NotNullIfNotNull("other")] 32 | public static PlayInfo? Merge(PlayInfo? self, PlayInfo? other) 33 | { 34 | if (other is null) 35 | return self; 36 | if (self is null) 37 | return other; 38 | self.ResourceOwnerUid ??= other.ResourceOwnerUid; 39 | self.StartOffset ??= other.StartOffset; 40 | return self; 41 | } 42 | 43 | public static PlayInfo MergeDefault(PlayInfo? self, PlayInfo? other) 44 | => Merge(self, other) ?? new PlayInfo(); 45 | } 46 | 47 | public interface IMetaContainer 48 | { 49 | public PlayInfo? PlayInfo { get; set; } 50 | } 51 | 52 | public static class MetaContainerExtensions 53 | { 54 | public static T MergeMeta(this T container, PlayInfo? other) where T : IMetaContainer 55 | { 56 | container.PlayInfo = PlayInfo.Merge(container.PlayInfo, other); 57 | return container; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/PlayInfoEventArgs.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TS3AudioBot.ResourceFactories; 12 | 13 | namespace TS3AudioBot.Audio 14 | { 15 | public sealed class PlayInfoEventArgs : EventArgs 16 | { 17 | public InvokerData Invoker { get; } 18 | public PlayResource PlayResource { get; } 19 | public AudioResource ResourceData => PlayResource.AudioResource; 20 | public PlayInfo? PlayInfo => PlayResource.PlayInfo; 21 | public string? SourceLink { get; } 22 | 23 | public PlayInfoEventArgs(InvokerData invoker, PlayResource playResource, string? sourceLink) 24 | { 25 | Invoker = invoker; 26 | PlayResource = playResource; 27 | SourceLink = sourceLink; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/SongEndEventArgs.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Audio 13 | { 14 | public class SongEndEventArgs : EventArgs 15 | { 16 | public bool SongEndedByCallback { get; } 17 | public SongEndEventArgs(bool songEndedByCallback) { SongEndedByCallback = songEndedByCallback; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/SongInfoChanged.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Audio 13 | { 14 | public class SongInfoChanged : EventArgs 15 | { 16 | public string? Title { get; set; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/StallCheckPipe.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TSLib.Audio; 12 | 13 | namespace TS3AudioBot.Audio 14 | { 15 | public class StallCheckPipe : IAudioPipe 16 | { 17 | private const uint StallCountInterval = 10; 18 | private const uint StallNoErrorCountMax = 5; 19 | 20 | public bool Active => OutStream?.Active ?? false; 21 | public IAudioPassiveConsumer? OutStream { get; set; } 22 | 23 | private bool isStall; 24 | private uint stallCount; 25 | private uint stallNoErrorCount; 26 | 27 | public StallCheckPipe() 28 | { 29 | isStall = false; 30 | stallCount = 0; 31 | } 32 | 33 | public void Write(Span data, Meta? meta) 34 | { 35 | if (OutStream is null) return; 36 | 37 | if (isStall) 38 | { 39 | // TODO maybe do time-cooldown instead of call-count-cooldown 40 | if (++stallCount % StallCountInterval == 0) 41 | { 42 | stallNoErrorCount++; 43 | if (stallNoErrorCount > StallNoErrorCountMax) 44 | { 45 | stallCount = 0; 46 | isStall = false; 47 | } 48 | } 49 | else 50 | { 51 | return; 52 | } 53 | } 54 | 55 | OutStream?.Write(data, meta); 56 | } 57 | 58 | public void SetStall() 59 | { 60 | stallNoErrorCount = 0; 61 | isStall = true; 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /TS3AudioBot/Audio/StreamAudioPlayerSource.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Threading.Tasks; 12 | using TSLib.Audio; 13 | 14 | namespace TS3AudioBot.Audio 15 | { 16 | public class StreamAudioPlayerSource : IPlayerSource, IAudioActiveConsumer 17 | { 18 | private bool hasFired = false; 19 | 20 | public IAudioPassiveProducer? InStream { get; set; } 21 | public TimeSpan? Length => null; 22 | public TimeSpan? Position => null; 23 | 24 | public event EventHandler? OnSongEnd; 25 | event EventHandler IPlayerSource.OnSongUpdated { add { } remove { } } 26 | 27 | public StreamAudioPlayerSource() { } 28 | 29 | public StreamAudioPlayerSource(IAudioPassiveProducer stream) : this() 30 | { 31 | InStream = stream; 32 | } 33 | 34 | public int Read(byte[] buffer, int offset, int length, out Meta? meta) 35 | { 36 | var stream = InStream; 37 | if (stream is null) 38 | { 39 | meta = default; 40 | return 0; 41 | } 42 | 43 | var read = stream.Read(buffer, offset, length, out meta); 44 | if (read == 0 && !hasFired) 45 | { 46 | hasFired = true; 47 | OnSongEnd?.Invoke(this, EventArgs.Empty); 48 | return 0; 49 | } 50 | return read; 51 | } 52 | 53 | public void Reset() => hasFired = false; 54 | 55 | public void Dispose() => InStream?.Dispose(); 56 | 57 | public Task Seek(TimeSpan position) { throw new NotSupportedException(); } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /TS3AudioBot/CallerInfo.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot 11 | { 12 | public class CallerInfo 13 | { 14 | /// Whether this call was initiated from the api. 15 | public bool ApiCall { get; } 16 | /// Skips all permission checks when set to true. 17 | public bool SkipRightsChecks { get; set; } = false; 18 | /// Counts execution token for a single call to prevent endless loops. 19 | public int CommandComplexityCurrent { get; set; } = 0; 20 | /// The maximum execution token count for a single call. 21 | public int CommandComplexityMax { get; set; } = 0; 22 | /// Whether the caller wants a colored output. 23 | public bool IsColor { get; set; } 24 | 25 | public CallerInfo(bool isApi) 26 | { 27 | ApiCall = isApi; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TS3AudioBot/ClientCall.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib; 11 | 12 | namespace TS3AudioBot 13 | { 14 | public class ClientCall : InvokerData 15 | { 16 | /// The original unmodified string which was received by the client. 17 | public string TextMessage { get; } 18 | 19 | public ClientDbId? DatabaseId { get; } 20 | public ChannelId? ChannelId { get; } 21 | public ClientId? ClientId { get; } 22 | public string? NickName { get; } 23 | public ServerGroupId[]? ServerGroups { get; } 24 | public ChannelGroupId? ChannelGroup { get; } 25 | public TextMessageTargetMode? Visibiliy { get; internal set; } 26 | 27 | public ClientCall(Uid clientUid, string textMessage, ClientDbId? databaseId = null, 28 | ChannelId? channelId = null, ClientId? clientId = null, string? nickName = null, 29 | TextMessageTargetMode? visibiliy = null, ServerGroupId[]? serverGroups = null, 30 | ChannelGroupId? channelGroup = null) : base(clientUid) 31 | { 32 | TextMessage = textMessage; 33 | DatabaseId = databaseId; 34 | ChannelId = channelId; 35 | ClientId = clientId; 36 | NickName = nickName; 37 | Visibiliy = visibiliy; 38 | ServerGroups = serverGroups; 39 | ChannelGroup = channelGroup; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/AstCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Text; 12 | 13 | namespace TS3AudioBot.CommandSystem.Ast 14 | { 15 | internal class AstCommand : AstNode 16 | { 17 | public override AstType Type => AstType.Command; 18 | 19 | public List Parameter { get; } = new List(); 20 | 21 | public AstCommand(string fullRequest) : base(fullRequest) { } 22 | 23 | public override void Write(StringBuilder strb, int depth) 24 | { 25 | strb.Space(depth); 26 | if (Parameter.Count == 0) 27 | { 28 | strb.Append(""); 29 | } 30 | else 31 | { 32 | if (Parameter[0] is AstValue comName) 33 | strb.Append("!").Append(comName.Value); 34 | else 35 | strb.Append(""); 36 | 37 | for (int i = 1; i < Parameter.Count; i++) 38 | { 39 | strb.AppendLine(); 40 | Parameter[i].Write(strb, depth + 1); 41 | } 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/AstError.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Text; 11 | 12 | namespace TS3AudioBot.CommandSystem.Ast 13 | { 14 | internal class AstError : AstNode 15 | { 16 | public override AstType Type => AstType.Error; 17 | 18 | public string Description { get; } 19 | 20 | public AstError(AstNode referenceNode, string description) 21 | : this(referenceNode.FullRequest, referenceNode.Position, referenceNode.Length, description) { } 22 | 23 | public AstError(string request, int pos, int len, string description) : base(request) 24 | { 25 | Position = pos; 26 | Length = len; 27 | Description = description; 28 | } 29 | 30 | public override void Write(StringBuilder strb, int depth) 31 | { 32 | strb.AppendLine(FullRequest); 33 | if (Position == 1) strb.Append('.'); 34 | else if (Position > 1) strb.Append(' ', Position); 35 | strb.Append('~', Length).Append('^').AppendLine(); 36 | strb.Append("Error: ").AppendLine(Description); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/AstNode.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Text; 11 | 12 | namespace TS3AudioBot.CommandSystem.Ast 13 | { 14 | public abstract class AstNode 15 | { 16 | public abstract AstType Type { get; } 17 | 18 | public string FullRequest { get; } 19 | public int Position { get; set; } 20 | public int Length { get; set; } 21 | 22 | protected AstNode(string fullRequest) 23 | { 24 | FullRequest = fullRequest; 25 | } 26 | 27 | public abstract void Write(StringBuilder strb, int depth); 28 | public sealed override string ToString() 29 | { 30 | var strb = new StringBuilder(); 31 | Write(strb, 0); 32 | return strb.ToString(); 33 | } 34 | } 35 | 36 | internal static class AstNodeExtensions 37 | { 38 | public const int SpacePerTab = 2; 39 | public static StringBuilder Space(this StringBuilder strb, int depth) => strb.Append(' ', depth * SpacePerTab); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/AstType.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.Ast 11 | { 12 | public enum AstType 13 | { 14 | Command, 15 | Value, 16 | Error, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/AstValue.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Text; 11 | 12 | namespace TS3AudioBot.CommandSystem.Ast 13 | { 14 | internal class AstValue : AstNode 15 | { 16 | private string? value; 17 | private string? tailString; 18 | 19 | public override AstType Type => AstType.Value; 20 | public StringType StringType { get; } 21 | public int TailLength { get; set; } 22 | 23 | public string Value 24 | { 25 | get => value ??= FullRequest.Substring(Position, Length); 26 | set { this.value = value; tailString = value; } 27 | } 28 | 29 | public string TailString 30 | { 31 | get 32 | { 33 | if (tailString is null) 34 | { 35 | if (TailLength == 0) 36 | tailString = FullRequest.Substring(Position); 37 | else 38 | tailString = FullRequest.Substring(Position, TailLength); 39 | } 40 | return tailString; 41 | } 42 | } 43 | 44 | public AstValue(string fullRequest, StringType stringType) : base(fullRequest) 45 | { 46 | StringType = stringType; 47 | } 48 | 49 | public override void Write(StringBuilder strb, int depth) => strb.Space(depth).Append(Value); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Ast/StringType.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.Ast 11 | { 12 | internal enum StringType 13 | { 14 | FreeString, 15 | QuotedString, 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandAttribute.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.CommandSystem 13 | { 14 | /// 15 | /// Marks a method as callable from the CommandSystem. 16 | /// The containing class must be registered in the CommandSystem to use this method. 17 | /// 18 | [AttributeUsage(AttributeTargets.Method, Inherited = false)] 19 | public sealed class CommandAttribute : Attribute 20 | { 21 | public string CommandNameSpace { get; } 22 | public string? OverrideHelpName { get; } 23 | 24 | public CommandAttribute(string commandNameSpace, string? overrideHelpName = null) 25 | { 26 | CommandNameSpace = commandNameSpace; 27 | OverrideHelpName = overrideHelpName; 28 | } 29 | } 30 | 31 | /// 32 | /// Gives an example on how to use this method. 33 | /// Can be used to clarify different functionality from various overloads. 34 | /// 35 | [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = true)] 36 | public sealed class UsageAttribute : Attribute 37 | { 38 | public string UsageSyntax { get; } 39 | public string UsageHelp { get; } 40 | 41 | public UsageAttribute(string syntax, string help) 42 | { 43 | UsageSyntax = syntax; 44 | UsageHelp = help; 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandResults/IAudioResourceResult.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.ResourceFactories; 11 | 12 | namespace TS3AudioBot.CommandSystem.CommandResults 13 | { 14 | public interface IAudioResourceResult 15 | { 16 | AudioResource AudioResource { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandResults/IWrappedResult.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.CommandResults 11 | { 12 | public interface IWrappedResult 13 | { 14 | object? Content { get; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandResults/PickObjectCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Reflection; 11 | 12 | namespace TS3AudioBot.CommandSystem.CommandResults 13 | { 14 | public class Pick : IWrappedResult 15 | { 16 | private readonly string pickPath; 17 | private readonly T baseObj; 18 | private bool isPicked; 19 | private object? pickedValue; 20 | 21 | public object? Content 22 | { 23 | get 24 | { 25 | if (!isPicked) 26 | { 27 | isPicked = true; 28 | pickedValue = null; 29 | pickedValue = DoPick(); 30 | } 31 | return pickedValue; 32 | } 33 | } 34 | 35 | public Pick(T obj, string pickPath) 36 | { 37 | baseObj = obj; 38 | this.pickPath = pickPath; 39 | } 40 | 41 | private object? DoPick() 42 | { 43 | if (baseObj == null) 44 | return null; // TODO maybe error ? 45 | if (string.IsNullOrEmpty(pickPath)) 46 | return baseObj; 47 | var type = baseObj.GetType(); 48 | var prop = type.GetProperty(pickPath, BindingFlags.Public | BindingFlags.Instance); 49 | if (prop is null) 50 | throw new CommandException("Property not found" /* TODO LOC */); 51 | return prop.GetValue(baseObj); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandResults/TailString.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.CommandResults 11 | { 12 | public class TailString : IWrappedResult 13 | { 14 | public string Content { get; } 15 | public string Tail { get; } 16 | object? IWrappedResult.Content => Content; 17 | 18 | public TailString(string contentArg, string tailArg) 19 | { 20 | Content = contentArg; 21 | Tail = tailArg; 22 | } 23 | 24 | public override string ToString() => Content; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandSystemExtensions.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Threading.Tasks; 13 | using TS3AudioBot.Algorithm; 14 | using TS3AudioBot.CommandSystem.Commands; 15 | using TS3AudioBot.Dependency; 16 | 17 | namespace TS3AudioBot.CommandSystem 18 | { 19 | public static class CommandSystemExtensions 20 | { 21 | public static IFilter GetFilter(this IInjector injector) 22 | { 23 | if (injector.TryGet(out var filter)) 24 | return filter; 25 | return Filter.DefaultFilter; 26 | } 27 | 28 | public static Lazy GetFilterLazy(this IInjector injector) 29 | => new Lazy(() => injector.GetFilter(), false); 30 | 31 | public static async ValueTask ExecuteToString(this ICommand com, ExecutionInformation info, IReadOnlyList arguments) 32 | { 33 | var res = await com.Execute(info, arguments); 34 | return res?.ToString() ?? ""; 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/CommandSystemTypes.cs: -------------------------------------------------------------------------------- 1 | // Copyright (C) 2017 TS3AudioBot contributors 2 | // 3 | // This program is free software: you can redistribute it and/or modify 4 | // it under the terms of the Open Software License v. 3.0 5 | // 6 | // You should have received a copy of the Open Software License along with this 7 | // program. If not, see . 8 | 9 | using System; 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using TS3AudioBot.CommandSystem.CommandResults; 13 | using TSLib; 14 | 15 | namespace TS3AudioBot.CommandSystem 16 | { 17 | public static class CommandSystemTypes 18 | { 19 | /// 20 | /// The order of types, the first item has the highest priority, 21 | /// items not in the list have higher priority as they are special types. 22 | /// 23 | public static readonly Type[] TypeOrder = { 24 | typeof(bool), 25 | typeof(sbyte), typeof(byte), 26 | typeof(short), typeof(ushort), 27 | typeof(int), typeof(uint), 28 | typeof(long), typeof(ulong), 29 | typeof(float), typeof(double), 30 | typeof(TimeSpan), typeof(DateTime), 31 | typeof(string) }; 32 | public static readonly HashSet BasicTypes = new HashSet(TypeOrder); 33 | 34 | public static readonly HashSet AdvancedTypes = new HashSet(new Type[] { 35 | typeof(IAudioResourceResult), 36 | typeof(System.Collections.IEnumerable), 37 | typeof(ResourceFactories.AudioResource), 38 | typeof(History.AudioLogEntry), 39 | typeof(Playlists.PlaylistItem), 40 | }.Concat(TsTypes.All)); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/AliasCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using System.Threading.Tasks; 14 | using TS3AudioBot.Dependency; 15 | 16 | namespace TS3AudioBot.CommandSystem.Commands 17 | { 18 | public class AliasCommand : ICommand 19 | { 20 | private readonly ICommand aliasCommand; 21 | public string AliasString { get; } 22 | 23 | public AliasCommand(string command) 24 | { 25 | var ast = CommandParser.ParseCommandRequest(command); 26 | aliasCommand = CommandManager.AstToCommandResult(ast); 27 | AliasString = command; 28 | } 29 | 30 | public async ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments) 31 | { 32 | info.UseComplexityTokens(1); 33 | 34 | IReadOnlyList? backupArguments = null; 35 | if (!info.TryGet(out var aliasContext)) 36 | { 37 | aliasContext = new AliasContext(); 38 | info.AddModule(aliasContext); 39 | } 40 | else 41 | { 42 | backupArguments = aliasContext.Arguments; 43 | } 44 | 45 | aliasContext.Arguments = arguments.Select(c => new LazyCommand(c)).ToArray(); 46 | var ret = await aliasCommand.Execute(info, Array.Empty()); 47 | aliasContext.Arguments = backupArguments; 48 | return ret; 49 | } 50 | } 51 | 52 | public class AliasContext 53 | { 54 | public IReadOnlyList? Arguments { get; set; } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/AppliedCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.CommandSystem.Commands 14 | { 15 | public class AppliedCommand : ICommand 16 | { 17 | private readonly ICommand internCommand; 18 | private readonly IReadOnlyList internArguments; 19 | 20 | public AppliedCommand(ICommand command, IReadOnlyList arguments) 21 | { 22 | internCommand = command; 23 | internArguments = arguments; 24 | } 25 | 26 | public virtual async ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments) 27 | { 28 | var merged = new ICommand[internArguments.Count + arguments.Count]; 29 | internArguments.CopyTo(0, merged, 0); 30 | arguments.CopyTo(0, merged, internArguments.Count); 31 | return await internCommand.Execute(info, merged); 32 | } 33 | 34 | public override string ToString() => $"F\"{internCommand}\"({string.Join(", ", internArguments)})"; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/ICommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.CommandSystem.Commands 14 | { 15 | public interface ICommand 16 | { 17 | /// Execute this command. 18 | /// All global informations for this execution. 19 | /// 20 | /// The arguments for this command. 21 | /// They are evaluated lazy which means they will only be evaluated if needed. 22 | /// 23 | /// 24 | /// The possible return types that should be returned by this execution. 25 | /// They are ordered by priority so, if possible, the first return type should be picked, then the second and so on. 26 | /// 27 | /// These types can contain primitive types, the actual return value will then be wrapped into a . 28 | /// null inside the list allows an empty result. 29 | /// 30 | /// 31 | /// The result of this command. 32 | /// null is an empty result. 33 | /// 34 | ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/LazyCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.CommandSystem.Commands 14 | { 15 | public class LazyCommand : ICommand 16 | { 17 | private readonly ICommand innerCommand; 18 | private bool executed = false; 19 | /// 20 | /// The cached result, if available. 21 | /// 22 | private object? result; 23 | 24 | public LazyCommand(ICommand innerCommandArg) 25 | { 26 | innerCommand = innerCommandArg; 27 | } 28 | 29 | public virtual async ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments) 30 | { 31 | if (!executed) 32 | { 33 | result = await innerCommand.Execute(info, arguments); 34 | executed = true; 35 | return result; 36 | } 37 | return result; 38 | } 39 | 40 | public override string ToString() => $"L({innerCommand})"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/ResultCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.CommandSystem.Commands 14 | { 15 | /// 16 | /// A command that stores a result and returns it. 17 | /// 18 | public class ResultCommand : ICommand 19 | { 20 | public object? Content { get; } 21 | 22 | public ResultCommand(object? contentArg) 23 | { 24 | Content = contentArg; 25 | } 26 | 27 | #pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously 28 | public virtual async ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments) 29 | #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously 30 | { 31 | return Content; 32 | } 33 | 34 | public override string ToString() => ""; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Commands/RootCommand.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Linq; 12 | using System.Threading.Tasks; 13 | using TS3AudioBot.Dependency; 14 | 15 | namespace TS3AudioBot.CommandSystem.Commands 16 | { 17 | /// 18 | /// A special group founction that extracts the root group from the current execution context 19 | /// 20 | public class RootCommand : ICommand 21 | { 22 | private readonly IReadOnlyList internArguments; 23 | 24 | public RootCommand(IReadOnlyList arguments) 25 | { 26 | internArguments = arguments; 27 | } 28 | 29 | public virtual async ValueTask Execute(ExecutionInformation info, IReadOnlyList arguments) 30 | { 31 | if (!info.TryGet(out var cmdSys)) 32 | throw new CommandException("Could not find local commandsystem tree", CommandExceptionReason.MissingContext); 33 | 34 | IReadOnlyList merged; 35 | if (arguments.Count == 0) 36 | merged = internArguments; 37 | else if (internArguments.Count == 0) 38 | merged = arguments; 39 | else 40 | merged = internArguments.Concat(arguments).ToArray(); 41 | return await cmdSys.RootGroup.Execute(info, merged); 42 | } 43 | 44 | public override string ToString() => $"RootCmd({string.Join(", ", internArguments)})"; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/ExecutionInformation.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.Dependency; 11 | 12 | namespace TS3AudioBot.CommandSystem 13 | { 14 | public class ExecutionInformation : ChainedInjector 15 | { 16 | public ExecutionInformation() : this(NullInjector.Instance) { } 17 | public ExecutionInformation(IInjector parent) : base(parent, new BasicInjector()) 18 | { 19 | this.AddModule(this); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/ICommandBag.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | 12 | namespace TS3AudioBot.CommandSystem 13 | { 14 | public interface ICommandBag 15 | { 16 | IReadOnlyCollection BagCommands { get; } 17 | IReadOnlyCollection AdditionalRights { get; } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Text/AppliedTextMod.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.Text 11 | { 12 | public readonly struct AppliedTextMod 13 | { 14 | public string? Text { get; } 15 | public TextMod Mod { get; } 16 | 17 | public AppliedTextMod(string? text) 18 | { 19 | Text = text; 20 | Mod = TextMod.None; 21 | } 22 | 23 | public AppliedTextMod(string? text, TextMod mod) 24 | { 25 | Text = text; 26 | Mod = mod; 27 | } 28 | 29 | public readonly AppliedTextMod Color(Color color) => new AppliedTextMod(Text, Mod.Color(color)); 30 | public readonly AppliedTextMod Bold() => new AppliedTextMod(Text, Mod.Bold()); 31 | public readonly AppliedTextMod Italic() => new AppliedTextMod(Text, Mod.Italic()); 32 | public readonly AppliedTextMod Underline() => new AppliedTextMod(Text, Mod.Underline()); 33 | public readonly AppliedTextMod Strike() => new AppliedTextMod(Text, Mod.Strike()); 34 | 35 | public static implicit operator AppliedTextMod(string? text) => new AppliedTextMod(text); 36 | 37 | public override readonly string? ToString() => Text; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Text/LongTextBehaviour.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.Text 11 | { 12 | public enum LongTextBehaviour 13 | { 14 | /// Splits the message preferably at line breaks. 15 | Split, 16 | /// Splits at exact maximum length per message. 17 | SplitHard, 18 | /// Discards the message. 19 | Drop, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Text/TextModFlag.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.CommandSystem.Text 13 | { 14 | [Flags] 15 | public enum TextModFlag 16 | { 17 | None = 0, 18 | Color = 1 << 0, 19 | Underline = 1 << 1, 20 | Strike = 1 << 2, 21 | Italic = 1 << 3, 22 | Bold = 1 << 4, 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /TS3AudioBot/CommandSystem/Text/TextModHelper.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.CommandSystem.Text 11 | { 12 | public static class TextModHelper 13 | { 14 | public static AppliedTextMod Mod(this string str) => str; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TS3AudioBot/Config/ConfigArray.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Nett; 11 | using Newtonsoft.Json; 12 | using System; 13 | using System.Collections.Generic; 14 | using TS3AudioBot.Helper; 15 | 16 | namespace TS3AudioBot.Config 17 | { 18 | public class ConfigArray : ConfigValue> where T : notnull 19 | { 20 | public ConfigArray(string key, IReadOnlyList defaultVal, string doc = "") : base(key, defaultVal, doc) { } 21 | 22 | public override void FromToml(TomlObject? tomlObject) 23 | { 24 | if (tomlObject != null && tomlObject.TryGetValueArray(out var array)) 25 | { 26 | Value = array; 27 | } 28 | } 29 | 30 | public override void ToJson(JsonWriter writer) 31 | { 32 | writer.WriteStartArray(); 33 | foreach (var item in Value) 34 | { 35 | writer.WriteValue(item); 36 | } 37 | writer.WriteEndArray(); 38 | } 39 | 40 | public override E FromJson(JsonReader reader) 41 | { 42 | try 43 | { 44 | if (reader.Read() 45 | && (reader.TokenType == JsonToken.StartArray)) 46 | { 47 | var list = new List(); 48 | while (reader.TryReadValue(out var value)) 49 | { 50 | list.Add(value); 51 | } 52 | 53 | if (reader.TokenType != JsonToken.EndArray) 54 | return $"Expected end of array but found {reader.TokenType}"; 55 | 56 | Value = list; 57 | return R.Ok; 58 | } 59 | return $"Wrong type, expected {typeof(T).Name}, got {reader.TokenType}"; 60 | } 61 | catch (JsonReaderException ex) { return $"Could not read value: {ex.Message}"; } 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /TS3AudioBot/Config/ConfigUpgrade2.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.IO; 12 | using System.Text.RegularExpressions; 13 | using TS3AudioBot.Helper; 14 | 15 | namespace TS3AudioBot.Config 16 | { 17 | /// 18 | /// Upgrades the /bots/ folder structure from each Bot being a 'bot_(name).toml' 19 | /// file to each bot having its own folder with '/(name)/bot.toml'. 20 | /// 21 | internal static class ConfigUpgrade2 22 | { 23 | private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); 24 | private static readonly Regex BotFileMatcher = new Regex(@"^bot_(.+)\.toml$", Util.DefaultRegexConfig); 25 | private const string NewBotConfigFileName = "bot.toml"; 26 | 27 | public static void Upgrade(string path) 28 | { 29 | string[] files; 30 | try 31 | { 32 | files = Directory.GetFiles(path); 33 | } 34 | catch (Exception ex) 35 | { 36 | Log.Error(ex, "Failed to get 'Bots' directory. Your bots might not be available. Refer to our GitHub for upgrade actions."); 37 | return; 38 | } 39 | 40 | foreach (var file in files) 41 | { 42 | try 43 | { 44 | var fi = new FileInfo(file); 45 | var match = BotFileMatcher.Match(fi.Name); 46 | if (match.Success) 47 | { 48 | var name = match.Groups[1].Value; 49 | Directory.CreateDirectory(Path.Combine(path, name)); 50 | fi.MoveTo(Path.Combine(path, name, NewBotConfigFileName)); 51 | } 52 | } 53 | catch (Exception ex) 54 | { 55 | Log.Error(ex, "Failed to move Bot '{0}' to the new folder structure.", file); 56 | } 57 | } 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TS3AudioBot/DbStore.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using LiteDB; 11 | using System; 12 | using System.IO; 13 | using TS3AudioBot.Config; 14 | 15 | namespace TS3AudioBot 16 | { 17 | public class DbStore : IDisposable 18 | { 19 | private const string DbMetaInformationTable = "dbmeta"; 20 | 21 | private readonly LiteDatabase database; 22 | private readonly LiteCollection metaTable; 23 | 24 | public DbStore(ConfDb config) 25 | { 26 | var historyFile = Path.GetFullPath(config.Path); 27 | database = new LiteDatabase(historyFile); 28 | 29 | metaTable = database.GetCollection(DbMetaInformationTable); 30 | } 31 | 32 | public DbMetaData GetMetaData(string table) 33 | { 34 | var meta = metaTable.FindById(table); 35 | if (meta is null) 36 | { 37 | meta = new DbMetaData { Id = table, Version = 0, CustomData = null }; 38 | metaTable.Insert(meta); 39 | } 40 | return meta; 41 | } 42 | 43 | public void UpdateMetaData(DbMetaData metaData) 44 | { 45 | metaTable.Upsert(metaData); 46 | } 47 | 48 | public LiteCollection GetCollection(string name) 49 | { 50 | return database.GetCollection(name); 51 | } 52 | 53 | public void DropCollection(string name) => database.DropCollection(name); 54 | 55 | public void CleanFile() 56 | { 57 | database.Shrink(); 58 | } 59 | 60 | public void Dispose() 61 | { 62 | database.Dispose(); 63 | } 64 | } 65 | 66 | public class DbMetaData 67 | { 68 | public string? Id { get; set; } 69 | public int Version { get; set; } 70 | public string? CustomData { get; set; } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /TS3AudioBot/Dependency/BasicInjector.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | 13 | namespace TS3AudioBot.Dependency 14 | { 15 | public class BasicInjector : IInjector 16 | { 17 | private readonly Dictionary dynamicObjects; 18 | public BasicInjector() { dynamicObjects = new Dictionary(); } 19 | public object? GetModule(Type type) => dynamicObjects.TryGetValue(type, out var mod) ? mod : null; 20 | public void AddModule(Type type, object obj) => dynamicObjects[type] = obj; 21 | public IEnumerable GetAllModules() => dynamicObjects.Values; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Dependency/ChainedInjector.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Dependency 13 | { 14 | public class ChainedInjector : IInjector where T : class, IInjector 15 | { 16 | public IInjector ParentInjector { get; set; } 17 | public T OwnInjector { get; protected set; } 18 | 19 | public ChainedInjector(IInjector parent, T own) 20 | { 21 | ParentInjector = parent ?? throw new ArgumentNullException(nameof(parent)); 22 | OwnInjector = own ?? throw new ArgumentNullException(nameof(parent)); 23 | } 24 | 25 | public virtual object? GetModule(Type type) 26 | => OwnInjector.GetModule(type) ?? ParentInjector.GetModule(type); 27 | 28 | public virtual void AddModule(Type type, object obj) 29 | => OwnInjector.AddModule(type, obj); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TS3AudioBot/Dependency/IInjector.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Dependency 13 | { 14 | /// 15 | /// This provides the base contract for 'injector' classes. 16 | /// An injector is basically a dictionary to look up objects by type. 17 | /// 18 | public interface IInjector 19 | { 20 | object? GetModule(Type type); 21 | void AddModule(Type type, object obj); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Dependency/Module.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Linq; 12 | 13 | namespace TS3AudioBot.Dependency 14 | { 15 | internal class Module 16 | { 17 | public Type TImplementation { get; } 18 | public Type TService { get; } 19 | public Type[] ConstructorParam { get; } 20 | 21 | public Module(Type tService, Type tImplementation) 22 | { 23 | TService = tService; 24 | TImplementation = tImplementation; 25 | ConstructorParam = DependencyBuilder.GetContructorParam(TImplementation) ?? throw new ArgumentException("Invalid type"); 26 | } 27 | 28 | public override string ToString() => $"{TService.Name}({(TService != TImplementation ? TImplementation.Name : "-")}) => {string.Join(",", ConstructorParam.Select(x => x.Name))}"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TS3AudioBot/Dependency/NullInjector.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Dependency 13 | { 14 | public sealed class NullInjector : IInjector 15 | { 16 | public static readonly IInjector Instance = new NullInjector(); 17 | private NullInjector() { } 18 | public object? GetModule(Type type) => null; 19 | public void AddModule(Type type, object obj) { } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/Error.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace TS3AudioBot 5 | { 6 | public static class Error 7 | { 8 | public static AudioBotException LocalStr(string text) => new AudioBotException().LocalStr(text); 9 | public static AudioBotException Exception(Exception ex) => new AudioBotException(ex); 10 | public static AudioBotException Str(string text) => new AudioBotException().Str(text); 11 | 12 | public static AudioBotException LocalStr(this AudioBotException ex, string text) { ex.LocalStr = text; return ex; } 13 | public static AudioBotException Str(this AudioBotException ex, string text) { ex.Str = text; return ex; } 14 | public static void Throw(this AudioBotException ex) => throw ex; 15 | } 16 | 17 | [Serializable] 18 | public class AudioBotException : Exception 19 | { 20 | public string? LocalStr { get; set; } 21 | public string? Str { get; set; } 22 | public Exception? InnerCustomException { get; set; } 23 | 24 | public override string Message => LocalStr ?? Str ?? ""; 25 | 26 | public AudioBotException(Exception? ex = null) 27 | : base(null, ex) 28 | { } 29 | 30 | public AudioBotException(string message, Exception? inner = null) 31 | : base(null, inner) 32 | { 33 | LocalStr = message; 34 | } 35 | 36 | protected AudioBotException(SerializationInfo info, StreamingContext context) 37 | : base(info, context) 38 | { } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TS3AudioBot/Helper/AttributeStrings.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Helper 11 | { 12 | internal static class AttributeStrings 13 | { 14 | public const string UnderDevelopment = "This feature is unstable and might change"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TS3AudioBot/Helper/Const.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Helper 11 | { 12 | internal static class SessionConst 13 | { 14 | public const string SearchResult = "tab_searchresult"; 15 | } 16 | 17 | public static class BotPaths 18 | { 19 | public const string Playlists = "playlists"; 20 | public const string Avatars = "avatars"; 21 | public const string Music = "music"; 22 | } 23 | 24 | public static class FilesConst 25 | { 26 | public const string CoreConfig = "ts3audiobot.toml"; 27 | public const string BotConfig = "bot.toml"; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3AudioBot/Helper/Diagnose/SelfDiagnoseLevel.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Helper.Diagnose 11 | { 12 | public enum SelfDiagnoseLevel 13 | { 14 | Info, 15 | Warning, 16 | Error 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/Helper/Diagnose/SelfDiagnoseMessage.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | 12 | namespace TS3AudioBot.Helper.Diagnose 13 | { 14 | public class SelfDiagnoseMessage 15 | { 16 | public string Description { get; } 17 | public string Category { get; } 18 | public string Level => LevelValue.ToString(); 19 | [JsonIgnore] 20 | public SelfDiagnoseLevel LevelValue { get; } 21 | 22 | public SelfDiagnoseMessage(string description, string category, SelfDiagnoseLevel levelValue) 23 | { 24 | Description = description; 25 | Category = category; 26 | LevelValue = levelValue; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3AudioBot/Helper/Interactive.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.Helper 14 | { 15 | public static class Interactive 16 | { 17 | public static bool UserAgree(bool defaultTo = true) 18 | { 19 | while (true) 20 | { 21 | var key = Console.ReadKey(true).Key; 22 | if (key == ConsoleKey.Y || (defaultTo && key == ConsoleKey.Enter)) 23 | return true; 24 | if (key == ConsoleKey.N || (!defaultTo && key == ConsoleKey.Enter)) 25 | return false; 26 | } 27 | } 28 | 29 | public static string? LoopAction(string question, Func action) 30 | { 31 | string text; 32 | do 33 | { 34 | Console.WriteLine(question); 35 | text = Console.ReadLine(); 36 | if (text is null) 37 | return null; 38 | } 39 | while (!action(text)); 40 | return text; 41 | } 42 | 43 | public static async Task LoopActionAsync(string question, Func> action) 44 | { 45 | string text; 46 | do 47 | { 48 | Console.WriteLine(question); 49 | text = Console.ReadLine(); 50 | if (text is null) 51 | return null; 52 | } 53 | while (!await action(text)); 54 | return text; 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /TS3AudioBot/History/HistorySaveData.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TS3AudioBot.ResourceFactories; 12 | using TSLib; 13 | 14 | namespace TS3AudioBot.History 15 | { 16 | public class HistorySaveData 17 | { 18 | public AudioResource Resource { get; } 19 | public Uid? InvokerUid { get; } 20 | 21 | public HistorySaveData(AudioResource resource, Uid? invokerUid) 22 | { 23 | Resource = resource ?? throw new ArgumentNullException(nameof(resource)); 24 | InvokerUid = invokerUid; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TS3AudioBot/History/IHistoryFormatter.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | 13 | namespace TS3AudioBot.History 14 | { 15 | public interface IHistoryFormatter 16 | { 17 | string ProcessQuery(AudioLogEntry entry, Func format); 18 | string ProcessQuery(IEnumerable entries, Func format); 19 | } 20 | 21 | // needed ? 22 | public enum HistoryDisplayColumn 23 | { 24 | AleId, 25 | UserDbId, 26 | UserName, 27 | AleTitle, 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3AudioBot/History/SearchQuery.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.History 13 | { 14 | public class SeachQuery 15 | { 16 | public string? TitlePart { get; set; } 17 | public string? UserUid { get; set; } 18 | public DateTime? LastInvokedAfter { get; set; } 19 | public int MaxResults { get; set; } 20 | 21 | public SeachQuery() 22 | { 23 | TitlePart = null; 24 | UserUid = null; 25 | LastInvokedAfter = null; 26 | MaxResults = 10; 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3AudioBot/InvokerData.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib; 11 | 12 | namespace TS3AudioBot 13 | { 14 | public class InvokerData 15 | { 16 | public Uid ClientUid { get; } 17 | public bool IsAnonymous => ClientUid == Uid.Anonymous; 18 | 19 | public static readonly InvokerData Anonymous = new InvokerData(Uid.Anonymous); 20 | 21 | public InvokerData(Uid clientUid) 22 | { 23 | ClientUid = clientUid; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TS3AudioBot/Limits.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot 11 | { 12 | public static class Limits 13 | { 14 | /// Max stream size to download before aborting. 15 | public static long MaxImageStreamSize { get; } = 10_000_000; 16 | /// Max image size which is allowed to be resized from. 17 | public static long MaxImageDimension { get; } = 10_000; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TS3AudioBot/Localization/LocalStr.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Localization 11 | { 12 | /// 13 | /// Represents a localizable string 14 | /// 15 | public readonly struct LocalStr 16 | { 17 | public static readonly LocalStr Empty = new LocalStr(string.Empty); 18 | 19 | public string Str { get; } 20 | 21 | public LocalStr(string str) 22 | { 23 | Str = str; 24 | } 25 | 26 | public override readonly string ToString() => Str; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TS3AudioBot/Media/SleepingKitty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TS3AudioBot/Media/SleepingKitty.png -------------------------------------------------------------------------------- /TS3AudioBot/Media/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TS3AudioBot/Media/favicon.ico -------------------------------------------------------------------------------- /TS3AudioBot/Playlists/LoopMode.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Playlists 11 | { 12 | public enum LoopMode 13 | { 14 | Off, 15 | One, 16 | All, 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/Playlists/PlaylistApiExtensions.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.ResourceFactories; 11 | using TS3AudioBot.Web.Model; 12 | 13 | namespace TS3AudioBot.Playlists 14 | { 15 | public static class PlaylistApiExtensions 16 | { 17 | public static PlaylistItemGetData ToApiFormat(this ResolveContext resourceFactory, PlaylistItem item) 18 | { 19 | var resource = item.AudioResource; 20 | return new PlaylistItemGetData 21 | { 22 | Link = resourceFactory.RestoreLink(resource), 23 | Title = resource.ResourceTitle, 24 | AudioType = resource.AudioType, 25 | }; 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TS3AudioBot/Playlists/PlaylistItem.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TS3AudioBot.Audio; 12 | using TS3AudioBot.CommandSystem.CommandResults; 13 | using TS3AudioBot.ResourceFactories; 14 | 15 | namespace TS3AudioBot.Playlists 16 | { 17 | public class PlaylistItem : IAudioResourceResult, IMetaContainer 18 | { 19 | public PlayInfo? PlayInfo { get; set; } 20 | public AudioResource AudioResource { get; } 21 | 22 | public PlaylistItem(AudioResource resource, PlayInfo? meta = null) 23 | { 24 | AudioResource = resource ?? throw new ArgumentNullException(nameof(resource)); 25 | PlayInfo = meta; 26 | } 27 | 28 | public static PlaylistItem From(PlayResource playResource) 29 | { 30 | return new PlaylistItem(playResource.AudioResource, playResource.PlayInfo); 31 | } 32 | 33 | public override string ToString() => AudioResource.ResourceTitle ?? $"{AudioResource.AudioType}: {AudioResource.ResourceId}"; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TS3AudioBot/Playlists/Shuffle/IShuffleAlgorithm.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Playlists.Shuffle 11 | { 12 | public interface IShuffleAlgorithm 13 | { 14 | int Seed { get; set; } 15 | int Length { get; set; } 16 | int Index { get; set; } 17 | // Returns true if the step reached the end of the list and wrapped around 18 | bool Next(); 19 | // Returns true if the step reached the end of the list and wrapped around 20 | bool Prev(); 21 | } 22 | 23 | // Output conventions: 24 | // 25 | // if Index = x, x >= Length 26 | // => Index = Tools.MathMod(Index, Length) 27 | // if Index = x, x < 0 28 | // => Index : undefined 29 | // if Index = x, Length < 0 30 | // => Index = -1 31 | } 32 | -------------------------------------------------------------------------------- /TS3AudioBot/Playlists/Shuffle/NormalOrder.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib.Helper; 11 | 12 | namespace TS3AudioBot.Playlists.Shuffle 13 | { 14 | public class NormalOrder : IShuffleAlgorithm 15 | { 16 | public int Seed { get; set; } 17 | public int Length { get; set; } 18 | public int Index { get; set; } 19 | 20 | public bool Next() 21 | { 22 | Index = Tools.MathMod(Index + 1, Length); 23 | return Index == 0; 24 | } 25 | 26 | public bool Prev() 27 | { 28 | Index = Tools.MathMod(Index - 1, Length); 29 | return Index == Length - 1; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/ITabPlugin.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.Plugins 13 | { 14 | public interface ITabPlugin : IDisposable 15 | { 16 | void Initialize(); 17 | } 18 | 19 | public interface ICorePlugin : ITabPlugin { } 20 | 21 | public interface IBotPlugin : ITabPlugin { } 22 | 23 | public interface IPluginMeta 24 | { 25 | string Name { get; } 26 | string Description { get; } 27 | string Author { get; } 28 | Uri ProjectUrl { get; } 29 | Version Version { get; } 30 | } 31 | 32 | [AttributeUsage(AttributeTargets.Class, Inherited = false)] 33 | [Obsolete("Static Plugins are deprecated, use an ICorePlugin instead")] 34 | public sealed class StaticPluginAttribute : Attribute { } 35 | } 36 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/PluginCommandBag.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Linq; 13 | using TS3AudioBot.CommandSystem; 14 | 15 | namespace TS3AudioBot.Plugins 16 | { 17 | internal class PluginCommandBag : ICommandBag 18 | { 19 | public IReadOnlyCollection BagCommands { get; } 20 | public IReadOnlyCollection AdditionalRights => Array.Empty(); 21 | 22 | public PluginCommandBag(object? obj, Type t) 23 | { 24 | BagCommands = CommandManager.GetBotCommands(obj, t).ToArray(); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/PluginExtensions.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using NLog; 11 | using System.Diagnostics; 12 | using System.Runtime.CompilerServices; 13 | 14 | namespace TS3AudioBot.Plugins 15 | { 16 | public static class PluginExtensions 17 | { 18 | [MethodImpl(MethodImplOptions.NoInlining)] 19 | public static Logger GetLogger() 20 | { 21 | var cls = new StackTrace()?.GetFrame(1)?.GetMethod()?.DeclaringType?.Name ?? "Unknown"; 22 | return LogManager.GetLogger($"TS3AudioBot.Plugins.{cls}"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/PluginObjects.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.CommandSystem; 11 | 12 | namespace TS3AudioBot.Plugins 13 | { 14 | internal class PluginObjects 15 | { 16 | public PluginCommandBag Bag { get; set; } 17 | public ITabPlugin Plugin { get; set; } 18 | public CommandManager CommandManager { get; set; } 19 | 20 | public PluginObjects(ITabPlugin plugin, PluginCommandBag bag, CommandManager commandManager) 21 | { 22 | Bag = bag; 23 | Plugin = plugin; 24 | CommandManager = commandManager; 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/PluginResponse.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Plugins 11 | { 12 | public enum PluginResponse 13 | { 14 | Ok, 15 | Crash, 16 | MissingDependency, 17 | MissingContext, 18 | InvalidBinary, 19 | NoTypeMatch, 20 | TooManyPlugins, 21 | UnknownError, 22 | PluginNotFound, 23 | CompileError, 24 | Disabled, 25 | NotSupported, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TS3AudioBot/Plugins/PluginStatus.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Plugins 11 | { 12 | public enum PluginStatus 13 | { 14 | /// The plugin has just been found and is ready to be prepared. 15 | Off, 16 | /// The plugin is valid and ready to be loaded. 17 | Ready, 18 | /// The plugin is currently active. 19 | Active, 20 | /// The plugin has been plugged off intentionally and will not be prepared with the next scan. 21 | Disabled, 22 | /// The plugin failed to load. 23 | Error, 24 | /// The plugin needs to be checked/loaded withing a Bot context. 25 | NotAvailable, 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TS3AudioBot/Properties.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("TS3ABotUnitTests")] 4 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/IPlaylistResolver.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Threading.Tasks; 11 | using TS3AudioBot.Playlists; 12 | 13 | namespace TS3AudioBot.ResourceFactories 14 | { 15 | public interface IPlaylistResolver : IResolver 16 | { 17 | MatchCertainty MatchPlaylist(ResolveContext ctx, string uri); 18 | 19 | Task GetPlaylist(ResolveContext ctx, string url); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/IResolver.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TS3AudioBot.ResourceFactories 13 | { 14 | public interface IResolver : IDisposable 15 | { 16 | string ResolverFor { get; } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/ISearchResolver.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Threading.Tasks; 12 | 13 | namespace TS3AudioBot.ResourceFactories 14 | { 15 | public interface ISearchResolver : IResolver 16 | { 17 | Task> Search(ResolveContext ctx, string keyword); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/IThumbnailResolver.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.IO; 12 | using System.Threading.Tasks; 13 | 14 | namespace TS3AudioBot.ResourceFactories 15 | { 16 | public interface IThumbnailResolver : IResolver 17 | { 18 | Task GetThumbnail(ResolveContext ctx, PlayResource playResource, Func action); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/MatchCertainty.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.ResourceFactories 11 | { 12 | public enum MatchCertainty 13 | { 14 | /// "Never" denotes that this factory cannot use this link. 15 | Never = 0, 16 | /// "OnlyIfLast" Only gets selected if no higher match was found. 17 | OnlyIfLast, 18 | /// "Always" will reserve a link exclusively for all factories which also said "Always". 19 | Always, 20 | } 21 | 22 | public static class MatchCertaintyExtensions 23 | { 24 | public static MatchCertainty ToMatchCertainty(this bool val) => val ? MatchCertainty.Always : MatchCertainty.Never; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/PlayResource.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.Audio; 11 | using TS3AudioBot.CommandSystem.CommandResults; 12 | 13 | namespace TS3AudioBot.ResourceFactories 14 | { 15 | public class PlayResource : IAudioResourceResult, IMetaContainer 16 | { 17 | public AudioResource AudioResource { get; } 18 | public string PlayUri { get; } 19 | public PlayInfo? PlayInfo { get; set; } 20 | public SongInfo? SongInfo { get; set; } 21 | 22 | public PlayResource(string uri, AudioResource baseData, PlayInfo? playInfo = null, SongInfo? songInfo = null) 23 | { 24 | AudioResource = baseData; 25 | PlayUri = uri; 26 | PlayInfo = playInfo; 27 | SongInfo = songInfo; 28 | } 29 | 30 | public override string ToString() => AudioResource.ToString(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/ResolveContext.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.IO; 13 | using System.Threading.Tasks; 14 | using TS3AudioBot.Config; 15 | using TS3AudioBot.Playlists; 16 | 17 | namespace TS3AudioBot.ResourceFactories 18 | { 19 | public class ResolveContext 20 | { 21 | public ResourceResolver Resolver { get; } 22 | public ConfBot Config { get; } 23 | 24 | public ResolveContext(ResourceResolver resolver, ConfBot config) 25 | { 26 | Resolver = resolver; 27 | Config = config; 28 | } 29 | 30 | public Task Load(AudioResource resource) => Resolver.Load(this, resource); 31 | public Task Load(string message, string? audioType = null) => Resolver.Load(this, message, audioType); 32 | public Task LoadPlaylistFrom(string message, string? audioType = null) => Resolver.LoadPlaylistFrom(this, message, audioType); 33 | public string? RestoreLink(AudioResource res) => Resolver.RestoreLink(this, res); 34 | public Task GetThumbnail(PlayResource playResource, Func action) => Resolver.GetThumbnail(this, playResource, action); 35 | public Task> Search(string resolverName, string query) => Resolver.Search(this, resolverName, query); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/SongInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace TS3AudioBot.ResourceFactories 4 | { 5 | public class SongInfo 6 | { 7 | public string? Title { get; set; } 8 | public string? Track { get; set; } 9 | public string? Artist { get; set; } 10 | public TimeSpan? Length { get; set; } 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/Youtube/LoaderPriority.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.ResourceFactories.Youtube 11 | { 12 | public enum LoaderPriority 13 | { 14 | Internal, 15 | YoutubeDl 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/Youtube/VideoCodec.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.ResourceFactories.Youtube 11 | { 12 | public enum VideoCodec 13 | { 14 | Unknown, 15 | Mp4, 16 | M4A, 17 | Webm, 18 | Flv, 19 | ThreeGp, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/ResourceFactories/Youtube/VideoData.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.ResourceFactories.Youtube 11 | { 12 | public sealed class VideoData 13 | { 14 | public VideoData(string link, string qualitydesciption, VideoCodec codec, bool audioOnly = false, bool videoOnly = false) 15 | { 16 | Link = link; 17 | Qualitydesciption = qualitydesciption; 18 | Codec = codec; 19 | AudioOnly = audioOnly; 20 | VideoOnly = videoOnly; 21 | } 22 | 23 | public string Link { get; } 24 | public string Qualitydesciption { get; } 25 | public VideoCodec Codec { get; } 26 | public bool AudioOnly { get; } 27 | public bool VideoOnly { get; } 28 | 29 | public override string ToString() => $"{Qualitydesciption} @ {Codec} - {Link}"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /TS3AudioBot/Resources/DefaultRights.toml: -------------------------------------------------------------------------------- 1 | # Rights declaration file 2 | # For more information about syntax and structure see here: 3 | # https://github.com/Splamy/TS3AudioBot/wiki/Rights 4 | 5 | "+" = [ 6 | # Basic stuff 7 | "cmd.help.*", 8 | "cmd.pm", 9 | "cmd.subscribe", 10 | "cmd.unsubscribe", 11 | "cmd.kickme.*", 12 | "cmd.version", 13 | 14 | # Getting song info 15 | "cmd.song", 16 | "cmd.repeat", 17 | "cmd.random", 18 | 19 | # Conditionals and basic scripting 20 | "cmd.if", 21 | "cmd.print", 22 | "cmd.rng", 23 | "cmd.eval", 24 | "cmd.take", 25 | "cmd.xecute", 26 | "cmd.getmy.*", 27 | "cmd.json.*", 28 | "cmd.bot.use", 29 | "cmd.rights.can", 30 | ] 31 | 32 | # Admin rule 33 | [[rule]] 34 | # Set your admin Group Ids here, ex: [ 13, 42 ] 35 | groupid = [] 36 | # And/Or your admin Client Uids here 37 | useruid = [ "_admin_uid_" ] 38 | # By default treat requests from localhost as admin 39 | ip = [ "127.0.0.1", "::1" ] 40 | 41 | "+" = "*" 42 | 43 | # Playing rights 44 | [[rule]] 45 | # Set Group Ids you want to allow here, ex: [ 13, 42 ] 46 | groupid = [] 47 | # And/Or Client Uids here, ex [ "uA0U7t4PBxdJ5TLnarsOHQh4/tY=", "8CnUQzwT/d9nHNeUaed0RPsDxxk=" ] 48 | useruid = [] 49 | # Or remove groupid and useruid to allow for everyone 50 | 51 | "+" = [ 52 | # Play controls 53 | "cmd.play", 54 | "cmd.pause", 55 | "cmd.stop", 56 | "cmd.seek", 57 | "cmd.volume", 58 | 59 | # Playlist management 60 | "cmd.list.*", 61 | "cmd.add", 62 | "cmd.clear", 63 | "cmd.previous", 64 | "cmd.next", 65 | "cmd.random.*", 66 | "cmd.repeat.*", 67 | 68 | # History features 69 | "cmd.history.add", 70 | "cmd.history.from", 71 | "cmd.history.id", 72 | "cmd.history.last", 73 | "cmd.history.play", 74 | "cmd.history.till", 75 | "cmd.history.title", 76 | ] 77 | -------------------------------------------------------------------------------- /TS3AudioBot/Resources/NLog.config: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | 7 | 8 | 13 | 14 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/CreateFileSettings.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Rights 11 | { 12 | public class CreateFileSettings 13 | { 14 | // can be null 15 | public string[]? AdminUids { get; set; } = null; 16 | 17 | public bool OverwriteIfExists { get; set; } = false; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/ExecuteContext.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | using System.Net; 13 | using TSLib; 14 | using TSLib.Messages; 15 | 16 | namespace TS3AudioBot.Rights 17 | { 18 | internal class ExecuteContext 19 | { 20 | public string? Host { get; set; } 21 | public ServerGroupId[]? ServerGroups { get; set; } = Array.Empty(); 22 | public ChannelGroupId? ChannelGroupId { get; set; } 23 | public Uid ClientUid { get; set; } 24 | public bool IsApi { get; set; } 25 | public IPAddress? ApiCallerIp { get; set; } 26 | public string? ApiToken { get; set; } 27 | public string? Bot { get; set; } 28 | public TextMessageTargetMode? Visibiliy { get; set; } 29 | public PermOverview[]? Permissions { get; set; } 30 | 31 | public List MatchingRules { get; } = new List(); 32 | 33 | public HashSet DeclAdd { get; } = new HashSet(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchApiCallerIp.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using System.Net; 12 | 13 | namespace TS3AudioBot.Rights.Matchers 14 | { 15 | internal class MatchApiCallerIp : Matcher 16 | { 17 | private readonly HashSet requestIps; 18 | 19 | public MatchApiCallerIp(IEnumerable requestIps) => this.requestIps = new HashSet(requestIps); 20 | 21 | public override bool Matches(ExecuteContext ctx) => ctx.ApiCallerIp != null && requestIps.Contains(ctx.ApiCallerIp); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchBot.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | 12 | namespace TS3AudioBot.Rights.Matchers 13 | { 14 | internal class MatchBot : Matcher 15 | { 16 | private readonly HashSet bots; 17 | 18 | public MatchBot(IEnumerable bots) => this.bots = new HashSet(bots); 19 | 20 | public override bool Matches(ExecuteContext ctx) => ctx.Bot != null && bots.Contains(ctx.Bot); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchChannelGroupId.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using TSLib; 12 | 13 | namespace TS3AudioBot.Rights.Matchers 14 | { 15 | internal class MatchChannelGroupId : Matcher 16 | { 17 | private readonly HashSet channelGroupIds; 18 | 19 | public MatchChannelGroupId(IEnumerable channelGroupIds) => this.channelGroupIds = new HashSet(channelGroupIds); 20 | 21 | public override bool Matches(ExecuteContext ctx) => ctx.ChannelGroupId != null && channelGroupIds.Contains(ctx.ChannelGroupId.Value); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchClientGroupId.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using TSLib; 12 | 13 | namespace TS3AudioBot.Rights.Matchers 14 | { 15 | internal class MatchServerGroupId : Matcher 16 | { 17 | private readonly HashSet serverGroupIds; 18 | 19 | public MatchServerGroupId(IEnumerable serverGroupIds) => this.serverGroupIds = new HashSet(serverGroupIds); 20 | 21 | public override bool Matches(ExecuteContext ctx) => ctx.ServerGroups?.Length > 0 && serverGroupIds.Overlaps(ctx.ServerGroups); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchClientUid.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using TSLib; 12 | 13 | namespace TS3AudioBot.Rights.Matchers 14 | { 15 | internal class MatchClientUid : Matcher 16 | { 17 | private readonly HashSet clientUids; 18 | 19 | public MatchClientUid(IEnumerable clientUids) => this.clientUids = new HashSet(clientUids); 20 | 21 | public override bool Matches(ExecuteContext ctx) => ctx.ClientUid != null && clientUids.Contains(ctx.ClientUid); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchHost.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | 12 | namespace TS3AudioBot.Rights.Matchers 13 | { 14 | internal class MatchHost : Matcher 15 | { 16 | private readonly HashSet hosts; 17 | 18 | public MatchHost(IEnumerable hosts) => this.hosts = new HashSet(hosts); 19 | 20 | public override bool Matches(ExecuteContext ctx) => ctx.Host != null && hosts.Contains(ctx.Host); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchIsApi.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Rights.Matchers 11 | { 12 | internal class MatchIsApi : Matcher 13 | { 14 | private readonly bool isApi; 15 | 16 | public MatchIsApi(bool isApi) => this.isApi = isApi; 17 | 18 | public override bool Matches(ExecuteContext ctx) => ctx.IsApi == isApi; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchToken.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | 12 | namespace TS3AudioBot.Rights.Matchers 13 | { 14 | internal class MatchToken : Matcher 15 | { 16 | private readonly HashSet tokens; 17 | 18 | public MatchToken(IEnumerable tokens) => this.tokens = new HashSet(tokens); 19 | 20 | public override bool Matches(ExecuteContext ctx) => ctx.ApiToken != null && tokens.Contains(ctx.ApiToken); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/MatchVisibility.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Linq; 11 | using TSLib; 12 | 13 | namespace TS3AudioBot.Rights.Matchers 14 | { 15 | internal class MatchVisibility : Matcher 16 | { 17 | private readonly TextMessageTargetMode[] visibility; 18 | 19 | public MatchVisibility(TextMessageTargetMode[] visibility) => this.visibility = visibility; 20 | 21 | public override bool Matches(ExecuteContext ctx) => ctx.Visibiliy != null && visibility.Contains(ctx.Visibiliy.Value); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/Matcher.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Rights.Matchers 11 | { 12 | internal abstract class Matcher 13 | { 14 | public abstract bool Matches(ExecuteContext ctx); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/Matchers/PermCompare.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Rights 11 | { 12 | internal enum PermCompare 13 | { 14 | Equal, 15 | NotEqual, 16 | Greater, 17 | GreaterOrEqual, 18 | Less, 19 | LessOrEqual, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/Rights/RightsGroup.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Rights 11 | { 12 | internal class RightsGroup : RightsDecl 13 | { 14 | public string Name { get; } 15 | 16 | public RightsGroup(string name) 17 | { 18 | Name = name; 19 | } 20 | 21 | public override RightsGroup? ResolveGroup(string groupName, ParseContext ctx) 22 | { 23 | if (Name == groupName) 24 | return this; 25 | return Parent?.ResolveGroup(groupName, ctx); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TS3AudioBot/Sessions/AnonymousSession.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Sessions 11 | { 12 | internal class AnonymousSession : UserSession 13 | { 14 | public AnonymousSession() 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /TS3AudioBot/Sessions/ApiToken.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TSLib.Helper; 12 | 13 | namespace TS3AudioBot.Sessions 14 | { 15 | internal class ApiToken 16 | { 17 | public const int TokenLen = 32; 18 | public static readonly TimeSpan DefaultTokenTimeout = TimeSpan.MaxValue; 19 | 20 | public string Value { get; } 21 | public DateTime Timeout { get; } 22 | public bool ApiTokenActive => Tools.Now <= Timeout; 23 | 24 | public ApiToken(string value, DateTime timeout) 25 | { 26 | Value = value; 27 | Timeout = timeout; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TS3AudioBot/Sessions/SessionManager.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | using TSLib; 12 | 13 | namespace TS3AudioBot.Sessions 14 | { 15 | /// Management for clients talking with the bot. 16 | public class SessionManager 17 | { 18 | private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); 19 | 20 | // Map: Id => UserSession 21 | private readonly Dictionary openSessions = new Dictionary(); 22 | 23 | public UserSession GetOrCreateSession(ClientId clientId) 24 | { 25 | lock (openSessions) 26 | { 27 | if (openSessions.TryGetValue(clientId, out var session)) 28 | return session; 29 | 30 | Log.Debug("ClientId {0} created session with the bot", clientId); 31 | session = new UserSession(); 32 | openSessions.Add(clientId, session); 33 | return session; 34 | } 35 | } 36 | 37 | public UserSession? GetSession(ClientId id) 38 | { 39 | lock (openSessions) 40 | { 41 | if (openSessions.TryGetValue(id, out var session)) 42 | return session; 43 | else 44 | return null; 45 | } 46 | } 47 | 48 | public void RemoveSession(ClientId id) 49 | { 50 | lock (openSessions) 51 | { 52 | openSessions.Remove(id); 53 | } 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /TS3AudioBot/Upgrader.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TS3AudioBot.Dependency; 11 | 12 | namespace TS3AudioBot 13 | { 14 | internal static class Upgrader 15 | { 16 | private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger(); 17 | private const string CoreTable = "core"; 18 | private const int CurrentVersion = 1; 19 | 20 | public static void PerformUpgrades(CoreInjector injector) 21 | { 22 | var database = injector.GetModuleOrThrow(); 23 | var meta = database.GetMetaData(CoreTable); 24 | 25 | void Advance(int version, string? explanation) 26 | { 27 | meta.Version = version; 28 | database.UpdateMetaData(meta); 29 | if (explanation != null) 30 | Log.Info("Upgrading data to ver {0}. {1}", version, explanation); 31 | } 32 | 33 | switch (meta.Version) 34 | { 35 | case 0: 36 | // Case 0 should always jump to the lastest version, since it gets created on first start. 37 | Advance(CurrentVersion, null); 38 | goto case CurrentVersion; 39 | 40 | case CurrentVersion: 41 | break; 42 | 43 | default: 44 | Log.Warn("It seems that you downgraded your TS3AB version. " + 45 | "Due to automatic upgrades some stuff might not work anymore, be advised. " + 46 | "It is recommended to backup data before upgrading to unstable/beta builds if you intend to downgrade again."); 47 | break; 48 | } 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/ApiCall.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Net; 12 | using TSLib; 13 | 14 | namespace TS3AudioBot.Web.Api 15 | { 16 | public class ApiCall : InvokerData 17 | { 18 | public string? Token { get; set; } 19 | public IPAddress? IpAddress { get; set; } 20 | public Uri? RequestUrl { get; set; } 21 | public string? Body { get; set; } 22 | 23 | public static ApiCall CreateAnonymous() => new ApiCall(Uid.Anonymous); 24 | 25 | public ApiCall(Uid clientUid, IPAddress? ipAddress = null, Uri? requestUrl = null, string? token = null, string? body = null) : base(clientUid) 26 | { 27 | Token = token; 28 | IpAddress = ipAddress; 29 | RequestUrl = requestUrl; 30 | Body = body; 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/DataStream.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Microsoft.AspNetCore.Http; 11 | using System; 12 | using System.Threading.Tasks; 13 | 14 | namespace TS3AudioBot.Web.Api 15 | { 16 | public class DataStream 17 | { 18 | private readonly Func writeFunc; 19 | 20 | public DataStream(Func writeFunc) 21 | { 22 | this.writeFunc = writeFunc; 23 | } 24 | 25 | public Task WriteOut(HttpResponse response) => writeFunc(response); 26 | 27 | public override string? ToString() => null; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/JsonArray.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | 13 | namespace TS3AudioBot.Web.Api 14 | { 15 | public class JsonArray : JsonValue> 16 | { 17 | public JsonArray(IList value, string msg) : base(value, msg) { } 18 | public JsonArray(IList value, Func, string>? asString = null) 19 | : base(value, asString) 20 | { } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/JsonEmpty.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Web.Api 11 | { 12 | public class JsonEmpty : JsonObject 13 | { 14 | private readonly string message; 15 | public JsonEmpty(string msg) { message = msg; } 16 | 17 | public override object GetSerializeObject() => string.Empty; 18 | public override string Serialize() => string.Empty; 19 | public override string ToString() => message; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/JsonError.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | using TS3AudioBot.CommandSystem; 12 | 13 | namespace TS3AudioBot.Web.Api 14 | { 15 | public class JsonError : JsonObject 16 | { 17 | private static readonly JsonSerializerSettings ErrorSerializeSettings = new JsonSerializerSettings 18 | { 19 | NullValueHandling = NullValueHandling.Ignore, 20 | }; 21 | 22 | private readonly CommandExceptionReason reason; 23 | public int ErrorCode => (int)reason; 24 | public string ErrorName => reason.ToString(); 25 | public string ErrorMessage { get; } 26 | public string? HelpMessage { get; set; } 27 | public string? HelpLink { get; set; } 28 | 29 | public JsonError(string msg, CommandExceptionReason reason) 30 | { 31 | ErrorMessage = msg; 32 | this.reason = reason; 33 | } 34 | 35 | public override string Serialize() => JsonConvert.SerializeObject(GetSerializeObject(), ErrorSerializeSettings); 36 | public override string ToString() => ErrorMessage; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/JsonObject.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | using TS3AudioBot.CommandSystem.CommandResults; 12 | using TS3AudioBot.Helper; 13 | 14 | namespace TS3AudioBot.Web.Api 15 | { 16 | public abstract class JsonObject : IWrappedResult 17 | { 18 | private static readonly JsonSerializerSettings DefaultSettigs = new JsonSerializerSettings(); 19 | 20 | static JsonObject() 21 | { 22 | DefaultSettigs.Converters.Add(new IJsonSerializableConverter()); 23 | DefaultSettigs.Converters.Add(new TimeSpanConverter()); 24 | } 25 | 26 | protected JsonObject() { } 27 | 28 | object? IWrappedResult.Content => GetSerializeObject(); 29 | public virtual object GetSerializeObject() => this; 30 | public virtual string Serialize() => JsonConvert.SerializeObject(GetSerializeObject(), DefaultSettigs); 31 | public override abstract string ToString(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Api/TimeSpanConverter.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | using System; 12 | 13 | namespace TS3AudioBot.Web.Api 14 | { 15 | internal class TimeSpanConverter : JsonConverter 16 | { 17 | public override void WriteJson(JsonWriter writer, TimeSpan value, JsonSerializer serializer) 18 | { 19 | writer.WriteValue(value.TotalSeconds); 20 | } 21 | 22 | public override TimeSpan ReadJson(JsonReader reader, Type objectType, TimeSpan existingValue, bool hasExistingValue, JsonSerializer serializer) 23 | { 24 | float secs = (float?)reader.Value ?? 0; 25 | return TimeSpan.FromSeconds(secs); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Model/CurrentSongInfo.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | using System; 12 | 13 | namespace TS3AudioBot.Web.Model 14 | { 15 | public class CurrentSongInfo : PlaylistItemGetData 16 | { 17 | [JsonProperty(PropertyName = "Position")] 18 | public TimeSpan Position { get; set; } 19 | [JsonProperty(PropertyName = "Length")] 20 | public TimeSpan Length { get; set; } 21 | [JsonProperty(PropertyName = "Paused")] 22 | public bool Paused { get; set; } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Model/PlaylistInfo.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | 12 | namespace TS3AudioBot.Web.Model 13 | { 14 | public class PlaylistInfo 15 | { 16 | // TODO better names 17 | [JsonProperty(PropertyName = "Id")] 18 | public string Id { get; set; } 19 | [JsonProperty(PropertyName = "Title")] 20 | public string Title { get; set; } 21 | 22 | /// How many songs are in the entire playlist 23 | [JsonProperty(PropertyName = "SongCount")] 24 | public int SongCount { get; set; } 25 | /// From which index the itemization begins. 26 | [JsonProperty(PropertyName = "DisplayOffset")] 27 | public int DisplayOffset { get; set; } 28 | /// The playlist items for the request. 29 | /// This might only be a part of the entire playlist. 30 | /// Check for the entire count. 31 | [JsonProperty(PropertyName = "Items", NullValueHandling = NullValueHandling.Ignore)] 32 | public PlaylistItemGetData[]? Items { get; set; } 33 | 34 | public PlaylistInfo(string id, string title) 35 | { 36 | Id = id; 37 | Title = title; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Model/PlaylistItemGetData.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TS3AudioBot.Web.Model 11 | { 12 | public class PlaylistItemGetData 13 | { 14 | // Optional, useful when adding a single element to a list 15 | // public int? Index { get; set; } 16 | public string? Link { get; set; } 17 | public string? Title { get; set; } 18 | public string? AudioType { get; set; } 19 | // Link 20 | // AlbumCover 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TS3AudioBot/Web/Model/QueueInfo.cs: -------------------------------------------------------------------------------- 1 | // TS3AudioBot - An advanced Musicbot for Teamspeak 3 2 | // Copyright (C) 2017 TS3AudioBot contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using Newtonsoft.Json; 11 | 12 | namespace TS3AudioBot.Web.Model 13 | { 14 | public class QueueInfo : PlaylistInfo 15 | { 16 | [JsonProperty(PropertyName = "PlaybackIndex")] 17 | public int PlaybackIndex { get; set; } 18 | 19 | public QueueInfo(string id, string title) : base(id, title) 20 | { 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TS3AudioBot/build.csx: -------------------------------------------------------------------------------- 1 | #r "nuget: SimpleExec, 6.2.0" 2 | #r "nuget: Newtonsoft.Json, 12.0.3" 3 | 4 | using Newtonsoft.Json; 5 | using static SimpleExec.Command; 6 | 7 | if (Args.Count == 0) { 8 | WriteLine("This script is itended to be used in the build pipeline"); 9 | return 1; 10 | } 11 | 12 | string outFile = Args[0]; 13 | string buildConfig = Args[1]; 14 | 15 | string json = Read("dotnet", "gitversion"); 16 | 17 | var version = JsonConvert.DeserializeAnonymousType(json, new { 18 | FullSemVer = "", 19 | BranchName = "", 20 | Sha = "", 21 | 22 | AssemblySemVer = "", 23 | AssemblySemFileVer = "", 24 | InformationalVersion = "", 25 | }); 26 | 27 | var genFile = $@" 28 | [assembly: System.Reflection.AssemblyVersion(""{version.AssemblySemVer}"")] 29 | [assembly: System.Reflection.AssemblyFileVersion(""{version.AssemblySemFileVer}"")] 30 | [assembly: System.Reflection.AssemblyInformationalVersion(""{version.InformationalVersion}"")] 31 | 32 | namespace TS3AudioBot.Environment 33 | {{ 34 | partial class BuildData {{ 35 | partial void GetDataInternal() {{ 36 | this.Version = ""{version.FullSemVer}""; 37 | this.Branch = ""{version.BranchName}""; 38 | this.CommitSha = ""{version.Sha}""; 39 | 40 | this.BuildConfiguration = ""{buildConfig}""; 41 | }} 42 | }} 43 | }} 44 | "; 45 | 46 | Console.WriteLine("Generated Version {0}", version.FullSemVer); 47 | var writeFull = Path.GetFullPath(outFile); 48 | //WriteLine("Writing to {0}", writeFull); 49 | File.WriteAllText(writeFull, genFile); 50 | -------------------------------------------------------------------------------- /TS3AudioBot/lib/x64/libopus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TS3AudioBot/lib/x64/libopus.dll -------------------------------------------------------------------------------- /TS3AudioBot/lib/x86/libopus.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TS3AudioBot/lib/x86/libopus.dll -------------------------------------------------------------------------------- /TSLib/Audio/AudioMeta.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Collections.Generic; 11 | 12 | namespace TSLib.Audio 13 | { 14 | public class Meta 15 | { 16 | public Codec? Codec { get; set; } 17 | public MetaIn In; 18 | public MetaOut? Out { get; set; } 19 | //public PipeControl Control { get; set; } 20 | } 21 | 22 | public struct MetaIn 23 | { 24 | public ClientId Sender { get; set; } 25 | public bool Whisper { get; set; } 26 | } 27 | 28 | public class MetaOut 29 | { 30 | public TargetSendMode SendMode { get; set; } 31 | public ulong TargetId { get; set; } 32 | public GroupWhisperTarget GroupWhisperTarget { get; set; } 33 | public GroupWhisperType GroupWhisperType { get; set; } 34 | public IReadOnlyList? ChannelIds { get; set; } 35 | public IReadOnlyList? ClientIds { get; set; } 36 | } 37 | 38 | public enum TargetSendMode 39 | { 40 | None, 41 | Voice, 42 | Whisper, 43 | WhisperGroup, 44 | } 45 | 46 | public enum PipeControl 47 | { 48 | Data, 49 | EmptyTick, 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TSLib/Audio/AudioPacketReader.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Buffers.Binary; 12 | 13 | namespace TSLib.Audio 14 | { 15 | public class AudioPacketReader : IAudioPipe 16 | { 17 | public bool Active => OutStream?.Active ?? false; 18 | public IAudioPassiveConsumer? OutStream { get; set; } 19 | 20 | public void Write(Span data, Meta? meta) 21 | { 22 | if (OutStream is null || meta is null) 23 | return; 24 | 25 | // End of stream is signalled with no data or a single byte. 26 | // The header has 5 bytes, so check for 6. 27 | if (data.Length < 6) 28 | return; 29 | 30 | // Skip [0,2) Voice Packet Id for now 31 | // TODO add packet id order checking 32 | // TODO add defragment start 33 | meta.In.Sender = (ClientId)BinaryPrimitives.ReadUInt16BigEndian(data.Slice(2, 2)); 34 | meta.Codec = (Codec)data[4]; 35 | OutStream?.Write(data.Slice(5), meta); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TSLib/Audio/AudioPipeExtensions.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Audio 13 | { 14 | public static class AudioPipeExtensions 15 | { 16 | public static T Chain(this IAudioActiveProducer producer, T addConsumer) where T : IAudioPassiveConsumer 17 | { 18 | if (producer.OutStream is null) 19 | { 20 | producer.OutStream = addConsumer; 21 | } 22 | else if (producer.OutStream is PassiveSplitterPipe splitter) 23 | { 24 | splitter.Add(addConsumer); 25 | } 26 | else 27 | { 28 | splitter = new PassiveSplitterPipe(); 29 | splitter.Add(addConsumer); 30 | splitter.Add(producer.OutStream); 31 | producer.OutStream = splitter; 32 | } 33 | return addConsumer; 34 | } 35 | 36 | public static T Chain(this IAudioActiveProducer producer, Action? init = null) where T : IAudioPassiveConsumer, new() 37 | { 38 | var addConsumer = new T(); 39 | init?.Invoke(addConsumer); 40 | return producer.Chain(addConsumer); 41 | } 42 | 43 | public static T Into(this IAudioPassiveProducer producer, T reader) where T : IAudioActiveConsumer 44 | { 45 | reader.InStream = producer; 46 | return reader; 47 | } 48 | 49 | public static T Into(this IAudioPassiveProducer producer, Action? init = null) where T : IAudioActiveConsumer, new() 50 | { 51 | var reader = new T(); 52 | init?.Invoke(reader); 53 | return producer.Into(reader); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /TSLib/Audio/AudioTools.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.Runtime.InteropServices; 11 | 12 | namespace TSLib.Audio 13 | { 14 | public static class AudioTools 15 | { 16 | public static bool TryMonoToStereo(byte[] pcm, ref int length) 17 | { 18 | if (length / 2 >= pcm.Length) 19 | return false; 20 | 21 | var shortArr = MemoryMarshal.Cast(pcm); 22 | 23 | for (int i = (length / 2) - 1; i >= 0; i--) 24 | { 25 | shortArr[i * 2 + 0] = shortArr[i]; 26 | shortArr[i * 2 + 1] = shortArr[i]; 27 | } 28 | 29 | length *= 2; 30 | 31 | return true; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /TSLib/Audio/CheckActivePipe.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Audio 13 | { 14 | public class CheckActivePipe : IAudioPipe 15 | { 16 | public bool Active => OutStream?.Active ?? false; 17 | public IAudioPassiveConsumer? OutStream { get; set; } 18 | 19 | public void Write(Span data, Meta? meta) 20 | { 21 | if (OutStream is null || data.IsEmpty || !Active) 22 | return; 23 | 24 | OutStream?.Write(data, meta); 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /TSLib/Audio/Opus/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2012 John Carruthers 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining 4 | a copy of this software and associated documentation files (the 5 | "Software"), to deal in the Software without restriction, including 6 | without limitation the rights to use, copy, modify, merge, publish, 7 | distribute, sublicense, and/or sell copies of the Software, and to 8 | permit persons to whom the Software is furnished to do so, subject to 9 | the following conditions: 10 | 11 | The above copyright notice and this permission notice shall be 12 | included in all copies or substantial portions of the Software. 13 | 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /TSLib/Audio/Opus/README: -------------------------------------------------------------------------------- 1 | The Opus.NET library was cloned from: 2 | https://github.com/JohnACarruthers/Opus.NET 3 | 4 | The LICENSE document in this folder applies to all files in this folder. 5 | All other files and projects within this solution are unaffected by this. 6 | -------------------------------------------------------------------------------- /TSLib/Audio/StreamAudioProducer.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System.IO; 11 | 12 | namespace TSLib.Audio 13 | { 14 | public class StreamAudioProducer : IAudioPassiveProducer 15 | { 16 | private readonly Stream stream; 17 | 18 | public StreamAudioProducer(Stream stream) { this.stream = stream; } 19 | 20 | public int Read(byte[] buffer, int offset, int length, out Meta? meta) 21 | { 22 | meta = default; 23 | return stream.Read(buffer, offset, length); 24 | } 25 | 26 | public void Dispose() => stream.Dispose(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /TSLib/Commands/CommandMultiParameter.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TSLib.Commands 11 | { 12 | /// Represents an array of data. Will be expanded to a pipe seperated list when sent. 13 | /// Multiple will be merged automatically but will need the same array length. 14 | public sealed partial class CommandMultiParameter : ICommandPart 15 | { 16 | public string Key { get; } 17 | public string[] Values { get; } 18 | public CommandPartType Type => CommandPartType.MultiParameter; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /TSLib/Commands/CommandOption.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Linq; 12 | using System.Text; 13 | using TSLib.Helper; 14 | 15 | namespace TSLib.Commands 16 | { 17 | /// Command options which will be added with "-name" at the and. 18 | public class CommandOption : ICommandPart 19 | { 20 | public string Value { get; } 21 | public CommandPartType Type => CommandPartType.Option; 22 | 23 | public CommandOption(string name) { Value = string.Concat(" -", name); } 24 | /// Creates one or many options from the enum. 25 | /// The enum must be a flag list which will be expanded. 26 | /// The name of each set enum flag will be used as the option name. 27 | /// 28 | public CommandOption(Enum values) 29 | { 30 | var strb = new StringBuilder(); 31 | foreach (var enu in values.GetFlags().Select(enu => enu.ToString())) 32 | strb.Append(" -").Append(enu); 33 | Value = strb.ToString(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TSLib/Commands/ICommandPart.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TSLib.Commands 11 | { 12 | public interface ICommandPart 13 | { 14 | CommandPartType Type { get; } 15 | } 16 | 17 | public enum CommandPartType 18 | { 19 | SingleParameter, 20 | MultiParameter, 21 | Option, 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TSLib/DisconnectEventArgs.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using TSLib.Messages; 12 | 13 | namespace TSLib 14 | { 15 | public class DisconnectEventArgs : EventArgs 16 | { 17 | public Reason ExitReason { get; } 18 | public CommandError? Error { get; } 19 | 20 | public DisconnectEventArgs(Reason exitReason, CommandError? error = null) 21 | { 22 | ExitReason = exitReason; 23 | Error = error; 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /TSLib/Full/Book/SpecialTypes.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Full.Book 13 | { 14 | public struct MaxClients 15 | { 16 | public ushort Count { get; internal set; } 17 | public MaxClientsKind LimitKind { get; internal set; } 18 | } 19 | 20 | public enum MaxClientsKind 21 | { 22 | Unlimited, 23 | Inherited, 24 | Limited, 25 | } 26 | 27 | public enum ChannelType 28 | { 29 | Temporary, 30 | SemiPermanent, 31 | Permanent, 32 | } 33 | 34 | public struct TalkPowerRequest 35 | { 36 | public DateTime Time { get; internal set; } 37 | public string Message { get; internal set; } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /TSLib/Full/PacketType.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Full 13 | { 14 | public enum PacketType : byte 15 | { 16 | Voice = 0x0, 17 | VoiceWhisper = 0x1, 18 | Command = 0x2, 19 | CommandLow = 0x3, 20 | Ping = 0x4, 21 | Pong = 0x5, 22 | Ack = 0x6, 23 | AckLow = 0x7, 24 | Init1 = 0x8, 25 | } 26 | 27 | [Flags] 28 | public enum PacketFlags : byte 29 | { 30 | None = 0x0, 31 | Fragmented = 0x10, 32 | Newprotocol = 0x20, 33 | Compressed = 0x40, 34 | Unencrypted = 0x80, 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TSLib/Generated/BookParser.ttinclude: -------------------------------------------------------------------------------- 1 | <#@ include file="Util.ttinclude" once="true" #> 2 | <#+ 3 | public class BookDeclarations 4 | { 5 | public static BookDeclarations Parse(string file) 6 | { 7 | var toml = Nett.Toml.ReadFile(file); 8 | 9 | // transfer all optional get/set confs 10 | foreach (var struc in toml.@struct) 11 | { 12 | foreach (var prop in struc.properties) 13 | { 14 | prop.get ??= struc.accessor.get; 15 | prop.set ??= struc.accessor.set; 16 | } 17 | } 18 | 19 | return toml; 20 | } 21 | 22 | public Struct[] @struct { get; set; } 23 | 24 | public class Struct 25 | { 26 | public string name { get; set; } 27 | public Id[] id { get; set; } 28 | public string doc { get; set; } 29 | public Accessor accessor { get; set; } 30 | public Property[] properties { get; set; } 31 | } 32 | 33 | public class Id 34 | { 35 | public string @struct { get; set; } 36 | public string prop { get; set; } 37 | } 38 | 39 | public class Accessor 40 | { 41 | public bool get { get; set; } 42 | public bool set { get; set; } 43 | } 44 | 45 | public class Property 46 | { 47 | public string name { get; set; } 48 | public string type { get; set; } 49 | public bool? get { get; set; } 50 | public bool? set { get; set; } 51 | public bool? opt { get; set; } 52 | public string mod { get; set; } 53 | public string key { get; set; } 54 | } 55 | } 56 | #> -------------------------------------------------------------------------------- /TSLib/Generated/ErrorParser.ttinclude: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ assembly name="Microsoft.VisualBasic" #> 3 | <#@ import namespace="System.Linq" #> 4 | <#@ import namespace="System.Collections.Generic" #> 5 | <#@ import namespace="Microsoft.VisualBasic.FileIO" #> 6 | <# 7 | List ParseErrors() 8 | { 9 | string declFilePath = Host.ResolvePath("../Declarations/Errors.csv"); 10 | var data = new List(); 11 | using (TextFieldParser parser = new TextFieldParser(declFilePath)) 12 | { 13 | parser.TextFieldType = FieldType.Delimited; 14 | parser.SetDelimiters(","); 15 | while (!parser.EndOfData) { 16 | var line = parser.ReadFields(); 17 | data.Add(new GenError { Doc = line[1], Name = line[0], Value = line[2] }); 18 | } 19 | } 20 | data.RemoveAt(0); 21 | return data; 22 | } 23 | #><#+ 24 | class GenError 25 | { 26 | public string Doc { get; set; } 27 | public string Name { get; set; } 28 | public string Value { get; set; } 29 | } 30 | #> -------------------------------------------------------------------------------- /TSLib/Generated/M2BParser.ttinclude: -------------------------------------------------------------------------------- 1 | <#@ include file="Util.ttinclude" once="true" #> 2 | <#+ 3 | public class M2BDeclarations 4 | { 5 | public static M2BDeclarations Parse(string file, Messages msgs, BookDeclarations book) 6 | { 7 | var toml = Nett.Toml.ReadFile(file); 8 | 9 | foreach (var rule in toml.rule) 10 | { 11 | rule.properties ??= new List(); 12 | 13 | // Add implicit move operations 14 | var msg = msgs.GetOrderedMsg().First(x => x.name == rule.from); 15 | var msgProps = msg.attributes.Select(x => msgs.GetField(x).fld); 16 | var bookItem = book.@struct.First(x => x.name == rule.to); 17 | var funcResults = new HashSet(rule.properties.Where(x => x.tolist != null).SelectMany(x => x.tolist)); 18 | 19 | foreach (var prop in msgProps) 20 | { 21 | if (funcResults.Contains(prop.pretty)) 22 | continue; 23 | 24 | if (bookItem.properties.Any(x => x.name == prop.pretty)) 25 | { 26 | // chek already exists 27 | 28 | rule.properties.Add(new M2BPropMove { 29 | from = prop.pretty, 30 | to = prop.pretty, 31 | }); 32 | } 33 | } 34 | } 35 | 36 | return toml; 37 | } 38 | 39 | public M2BRule[] rule { get; set; } 40 | 41 | public class M2BRule 42 | { 43 | public string from { get; set; } 44 | public string[] id { get; set; } 45 | public string to { get; set; } 46 | public string operation { get; set; } 47 | public List properties { get; set; } 48 | } 49 | 50 | public class M2BPropMove 51 | { 52 | public string from { get; set; } 53 | public string to { get; set; } 54 | public string function { get; set; } 55 | public string[] tolist { get; set; } 56 | public string operation { get; set; } 57 | } 58 | } 59 | #> -------------------------------------------------------------------------------- /TSLib/Generated/NotificationUtil.ttinclude: -------------------------------------------------------------------------------- 1 | <#+ 2 | HashSet sharedNotifications = new HashSet { 3 | "ChannelCreated", 4 | "ChannelDeleted", 5 | "ChannelChanged", 6 | "ChannelEdited", 7 | "ChannelMoved", 8 | "ChannelPasswordChanged", 9 | "ClientEnterView", 10 | "ClientLeftView", 11 | "ClientMoved", 12 | "ServerEdited", 13 | "TextMessage", 14 | "TokenUsed", 15 | }; 16 | 17 | public void GenNtfyDecls(IEnumerable enu, bool root = false) { 18 | PushIndent("\t\t"); 19 | WriteLine(""); 20 | var modifier = root ? " abstract" : " override"; 21 | 22 | foreach(var ntfy in enu) 23 | { 24 | Write("public"); 25 | if(sharedNotifications.Contains(ntfy.name)) 26 | Write(modifier); 27 | WriteLine($" event NotifyEventHandler<{ntfy.name}>? On{ntfy.name};"); 28 | 29 | Write("public"); 30 | if(sharedNotifications.Contains(ntfy.name)) 31 | Write(modifier); 32 | WriteLine($" event EventHandler<{ntfy.name}>? OnEach{ntfy.name};"); 33 | } 34 | 35 | PopIndent(); 36 | } 37 | #> -------------------------------------------------------------------------------- /TSLib/Generated/TsErrorCode.tt: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | // 10 | 11 | <#@ template debug="false" hostspecific="true" language="C#" #> 12 | <#@ include file="ErrorParser.ttinclude" once="true" #> 13 | <#@ output extension=".cs" #> 14 | <# var errors = ParseErrors(); #> 15 | 16 | namespace TSLib 17 | { 18 | // Source: http://forum.teamspeak.com/threads/102276-Server-query-error-id-list 19 | public enum TsErrorCode : uint 20 | { 21 | // ReSharper disable InconsistentNaming, UnusedMember.Global<# foreach (var line in errors) { #> 22 | /// <#= line.Doc #> 23 | <#= line.Name #> = <#= line.Value #>,<# } #> 24 | /// For own custom errors 25 | custom_error = 0xFFFF, 26 | // ReSharper enable InconsistentNaming, UnusedMember.Global 27 | } 28 | } -------------------------------------------------------------------------------- /TSLib/Generated/Util.ttinclude: -------------------------------------------------------------------------------- 1 | <#@ assembly name="System.Core" #> 2 | <#@ assembly name="%userprofile%/.nuget/packages/nett/0.13.0/lib/Net40/Nett.dll" #> 3 | <#+ 4 | public void Warn(string _warn) { WriteLine($"#warning {_warn}"); } 5 | 6 | const string ConversionSet = 7 | @"#pragma warning disable CS8019 // Ignore unused imports 8 | using i8 = System.SByte; 9 | using u8 = System.Byte; 10 | using i16 = System.Int16; 11 | using u16 = System.UInt16; 12 | using i32 = System.Int32; 13 | using u32 = System.UInt32; 14 | using i64 = System.Int64; 15 | using u64 = System.UInt64; 16 | using f32 = System.Single; 17 | using f64 = System.Double; 18 | using str = System.String; 19 | 20 | using DateTime = System.DateTime; 21 | using Duration = System.TimeSpan; 22 | using DurationSeconds = System.TimeSpan; 23 | using DurationMilliseconds = System.TimeSpan; 24 | using SocketAddr = System.String; 25 | using IpAddr = System.String; 26 | using Ts3ErrorCode = TSLib.TsErrorCode; 27 | using Ts3Permission = TSLib.TsPermission; 28 | 29 | using IconHash = System.Int32; 30 | using ConnectionId = System.UInt32; 31 | using EccKeyPubP256 = TSLib.Uid; 32 | #pragma warning restore CS8019"; 33 | #> -------------------------------------------------------------------------------- /TSLib/Helper/AsyncEventHandler.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Threading.Tasks; 4 | 5 | namespace TSLib.Helper 6 | { 7 | // Normal EventHandler: 8 | // public delegate void EventHandler(object? sender, EventArgs e); 9 | 10 | public delegate Task AsyncEventHandler(object? sender, EventArgs e); 11 | public delegate Task AsyncEventHandler(object? sender, T value); 12 | 13 | public static class AsyncEventExtensions 14 | { 15 | public static Task InvokeAsync(this AsyncEventHandler? ev, object? sender, T value) 16 | { 17 | if (ev == null) 18 | return Task.CompletedTask; 19 | 20 | var invList = ev.GetInvocationList(); 21 | if (invList.Length == 1) 22 | { 23 | return ((AsyncEventHandler)invList[0]).Invoke(sender, value); 24 | } 25 | 26 | return Task.WhenAll(invList.Select(func => ((AsyncEventHandler)func).Invoke(sender, value))); 27 | } 28 | 29 | public static Task InvokeAsync(this AsyncEventHandler? ev, object? sender) 30 | => InvokeAsync(ev, sender, EventArgs.Empty); 31 | public static Task InvokeAsync(this AsyncEventHandler? ev, object? sender, EventArgs e) 32 | { 33 | if (ev == null) 34 | return Task.CompletedTask; 35 | 36 | var invList = ev.GetInvocationList(); 37 | if (invList.Length == 1) 38 | { 39 | return ((AsyncEventHandler)invList[0]).Invoke(sender, e); 40 | } 41 | 42 | return Task.WhenAll(invList.Select(func => ((AsyncEventHandler)func).Invoke(sender, e))); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /TSLib/Helper/DebugUtil.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Linq; 12 | 13 | namespace TSLib.Helper 14 | { 15 | internal static class DebugUtil 16 | { 17 | public static string DebugToHex(byte[] bytes) => bytes is null ? "" : DebugToHex(bytes.AsSpan()); 18 | 19 | public static string DebugToHex(ReadOnlySpan bytes) 20 | { 21 | var c = new char[bytes.Length * 3]; 22 | for (int bx = 0, cx = 0; bx < bytes.Length; ++bx, ++cx) 23 | { 24 | var b = (byte)(bytes[bx] >> 4); 25 | c[cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); 26 | 27 | b = (byte)(bytes[bx] & 0x0F); 28 | c[++cx] = (char)(b > 9 ? b - 10 + 'A' : b + '0'); 29 | c[++cx] = ' '; 30 | } 31 | return new string(c); 32 | } 33 | 34 | public static byte[] DebugFromHex(string hex) 35 | => hex.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries) 36 | .Select(x => Convert.ToByte(x, 16)).ToArray(); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /TSLib/Helper/LogId.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Helper 13 | { 14 | public readonly struct Id : IEquatable 15 | { 16 | public static readonly Id Null = new Id(-1); 17 | 18 | public int Value { get; } 19 | 20 | public Id(int id) 21 | { 22 | Value = id; 23 | } 24 | 25 | public static implicit operator int(Id id) => id.Value; 26 | 27 | public override string ToString() => Value.ToString(); 28 | 29 | public override bool Equals(object? obj) => obj is Id id && Equals(id); 30 | public bool Equals(Id other) => Value == other.Value; 31 | public override int GetHashCode() => Value; 32 | 33 | public static bool operator ==(Id id, Id other) => id.Value == other.Value; 34 | public static bool operator !=(Id id, Id other) => id.Value != other.Value; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /TSLib/Helper/MissingEnumCaseException.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Runtime.Serialization; 12 | 13 | namespace TSLib.Helper 14 | { 15 | [Serializable] 16 | public sealed class MissingEnumCaseException : Exception 17 | { 18 | public MissingEnumCaseException(string enumTypeName, string valueName) : base($"The switch does not handle the value \"{valueName}\" from \"{enumTypeName}\".") { } 19 | public MissingEnumCaseException(string message, Exception inner) : base(message, inner) { } 20 | private MissingEnumCaseException(SerializationInfo info, StreamingContext context) : base(info, context) { } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TSLib/Helper/SpanExtensions.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Helper 13 | { 14 | public static class SpanExtensions 15 | { 16 | public static string NewUtf8String(this ReadOnlySpan span) 17 | { 18 | #if NETSTANDARD2_1 || NETCOREAPP3_1 19 | return Tools.Utf8Encoder.GetString(span); 20 | #else 21 | return Tools.Utf8Encoder.GetString(span.ToArray()); 22 | #endif 23 | } 24 | 25 | public static string NewUtf8String(this Span span) => ((ReadOnlySpan)span).NewUtf8String(); 26 | 27 | public static ReadOnlySpan Trim(this ReadOnlySpan span, byte elem) => span.TrimStart(elem).TrimEnd(elem); 28 | 29 | public static ReadOnlySpan TrimStart(this ReadOnlySpan span, byte elem) 30 | { 31 | int start = 0; 32 | for (; start < span.Length; start++) 33 | { 34 | if (span[start] != elem) 35 | break; 36 | } 37 | return span.Slice(start); 38 | } 39 | 40 | public static ReadOnlySpan TrimEnd(this ReadOnlySpan span, byte elem) 41 | { 42 | int end = span.Length - 1; 43 | for (; end >= 0; end--) 44 | { 45 | if (span[end] != elem) 46 | break; 47 | } 48 | return span.Slice(0, end + 1); 49 | } 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /TSLib/Helper/SpanSplitter.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Runtime.CompilerServices; 12 | 13 | namespace TSLib.Helper 14 | { 15 | internal struct SpanSplitter where T : IEquatable 16 | { 17 | public bool HasNext => NextIndex >= 0; 18 | public int NextIndex { get; private set; } 19 | private T splitchar; 20 | 21 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 22 | public void First(in ReadOnlySpan span, T split) 23 | { 24 | splitchar = split; 25 | NextIndex = span.IndexOf(split); 26 | } 27 | 28 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 | public ReadOnlySpan Next(in ReadOnlySpan current) 30 | { 31 | if (!HasNext) 32 | throw new InvalidOperationException("No next element in span split"); 33 | var ret = current.Slice(NextIndex + 1); 34 | NextIndex = ret.IndexOf(splitchar); 35 | return ret; 36 | } 37 | 38 | [MethodImpl(MethodImplOptions.AggressiveInlining)] 39 | public ReadOnlySpan Trim(in ReadOnlySpan current) => HasNext ? current.Slice(0, NextIndex) : current; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /TSLib/LazyNotification.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib.Messages; 11 | 12 | namespace TSLib 13 | { 14 | public readonly struct LazyNotification 15 | { 16 | public readonly INotification[] Notifications; 17 | public readonly NotificationType NotifyType; 18 | 19 | public LazyNotification(INotification[] notifications, NotificationType notifyType) 20 | { 21 | Notifications = notifications; 22 | NotifyType = notifyType; 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /TSLib/Messages/BaseTypes.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | using System.Collections.Generic; 12 | 13 | namespace TSLib.Messages 14 | { 15 | public interface IMessage 16 | { 17 | void SetField(string name, ReadOnlySpan value, Deserializer ser); 18 | void Expand(IMessage[] to, IEnumerable flds); 19 | } 20 | 21 | public interface INotification : IMessage 22 | { 23 | NotificationType NotifyType { get; } 24 | } 25 | 26 | public interface IResponse : IMessage 27 | { 28 | string? ReturnCode { get; set; } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /TSLib/Messages/MessageAdditions.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | namespace TSLib.Messages 11 | { 12 | public interface IChannelCreateResponse 13 | { 14 | ChannelId ChannelId { get; set; } 15 | } 16 | 17 | partial class ChannelCreateResponse : IChannelCreateResponse { } 18 | 19 | partial class ChannelCreated : IChannelCreateResponse { } 20 | } 21 | -------------------------------------------------------------------------------- /TSLib/Messages/PermissionTransform.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Messages 13 | { 14 | public interface IPermissionTransform 15 | { 16 | ushort GetId(TsPermission name); 17 | TsPermission GetName(ushort id); 18 | } 19 | 20 | public class DummyPermissionTransform : IPermissionTransform 21 | { 22 | public static readonly IPermissionTransform Instance = new DummyPermissionTransform(); 23 | 24 | public ushort GetId(TsPermission name) => 0; 25 | public TsPermission GetName(ushort id) => TsPermission.undefined; 26 | } 27 | 28 | public class TablePermissionTransform : IPermissionTransform 29 | { 30 | private readonly TsPermission[] nameTable; 31 | private readonly ushort[] idTable; 32 | 33 | public TablePermissionTransform(TsPermission[] nameTable) 34 | { 35 | this.nameTable = nameTable; 36 | idTable = new ushort[Enum.GetValues(typeof(TsPermission)).Length]; 37 | for (ushort i = 0; i < nameTable.Length; i++) 38 | { 39 | idTable[(int)nameTable[i]] = i; 40 | } 41 | } 42 | 43 | public ushort GetId(TsPermission name) => (int)name < idTable.Length ? idTable[(int)name] : (ushort)0; 44 | public TsPermission GetName(ushort id) => id < nameTable.Length ? nameTable[id] : TsPermission.undefined; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /TSLib/Properties.cs: -------------------------------------------------------------------------------- 1 | using System.Runtime.CompilerServices; 2 | 3 | [assembly: InternalsVisibleTo("TS3ABotUnitTests")] 4 | -------------------------------------------------------------------------------- /TSLib/ReSpeak.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/TSLib/ReSpeak.png -------------------------------------------------------------------------------- /TSLib/Scheduler/DispatcherHelper.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib.Helper; 11 | 12 | namespace TSLib.Scheduler 13 | { 14 | internal static class DispatcherHelper 15 | { 16 | public const string DispatcherTitle = "TS Dispatcher"; 17 | 18 | internal static string CreateLogThreadName(string threadName, Id id) => threadName + (id == Id.Null ? "" : $"[{id}]"); 19 | 20 | internal static string CreateDispatcherTitle(Id id) => CreateLogThreadName(DispatcherTitle, id); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /TSLib/Scheduler/TickWorker.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using System; 11 | 12 | namespace TSLib.Scheduler 13 | { 14 | public class TickWorker 15 | { 16 | readonly DedicatedTaskScheduler parent; 17 | private TimeSpan interval; 18 | 19 | internal Action Method { get; } 20 | internal TimeSpan Timestamp { get; set; } = TimeSpan.Zero; 21 | 22 | public TimeSpan Interval 23 | { 24 | get => interval; 25 | set 26 | { 27 | if (value <= TimeSpan.Zero) 28 | throw new ArgumentOutOfRangeException(nameof(Interval), "Interval must not be 0 or negative"); 29 | interval = value; 30 | } 31 | } 32 | 33 | public bool IsActive { get; private set; } = false; 34 | 35 | public void Enable() 36 | { 37 | if (!IsActive) 38 | { 39 | parent.EnableTimer(this); 40 | IsActive = true; 41 | } 42 | } 43 | 44 | public void Disable() 45 | { 46 | if (IsActive) 47 | { 48 | parent.DisableTimer(this); 49 | IsActive = false; 50 | } 51 | } 52 | 53 | internal TickWorker(DedicatedTaskScheduler parent, Action method, TimeSpan interval) 54 | { 55 | this.parent = parent; 56 | Method = method; 57 | Interval = interval; 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /TSLib/Types.cs: -------------------------------------------------------------------------------- 1 | // TSLib - A free TeamSpeak 3 and 5 client library 2 | // Copyright (C) 2017 TSLib contributors 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the Open Software License v. 3.0 6 | // 7 | // You should have received a copy of the Open Software License along with this 8 | // program. If not, see . 9 | 10 | using TSLib.Full; 11 | 12 | namespace TSLib 13 | { 14 | public partial struct Uid 15 | { 16 | /// Unofficial type 17 | public static readonly Uid Anonymous = new Uid("anonymous"); 18 | public static readonly Uid ServerAdmin = new Uid("serveradmin"); 19 | 20 | public static bool IsValid(string uid) 21 | { 22 | if (uid == Anonymous.Value || uid == ServerAdmin.Value) 23 | return true; 24 | var result = TsCrypt.Base64Decode(uid); 25 | return result != null && result.Length == 20; 26 | } 27 | } 28 | 29 | public partial struct ChannelId 30 | { 31 | public string ToPath() => $"/{Value}"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /TSLib/dnc2_compat/Extensions.cs: -------------------------------------------------------------------------------- 1 | #if NETSTANDARD2_0 2 | 3 | using System; 4 | using System.Collections.Generic; 5 | 6 | internal static class Extensions 7 | { 8 | // TimeSpan 9 | 10 | public static TimeSpan Divide(this TimeSpan timeSpan, double divisor) => TimeSpan.FromTicks((long)(timeSpan.Ticks / divisor)); 11 | 12 | // Dictionary 13 | 14 | public static bool Remove(this Dictionary dict, K key, out V value) 15 | { 16 | if (dict.TryGetValue(key, out value)) 17 | { 18 | return dict.Remove(key); 19 | } 20 | return false; 21 | } 22 | } 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /TSLib/dnc2_compat/info.txt: -------------------------------------------------------------------------------- 1 | Since netstandard2.0 does not contain a lot of features wich are required for 2 | C# 8 or available in with netstandard2.1 / dotnet core 3.+ this folder 3 | provides preprocessor-conditionals to supply them. 4 | 5 | The folder can be completely deleted once netstandard2.0 is not targeted 6 | anymore. 7 | -------------------------------------------------------------------------------- /Tools/pack_linux.csx: -------------------------------------------------------------------------------- 1 | #r "nuget: SharpZipLib, 1.2.0" 2 | #r "nuget: SimpleExec, 6.2.0" 3 | 4 | using ICSharpCode.SharpZipLib.Tar; 5 | using ICSharpCode.SharpZipLib.GZip; 6 | using static SimpleExec.Command; 7 | 8 | using (var fs = File.Open("TS3AudioBot.tar", FileMode.Create, FileAccess.Write)) 9 | using (var tar = TarArchive.CreateOutputTarArchive(fs)) 10 | using (var read = File.OpenRead("TS3AudioBot")) 11 | { 12 | var entry = TarEntry.CreateEntryFromFile("TS3AudioBot"); 13 | entry.TarHeader.Mode = Convert.ToInt32("0755", 8); 14 | tar.WriteEntry(entry, false); 15 | } 16 | 17 | Run("tar", "-rf TS3AudioBot.tar WebInterface"); 18 | 19 | using (var fs = File.Open("TS3AudioBot.tar.gz", FileMode.Create, FileAccess.Write)) 20 | using (var gz = new GZipOutputStream(fs)) 21 | using (var read = File.OpenRead("TS3AudioBot.tar")) 22 | { 23 | read.CopyTo(gz); 24 | } 25 | -------------------------------------------------------------------------------- /Tools/ts3notify.ps1: -------------------------------------------------------------------------------- 1 | Param( 2 | [bool]$ok 3 | ) 4 | 5 | # cut to the first 7 chars of the commit hash 6 | $commitCut = $env:APPVEYOR_REPO_COMMIT.Substring(0, 7) 7 | # and set up a nice teamspeak link for it 8 | $commitLink = "[url=https://github.com/$env:APPVEYOR_REPO_NAME/commit/$env:APPVEYOR_REPO_COMMIT]$commitCut[/url]" 9 | # now we do the same for the appveyor build 10 | $buildLink = "[url=https://ci.appveyor.com/project/$env:APPVEYOR_REPO_NAME/builds/$env:APPVEYOR_BUILD_ID]Build #$env:APPVEYOR_BUILD_NUMBER[/url]" 11 | 12 | $gitTitle = git log --format=%B -n 1 HEAD | Out-String 13 | 14 | $finalMsg = "Commit $commitLink in branch $env:APPVEYOR_REPO_BRANCH ($buildLink) " 15 | if ($ok) { 16 | $finalMsg = $finalMsg + "[b][color=green]succeeded[/b].`n Summary: $gitTitle" 17 | } else { 18 | $finalMsg = $finalMsg + "[b][color=red]failed[/b].`n Summary: $gitTitle" 19 | } 20 | $finalMsg = [System.Uri]::EscapeDataString($finalMsg) 21 | $finalMsg = $finalMsg.Replace("(", "%28").Replace(")", "%29") 22 | 23 | try { Invoke-RestMethod -Uri "https://bot.splamy.de/api/bot/template/splamy/(/xecute(/pm/channel/$finalMsg)" } 24 | catch { 25 | Write-Host "Failed to notify:" 26 | Write-Host $_ 27 | } 28 | -------------------------------------------------------------------------------- /WebInterface/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ts3abweb", 3 | "version": "2.0.0-alpha", 4 | "description": "Provides a ui to control the TS3AudioBot", 5 | "scripts": { 6 | "build": "webpack --config webpack.production.config.js", 7 | "start": "webpack-dev-server --config webpack.development.config.js" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "https://github.com/Splamy/TS3AudioBot" 12 | }, 13 | "keywords": [ 14 | "ts3", 15 | "ts3ab", 16 | "interface", 17 | "ui", 18 | "audio", 19 | "bot" 20 | ], 21 | "author": "Splamy", 22 | "license": "OSL-3.0", 23 | "dependencies": { 24 | "@mdi/font": "^5.5.55", 25 | "buefy": "^0.8.20", 26 | "lodash-es": "^4.17.15", 27 | "swagger-ui-dist": "^3.32.1", 28 | "vue": "^2.6.11", 29 | "vue-router": "^3.4.3" 30 | }, 31 | "devDependencies": { 32 | "@types/lodash-es": "^4.17.3", 33 | "copy-webpack-plugin": "^6.0.3", 34 | "css-loader": "^3.5.3", 35 | "file-loader": "^6.0.0", 36 | "html-webpack-plugin": "^4.3.0", 37 | "less": "^3.12.2", 38 | "less-loader": "^6.2.0", 39 | "material-design-icons-iconfont": "^5.0.1", 40 | "mini-css-extract-plugin": "^0.9.0", 41 | "style-loader": "^1.2.1", 42 | "svg-inline-loader": "^0.8.2", 43 | "ts-loader": "^8.0.2", 44 | "typescript": "^3.9.7", 45 | "uglify-es": "^3.3.9", 46 | "vue-loader": "^15.9.3", 47 | "vue-style-loader": "^4.1.2", 48 | "vue-template-compiler": "^2.6.11", 49 | "webpack": "^4.44.1", 50 | "webpack-bundle-analyzer": "^3.8.0", 51 | "webpack-cli": "^3.3.12", 52 | "webpack-dev-server": "^3.11.0", 53 | "webpack-merge": "^5.1.1" 54 | }, 55 | "note": { 56 | "_1": "css-loaded 4.X.X is available but breaks everything and I don't know why" 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /WebInterface/src/html/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/WebInterface/src/html/favicon.ico -------------------------------------------------------------------------------- /WebInterface/src/html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | TS3AudioBot 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /WebInterface/src/html/openapi/favicon-16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/WebInterface/src/html/openapi/favicon-16x16.png -------------------------------------------------------------------------------- /WebInterface/src/html/openapi/favicon-32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Splamy/TS3AudioBot/a69a38d8cba5a4d671dbe06505506f6b46f1d947/WebInterface/src/html/openapi/favicon-32x32.png -------------------------------------------------------------------------------- /WebInterface/src/html/openapi/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Swagger UI 7 | 8 | 9 | 10 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /WebInterface/src/html/openapi/swagger-ui.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":[],"names":[],"mappings":"","file":"swagger-ui.css","sourceRoot":""} -------------------------------------------------------------------------------- /WebInterface/src/less/styles_formdata.less: -------------------------------------------------------------------------------- 1 | // main: styles.less 2 | 3 | .formcontent { 4 | padding: 0.5em; 5 | } 6 | 7 | .formdatablock { 8 | display: flex; 9 | align-items: center; 10 | } 11 | 12 | .formdatablock > * { 13 | margin: 0.3em 0.2em; 14 | } 15 | 16 | .formdatablock > *:first-child { 17 | font-weight: bold; 18 | } 19 | 20 | .formdatablock_fill { 21 | flex-grow: 1; 22 | } 23 | -------------------------------------------------------------------------------- /WebInterface/src/ts/ApiAuth.ts: -------------------------------------------------------------------------------- 1 | export class ApiAuth { 2 | 3 | public get IsAnonymous(): boolean { return this.UserUid.length === 0 && this.Token.length === 0; } 4 | 5 | public static readonly Anonymous: ApiAuth = new ApiAuth("", ""); 6 | 7 | constructor( 8 | public readonly UserUid: string, 9 | public readonly Token: string) { 10 | } 11 | 12 | public static Create(fullTokenString: string): ApiAuth { 13 | if (fullTokenString.length === 0) 14 | return ApiAuth.Anonymous; 15 | 16 | const split = fullTokenString.split(/:/); 17 | if (split.length === 2) { 18 | return new ApiAuth(split[0], split[1]); 19 | } else if (split.length === 3) { 20 | return new ApiAuth(split[0], split[2]); 21 | } else { 22 | throw new Error("Invalid token"); 23 | } 24 | } 25 | 26 | public getBasic(): string { 27 | return `Basic ${btoa(this.UserUid + ":" + this.Token)}`; 28 | } 29 | 30 | public getFullAuth() { 31 | return this.UserUid + ":" + this.Token; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /WebInterface/src/ts/App.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 24 | 25 | 30 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/BotNavbarItem.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 48 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/EditableText.vue: -------------------------------------------------------------------------------- 1 | 25 | 26 | 68 | 69 | 87 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/Hovercon.vue: -------------------------------------------------------------------------------- 1 | 11 | 12 | 26 | 27 | 32 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/PlaybackInfo.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 12 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/SettingsField.vue: -------------------------------------------------------------------------------- 1 | 14 | 15 | 65 | 66 | 68 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/SettingsGroup.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 45 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/SettingsPassword.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 53 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Components/VCanvas.vue: -------------------------------------------------------------------------------- 1 | 4 | 5 | 25 | 26 | 34 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/CreateBotModal.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 31 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/CreatePlaylistModal.vue: -------------------------------------------------------------------------------- 1 | 29 | 30 | 69 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/DeleteBotModal.vue: -------------------------------------------------------------------------------- 1 | 15 | 16 | 25 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/DeletePlaylistModal.vue: -------------------------------------------------------------------------------- 1 | 17 | 18 | 28 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/EnterPasswordModal.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 40 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/QuickConnectModal.vue: -------------------------------------------------------------------------------- 1 | 19 | 20 | 33 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Modals/SiteSettingsModal.vue: -------------------------------------------------------------------------------- 1 | 18 | 19 | 37 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/BotInfoSync.ts: -------------------------------------------------------------------------------- 1 | import { CmdBotInfo, CmdQueueInfo, CmdSong, Empty } from "../ApiObjects"; 2 | import { BotStatus } from "./BotStatus"; 3 | import { RepeatKind } from "./RepeatKind"; 4 | 5 | export class BotInfoSync { 6 | public botInfo = Empty.CmdBotInfo(); 7 | public nowPlaying = Empty.CmdQueueInfo(); 8 | public volume = 0; 9 | public repeat = RepeatKind.Off; 10 | public shuffle = false; 11 | public song = null as CmdSong | null; 12 | } 13 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/BotStatus.ts: -------------------------------------------------------------------------------- 1 | export enum BotStatus { 2 | Offline, 3 | Connecting, 4 | Connected 5 | } 6 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/Languge.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | "cs": "Czech", 3 | "da": "Danish", 4 | "en": "English", 5 | "fr": "French", 6 | "de": "German [Deutsch]", 7 | "hu": "Hungarian", 8 | "pl": "Polish", 9 | "ru": "Russian [Русский]", 10 | "es": "Spanish", 11 | "es-ar": "Spanish (Argentinia)", 12 | "th": "Thai", 13 | }; 14 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/PlayState.ts: -------------------------------------------------------------------------------- 1 | export enum PlayState { 2 | Off, 3 | Playing, 4 | Paused, 5 | } 6 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/RepeatKind.ts: -------------------------------------------------------------------------------- 1 | export enum RepeatKind { 2 | Off = 0, 3 | One, 4 | All, 5 | } 6 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/SettingsLevel.ts: -------------------------------------------------------------------------------- 1 | export enum SettLevel { 2 | Beginner = 0, 3 | Advanced = 1, 4 | Expert = 2, 5 | } 6 | 7 | export interface ISettFilter { 8 | text: string; 9 | level: SettLevel; 10 | } 11 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/SpacerType.ts: -------------------------------------------------------------------------------- 1 | export enum SpacerType { 2 | None = 0, 3 | CSpacer, 4 | RSpacer, 5 | StarSpacer 6 | } 7 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Model/TargetSendMode.ts: -------------------------------------------------------------------------------- 1 | export enum TargetSendMode { 2 | None = 0, 3 | Voice, 4 | Whisper, 5 | WhisperGroup, 6 | } 7 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Pages/BotServer.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 27 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Pages/Commands.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 26 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Pages/OpenApi.d.ts: -------------------------------------------------------------------------------- 1 | declare const SwaggerUIStandalonePreset: any; 2 | declare const SwaggerUIBundle: any; 3 | -------------------------------------------------------------------------------- /WebInterface/src/ts/Timer.ts: -------------------------------------------------------------------------------- 1 | export class Timer { 2 | public interval: number; 3 | private readonly func: () => void; 4 | private timerId: number | undefined; 5 | public get isRunning(): boolean { 6 | return this.timerId !== undefined; 7 | } 8 | 9 | constructor(func: () => void, interval: number) { 10 | this.func = func; 11 | this.interval = interval; 12 | } 13 | 14 | public start(): void { 15 | if (this.timerId !== undefined) 16 | return; 17 | this.timerId = window.setInterval(this.func, this.interval); 18 | } 19 | 20 | public stop(): void { 21 | if (this.timerId === undefined) 22 | return; 23 | window.clearInterval(this.timerId); 24 | this.timerId = undefined; 25 | } 26 | 27 | public restart(): void { 28 | this.stop(); 29 | this.start(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /WebInterface/src/ts/vue-shim.d.ts: -------------------------------------------------------------------------------- 1 | declare module "*.vue" { 2 | import Vue from 'vue' 3 | export default Vue 4 | } 5 | -------------------------------------------------------------------------------- /WebInterface/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es2015", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "watch": false, 8 | "rootDir": "src/ts", 9 | 10 | "removeComments": true, 11 | "noImplicitAny": true, 12 | "strictNullChecks": true, 13 | "alwaysStrict": true, 14 | "noFallthroughCasesInSwitch": true, 15 | "noImplicitReturns": true, 16 | "noImplicitThis": true, 17 | //"noUnusedLocals": true, 18 | //,"noUnusedParameters": true 19 | "strictPropertyInitialization": true, 20 | "strictFunctionTypes": true, 21 | "strict": true, 22 | 23 | "jsx": "react", 24 | "jsxFactory": "createElement" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /WebInterface/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const HtmlWebpackPlugin = require('html-webpack-plugin') 3 | const CopyPlugin = require('copy-webpack-plugin'); 4 | const VueLoaderPlugin = require('vue-loader/lib/plugin') 5 | 6 | module.exports = { 7 | entry: './src/ts/Main.ts', 8 | module: { 9 | rules: [ 10 | { 11 | test: /\.tsx?$/i, 12 | use: [{ 13 | loader: 'ts-loader', 14 | options: { 15 | appendTsSuffixTo: [/\.vue$/] 16 | } 17 | }], 18 | exclude: /node_modules/ 19 | }, 20 | { 21 | test: /\.less$/i, 22 | use: [ 23 | 'style-loader', 24 | 'css-loader', 25 | 'less-loader', 26 | ], 27 | }, 28 | { 29 | test: /\.svg$/i, 30 | loader: 'svg-inline-loader' 31 | }, 32 | { 33 | test: /\.vue$/i, 34 | loader: 'vue-loader' 35 | }, 36 | { 37 | test: /\.css$/i, 38 | use: [ 39 | 'vue-style-loader', 40 | 'css-loader', 41 | ], 42 | }, 43 | { 44 | test: /\.(jpe?g|png|gif|svg|eot|woff|ttf|svg|woff2)$/i, 45 | use: [ 46 | { 47 | loader: 'file-loader', 48 | options: { 49 | name: "[path][name].[ext]" 50 | } 51 | } 52 | ] 53 | } 54 | ] 55 | }, 56 | resolve: { 57 | extensions: ['.tsx', '.ts', '.js', '.vue'], 58 | alias: { 59 | 'vue$': 'vue/dist/vue.esm.js' 60 | } 61 | }, 62 | output: { 63 | filename: 'bundle.js', 64 | path: path.resolve(__dirname, 'dist') 65 | }, 66 | plugins: [ 67 | new HtmlWebpackPlugin({ 68 | title: 'TS3AudioBot', 69 | template: 'src/html/index.html' 70 | }), 71 | new CopyPlugin({ 72 | patterns: [ 73 | { from: 'src/html', to: '.' }, 74 | ] 75 | }), 76 | new VueLoaderPlugin() 77 | ], 78 | devServer: { 79 | disableHostCheck: true, 80 | headers: { 81 | "Access-Control-Allow-Origin": "*", 82 | "Access-Control-Allow-Methods": "GET", 83 | "Access-Control-Allow-Headers": "X-Requested-With, Content-Type, Authorization" 84 | } 85 | } 86 | }; 87 | -------------------------------------------------------------------------------- /WebInterface/webpack.development.config.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.config.js'); 3 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 4 | 5 | module.exports = merge(common, { 6 | mode: 'development', 7 | 8 | //plugins: [new BundleAnalyzerPlugin()] 9 | }); 10 | -------------------------------------------------------------------------------- /WebInterface/webpack.production.config.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.config.js'); 3 | const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin; 4 | 5 | module.exports = merge(common, { 6 | mode: 'production', 7 | 8 | //plugins: [new BundleAnalyzerPlugin()] 9 | }); 10 | --------------------------------------------------------------------------------