DiscordPlaysSwitch & TwitchPlaysSwitch

This commit is contained in:
loicbersier 2020-10-25 16:59:04 +01:00
commit 7f17f3925a
38 changed files with 2107 additions and 0 deletions

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
SysBot.Base/
DiscordPlaySwitch/bin
DiscordPlaySwitch/obj
TwitchPlaySwitch/bin
TwitchPlaySwitch/obj

3
.gitmodules vendored Normal file
View file

@ -0,0 +1,3 @@
[submodule "SysBot.NET"]
path = SysBot.NET
url = https://github.com/kwsch/SysBot.NET.git

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelStore">
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_.19.00" t="ExcludeRecursive" />
<e p="$PROJECT_DIR$" t="IncludeFlat">
<e p="DiscordPlaySwitch" t="IncludeRecursive">
<e p="DiscordPlaySwitch.csproj" t="IncludeRecursive" />
<e p="Program.cs" t="Include" />
<e p="bin" t="ExcludeRecursive" />
<e p="ffmpeg.exe" t="Include" />
<e p="obj" t="ExcludeRecursive">
<e p="Debug" t="Include">
<e p="netcoreapp3.1" t="Include">
<e p="DiscordPlaySwitch.AssemblyInfo.cs" t="Include" />
</e>
</e>
</e>
</e>
<e p="SysBot.Base" t="IncludeRecursive">
<e p="Connection" t="Include">
<e p="SwitchBotConfig.cs" t="Include" />
<e p="SwitchConfigureParameter.cs" t="Include" />
<e p="SwitchConnection.cs" t="Include" />
<e p="SwitchConnectionAsync.cs" t="Include" />
<e p="SwitchConnectionBase.cs" t="Include" />
</e>
<e p="Control" t="Include">
<e p="BotList.cs" t="Include" />
<e p="BotRunner.cs" t="Include" />
<e p="BotSource.cs" t="Include" />
</e>
<e p="Enums" t="Include">
<e p="SwitchButton.cs" t="Include" />
<e p="SwitchStick.cs" t="Include" />
</e>
<e p="SwitchRoutineExecutor.cs" t="Include" />
<e p="Synchronization" t="Include">
<e p="BotSyncOption.cs" t="Include" />
<e p="BotSynchronizer.cs" t="Include" />
<e p="ISynchronizationSetting.cs" t="Include" />
</e>
<e p="SysBot.Base.csproj" t="IncludeRecursive" />
<e p="Util" t="Include">
<e p="Decoder.cs" t="Include" />
<e p="EchoUtil.cs" t="Include" />
<e p="LogUtil.cs" t="Include" />
<e p="NLog.config" t="Include" />
<e p="SwitchCommand.cs" t="Include" />
</e>
<e p="bin" t="ExcludeRecursive" />
<e p="obj" t="ExcludeRecursive">
<e p="Debug" t="Include">
<e p="netstandard2.0" t="Include">
<e p="SysBot.Base.AssemblyInfo.cs" t="Include" />
</e>
</e>
</e>
</e>
<e p="packages" t="ExcludeRecursive" />
</e>
</component>
</project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch.dir/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch.dir/riderModule.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View file

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile>DiscordPlaySwitch/DiscordPlaySwitch.csproj</projectFile>
</component>
<component name="ChangeListManager">
<list default="true" id="bed26ad0-f95b-4721-b5a2-ddafb8ab0955" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="ProjectId" id="1haeJRq7IqT2Dud87rPfWc4kaSn" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/TwitchPlaySwitch.sln" />
<property name="settings.editor.selected.configurable" value="terminal" />
<property name="vue.rearranger.settings.migration" value="true" />
</component>
<component name="RunManager">
<configuration name="DiscordPlaySwitch" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/DiscordPlaySwitch/DiscordPlaySwitch.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="" />
<method v="2">
<option name="Build" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="bed26ad0-f95b-4721-b5a2-ddafb8ab0955" name="Default Changelist" comment="" />
<created>1600253557239</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1600253557239</updated>
<workItem from="1600253560081" duration="69000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityProjectConfiguration" hasMinimizedUI="null" />
<component name="UnityUnitTestConfiguration" currentTestLauncher="NUnit" />
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
</component>
<component name="WindowStateProjectService">
<state x="2692" y="295" key="FileChooserDialogImpl" timestamp="1600253627599">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2692" y="295" key="FileChooserDialogImpl/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253627599" />
</component>
</project>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View file

@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelStore">
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_DiscordPlaySwitch.756794270.00" t="ExcludeRecursive" />
<e p="$PROJECT_DIR$" t="IncludeFlat">
<e p="DiscordPlaySwitch" t="IncludeRecursive">
<e p="DiscordPlaySwitch.csproj" t="IncludeRecursive" />
<e p="Program.cs" t="Include" />
<e p="bin" t="ExcludeRecursive" />
<e p="obj" t="ExcludeRecursive">
<e p="x64" t="Include">
<e p="Debug" t="Include">
<e p="netcoreapp3.1" t="Include">
<e p="DiscordPlaySwitch.AssemblyInfo.cs" t="Include" />
</e>
</e>
</e>
</e>
</e>
<e p="DiscordPlaySwitch.sln" t="IncludeFlat" />
<e p="SysBot.NET/SysBot.Base" t="IncludeRecursive">
<e p="Connection" t="Include">
<e p="SwitchBotConfig.cs" t="Include" />
<e p="SwitchConfigureParameter.cs" t="Include" />
<e p="SwitchConnection.cs" t="Include" />
<e p="SwitchConnectionAsync.cs" t="Include" />
<e p="SwitchConnectionBase.cs" t="Include" />
</e>
<e p="Control" t="Include">
<e p="BotList.cs" t="Include" />
<e p="BotRunner.cs" t="Include" />
<e p="BotSource.cs" t="Include" />
</e>
<e p="Enums" t="Include">
<e p="SwitchButton.cs" t="Include" />
<e p="SwitchStick.cs" t="Include" />
</e>
<e p="SwitchRoutineExecutor.cs" t="Include" />
<e p="Synchronization" t="Include">
<e p="BotSyncOption.cs" t="Include" />
<e p="BotSynchronizer.cs" t="Include" />
<e p="ISynchronizationSetting.cs" t="Include" />
</e>
<e p="SysBot.Base.csproj" t="IncludeRecursive" />
<e p="Util" t="Include">
<e p="Decoder.cs" t="Include" />
<e p="EchoUtil.cs" t="Include" />
<e p="LogUtil.cs" t="Include" />
<e p="NLog.config" t="Include" />
<e p="SwitchCommand.cs" t="Include" />
</e>
<e p="bin" t="ExcludeRecursive" />
<e p="obj" t="ExcludeRecursive">
<e p="Debug" t="Include">
<e p="netstandard2.0" t="Include">
<e p="SysBot.Base.AssemblyInfo.cs" t="Include" />
</e>
</e>
</e>
</e>
<e p="TwitchPlaySwitch" t="IncludeRecursive">
<e p="Program.cs" t="Include" />
<e p="TwitchPlaySwitch.csproj" t="IncludeRecursive" />
<e p="bin" t="ExcludeRecursive" />
<e p="obj" t="ExcludeRecursive">
<e p="x64" t="Include">
<e p="Debug" t="Include">
<e p="netcoreapp3.1" t="Include">
<e p="TwitchPlaySwitch.AssemblyInfo.cs" t="Include" />
</e>
</e>
</e>
</e>
</e>
<e p="packages" t="ExcludeRecursive" />
</e>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
</component>
</project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/riderModule.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
<mapping directory="$PROJECT_DIR$/SysBot.NET" vcs="Git" />
</component>
</project>

View file

@ -0,0 +1,485 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile>DiscordPlaySwitch/DiscordPlaySwitch.csproj</projectFile>
<projectFile>TwitchPlaySwitch/TwitchPlaySwitch.csproj</projectFile>
</component>
<component name="BranchesTreeState">
<expand>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
</path>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="REMOTE_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="GROUP_NODE:origin" type="e8cecc67:BranchNodeDescriptor" />
</path>
</expand>
<select>
<path>
<item name="ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="LOCAL_ROOT" type="e8cecc67:BranchNodeDescriptor" />
<item name="BRANCH:master" type="e8cecc67:BranchNodeDescriptor" />
</path>
</select>
</component>
<component name="ChangeListManager">
<list default="true" id="74ed0fa6-d508-4c56-90d3-45ead4717cb5" name="Default Changelist" comment="">
<change beforePath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/.idea/contentModel.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/.idea/contentModel.xml" afterDir="false" />
<change beforePath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.DiscordPlaySwitch/.idea/workspace.xml" afterDir="false" />
</list>
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="Git.Settings">
<option name="RECENT_COMMON_BRANCH" value="master" />
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
<option name="RESET_MODE" value="MIXED" />
</component>
<component name="HighlightingSettingsPerFile">
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/IL/37BB4072-7464-4C78-AA28-9B469E7ADD54/9d/010f2faf/02000002.il" root0="SKIP_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/37BB4072-7464-4C78-AA28-9B469E7ADD54/15/ca3e80be/OnLogArgs.cs" root0="SKIP_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/TwitchPlaySwitch/Program.cs" root0="FORCE_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/TwitchPlaySwitch/obj/x64/Release/netcoreapp3.1/TwitchPlaySwitch.AssemblyInfo.cs" root0="SKIP_HIGHLIGHTING" />
<setting file="file://$PROJECT_DIR$/DiscordPlaySwitch/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs" root0="SKIP_HIGHLIGHTING" />
<setting file="file://$APPLICATION_CONFIG_DIR$/resharper-host/DecompilerCache/decompiler/37BB4072-7464-4C78-AA28-9B469E7ADD54/99/6e7c754b/TwitchClient.cs" root0="SKIP_HIGHLIGHTING" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/DiscordPlaySwitch.sln" />
<option value="$PROJECT_DIR$/TwitchPlaySwitch/obj/x64/Release/netcoreapp3.1/TwitchPlaySwitch.AssemblyInfo.cs" />
<option value="$PROJECT_DIR$/DiscordPlaySwitch/DiscordPlaySwitch.csproj" />
<option value="$PROJECT_DIR$/TwitchPlaySwitch/TwitchPlaySwitch.csproj" />
<option value="$PROJECT_DIR$/DiscordPlaySwitch/Program.cs" />
<option value="$PROJECT_DIR$/.gitignore" />
<option value="$PROJECT_DIR$/DiscordPlaySwitch/obj/Debug/netcoreapp3.1/.NETCoreApp,Version=v3.1.AssemblyAttributes.cs" />
<option value="$PROJECT_DIR$/TwitchPlaySwitch/bin/x64/Release/netcoreapp3.1/config.json" />
<option value="$PROJECT_DIR$/readme.md" />
<option value="$PROJECT_DIR$/TwitchPlaySwitch/Program.cs" />
</list>
</option>
</component>
<component name="ProjectId" id="1hafEOuIWcZ2CbESB9ceTfRoTyA" />
<component name="ProjectLevelVcsManager" settingsEditedManually="true">
<ConfirmationsSetting value="2" id="Add" />
</component>
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="ASKED_ADD_EXTERNAL_FILES" value="true" />
<property name="DebuggerViewTab_PTCS_FirstProportionKey" value="0.3497482" />
<property name="DebuggerViewTab_PTCS_LastProportionKey" value="0.29994404" />
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/SysBot.NET/SysBot.Base" />
<property name="nodejs_package_manager_path" value="npm" />
<property name="restartRequiresConfirmation" value="false" />
<property name="settings.editor.selected.configurable" value="vcs.Git" />
<property name="vue.rearranger.settings.migration" value="true" />
</component>
<component name="RunManager" selected=".NET Project.TwitchPlaySwitch">
<configuration name="DiscordPlaySwitch" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/DiscordPlaySwitch/DiscordPlaySwitch.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="" />
<method v="2">
<option name="Build" />
</method>
</configuration>
<configuration name="TwitchPlaySwitch" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="$PROJECT_DIR$/TwitchPlaySwitch/bin/x64/Release/netcoreapp3.1/TwitchPlaySwitch.dll" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/TwitchPlaySwitch/bin/x64/Release/netcoreapp3.1/" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/TwitchPlaySwitch/TwitchPlaySwitch.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="0" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
<method v="2">
<option name="Build" />
</method>
</configuration>
<list>
<item itemvalue=".NET Project.DiscordPlaySwitch" />
<item itemvalue=".NET Project.TwitchPlaySwitch" />
</list>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="74ed0fa6-d508-4c56-90d3-45ead4717cb5" name="Default Changelist" comment="" />
<created>1600254011799</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1600254011799</updated>
<workItem from="1600254014409" duration="2470000" />
<workItem from="1600258539973" duration="5383000" />
<workItem from="1600272650152" duration="4886000" />
<workItem from="1600296874375" duration="4427000" />
<workItem from="1600420138874" duration="2132000" />
<workItem from="1600422561434" duration="2436000" />
<workItem from="1600440328700" duration="1513000" />
<workItem from="1600441864085" duration="654000" />
<workItem from="1600442541832" duration="1402000" />
<workItem from="1600510362904" duration="648000" />
<workItem from="1600771023318" duration="1271000" />
<workItem from="1601113998761" duration="3333000" />
<workItem from="1601153703657" duration="10603000" />
<workItem from="1601216647856" duration="40185000" />
<workItem from="1601909840415" duration="1461000" />
<workItem from="1601928197792" duration="162000" />
<workItem from="1602257255996" duration="1024000" />
</task>
<task id="LOCAL-00001" summary="DiscordPlaysSwitch/TwitchPlaysSwitch">
<created>1600443267971</created>
<option name="number" value="00001" />
<option name="presentableId" value="LOCAL-00001" />
<option name="project" value="LOCAL" />
<updated>1600443267971</updated>
</task>
<task id="LOCAL-00002" summary="TwitchPlaysSwitch &amp; DiscordPlaysSwitch">
<created>1601215825516</created>
<option name="number" value="00002" />
<option name="presentableId" value="LOCAL-00002" />
<option name="project" value="LOCAL" />
<updated>1601215825516</updated>
</task>
<task id="LOCAL-00003" summary="Add git ignore">
<created>1601215939083</created>
<option name="number" value="00003" />
<option name="presentableId" value="LOCAL-00003" />
<option name="project" value="LOCAL" />
<updated>1601215939083</updated>
</task>
<task id="LOCAL-00004" summary="Add git ignore">
<created>1601216545046</created>
<option name="number" value="00004" />
<option name="presentableId" value="LOCAL-00004" />
<option name="project" value="LOCAL" />
<updated>1601216545046</updated>
</task>
<task id="LOCAL-00005" summary="I don't know what i am doing">
<created>1601216723277</created>
<option name="number" value="00005" />
<option name="presentableId" value="LOCAL-00005" />
<option name="project" value="LOCAL" />
<updated>1601216723277</updated>
</task>
<task id="LOCAL-00006" summary="Updated readme">
<created>1601217111941</created>
<option name="number" value="00006" />
<option name="presentableId" value="LOCAL-00006" />
<option name="project" value="LOCAL" />
<updated>1601217111941</updated>
</task>
<task id="LOCAL-00007" summary="I don't know what that is">
<created>1601217127004</created>
<option name="number" value="00007" />
<option name="presentableId" value="LOCAL-00007" />
<option name="project" value="LOCAL" />
<updated>1601217127004</updated>
</task>
<task id="LOCAL-00008" summary="Updated readme">
<created>1601217462310</created>
<option name="number" value="00008" />
<option name="presentableId" value="LOCAL-00008" />
<option name="project" value="LOCAL" />
<updated>1601217462310</updated>
</task>
<task id="LOCAL-00009" summary="Still don't know what that is">
<created>1601217472406</created>
<option name="number" value="00009" />
<option name="presentableId" value="LOCAL-00009" />
<option name="project" value="LOCAL" />
<updated>1601217472406</updated>
</task>
<task id="LOCAL-00010" summary="Update readme">
<created>1601217968948</created>
<option name="number" value="00010" />
<option name="presentableId" value="LOCAL-00010" />
<option name="project" value="LOCAL" />
<updated>1601217968948</updated>
</task>
<task id="LOCAL-00011" summary="I still don't know what that is">
<created>1601217983168</created>
<option name="number" value="00011" />
<option name="presentableId" value="LOCAL-00011" />
<option name="project" value="LOCAL" />
<updated>1601217983168</updated>
</task>
<task id="LOCAL-00012" summary="Update readme">
<created>1601218188204</created>
<option name="number" value="00012" />
<option name="presentableId" value="LOCAL-00012" />
<option name="project" value="LOCAL" />
<updated>1601218188204</updated>
</task>
<task id="LOCAL-00013" summary="Still don't know what that is">
<created>1601330792259</created>
<option name="number" value="00013" />
<option name="presentableId" value="LOCAL-00013" />
<option name="project" value="LOCAL" />
<updated>1601330792259</updated>
</task>
<task id="LOCAL-00014" summary="Added BroadcasterOnly mode&#10;Made button &amp; stick input separate&#10;Added queue for button &amp; stick&#10;Added log function&#10;Added francy pants figlet&#10;Added home, exit &amp; exit game to breadcaster only">
<created>1601333833895</created>
<option name="number" value="00014" />
<option name="presentableId" value="LOCAL-00014" />
<option name="project" value="LOCAL" />
<updated>1601333833895</updated>
</task>
<task id="LOCAL-00015" summary="WHAT THE FUCK IS THAT????">
<created>1601333842289</created>
<option name="number" value="00015" />
<option name="presentableId" value="LOCAL-00015" />
<option name="project" value="LOCAL" />
<updated>1601333842289</updated>
</task>
<task id="LOCAL-00016" summary="Update readme">
<created>1601333916849</created>
<option name="number" value="00016" />
<option name="presentableId" value="LOCAL-00016" />
<option name="project" value="LOCAL" />
<updated>1601333916849</updated>
</task>
<task id="LOCAL-00017" summary="yea">
<created>1601334235482</created>
<option name="number" value="00017" />
<option name="presentableId" value="LOCAL-00017" />
<option name="project" value="LOCAL" />
<updated>1601334235482</updated>
</task>
<task id="LOCAL-00018" summary="still don't know">
<created>1601334240777</created>
<option name="number" value="00018" />
<option name="presentableId" value="LOCAL-00018" />
<option name="project" value="LOCAL" />
<updated>1601334240777</updated>
</task>
<task id="LOCAL-00019" summary="make stick show correct user">
<created>1601334250876</created>
<option name="number" value="00019" />
<option name="presentableId" value="LOCAL-00019" />
<option name="project" value="LOCAL" />
<updated>1601334250876</updated>
</task>
<task id="LOCAL-00020" summary="ACTUALLY make stick &amp; button show correct user">
<created>1601334676770</created>
<option name="number" value="00020" />
<option name="presentableId" value="LOCAL-00020" />
<option name="project" value="LOCAL" />
<updated>1601334676770</updated>
</task>
<task id="LOCAL-00021" summary="I still don't know what that is">
<created>1601334686072</created>
<option name="number" value="00021" />
<option name="presentableId" value="LOCAL-00021" />
<option name="project" value="LOCAL" />
<updated>1601334686072</updated>
</task>
<task id="LOCAL-00022" summary="uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh&#10;&#10;i actually forgot but i think it work">
<created>1601928132301</created>
<option name="number" value="00022" />
<option name="presentableId" value="LOCAL-00022" />
<option name="project" value="LOCAL" />
<updated>1601928132301</updated>
</task>
<option name="localTasksCounter" value="23" />
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
<component name="UnityUnitTestConfiguration" currentTestLauncher="NUnit" />
<component name="Vcs.Log.Tabs.Properties">
<option name="TAB_STATES">
<map>
<entry key="MAIN">
<value>
<State>
<option name="FILTERS">
<map>
<entry key="branch">
<value>
<list>
<option value="master" />
</list>
</value>
</entry>
</map>
</option>
</State>
</value>
</entry>
</map>
</option>
<option name="oldMeFiltersMigrated" value="true" />
</component>
<component name="VcsManagerConfiguration">
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
<MESSAGE value="DiscordPlaysSwitch/TwitchPlaysSwitch" />
<MESSAGE value="TwitchPlaysSwitch &amp; DiscordPlaysSwitch" />
<MESSAGE value="Add git ignore" />
<MESSAGE value="I don't know what i am doing" />
<MESSAGE value="I don't know what that is" />
<MESSAGE value="Updated readme" />
<MESSAGE value="Still don't know what that is" />
<MESSAGE value="Added BroadcasterOnly mode&#10;Made button &amp; stick input separate&#10;Added queue for button &amp; stick&#10;Added log function&#10;Added francy pants figlet&#10;Added home, exit &amp; exit game to breadcaster only" />
<MESSAGE value="WHAT THE FUCK IS THAT????" />
<MESSAGE value="Update readme" />
<MESSAGE value="yea" />
<MESSAGE value="still don't know" />
<MESSAGE value="make stick show correct user" />
<MESSAGE value="ACTUALLY make stick &amp; button show correct user" />
<MESSAGE value="I still don't know what that is" />
<MESSAGE value="uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh&#10;&#10;i actually forgot but i think it work" />
<option name="LAST_COMMIT_MESSAGE" value="uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuh&#10;&#10;i actually forgot but i think it work" />
</component>
<component name="WindowStateProjectService">
<state x="2367" y="195" width="1081" height="758" key="#com.intellij.execution.impl.EditConfigurationsDialog" timestamp="1600443097312">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2367" y="195" width="1081" height="758" key="#com.intellij.execution.impl.EditConfigurationsDialog/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443097312" />
<state x="100" y="100" width="1720" height="880" key="DiffContextDialog" timestamp="1601333978967">
<screen x="0" y="0" width="1920" height="1080" />
</state>
<state x="100" y="100" width="1720" height="880" key="DiffContextDialog/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601333978967" />
<state x="2691" y="298" width="432" height="490" key="FileChooserDialogImpl" timestamp="1600442003825">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2691" y="298" width="432" height="490" key="FileChooserDialogImpl/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600442003825" />
<state x="2752" y="437" key="Github.ShareDialog" timestamp="1601216844096">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2752" y="437" key="Github.ShareDialog/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1601216844096" />
<state width="1820" height="237" key="GridCell.Tab.0.bottom" timestamp="1602258279152">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1874" height="199" key="GridCell.Tab.0.bottom/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1600432875623" />
<state width="1874" height="133" key="GridCell.Tab.0.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601851232315" />
<state width="1820" height="237" key="GridCell.Tab.0.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1602258279152" />
<state width="1180" height="133" key="GridCell.Tab.0.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@3840.0.1920.1080" timestamp="1601928359431" />
<state width="1820" height="237" key="GridCell.Tab.0.center" timestamp="1602258279152">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1874" height="199" key="GridCell.Tab.0.center/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1600432875623" />
<state width="1874" height="133" key="GridCell.Tab.0.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601851232315" />
<state width="1820" height="237" key="GridCell.Tab.0.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1602258279152" />
<state width="1180" height="133" key="GridCell.Tab.0.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@3840.0.1920.1080" timestamp="1601928359431" />
<state width="1820" height="237" key="GridCell.Tab.0.left" timestamp="1602258279152">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1874" height="199" key="GridCell.Tab.0.left/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1600432875623" />
<state width="1874" height="133" key="GridCell.Tab.0.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601851232315" />
<state width="1820" height="237" key="GridCell.Tab.0.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1602258279152" />
<state width="1180" height="133" key="GridCell.Tab.0.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@3840.0.1920.1080" timestamp="1601928359431" />
<state width="1820" height="237" key="GridCell.Tab.0.right" timestamp="1602258279152">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1874" height="199" key="GridCell.Tab.0.right/1920.0.1920.1080/0.0.1920.1080/3840.0.1920.1080@0.0.1920.1080" timestamp="1600432875623" />
<state width="1874" height="133" key="GridCell.Tab.0.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601851232315" />
<state width="1820" height="237" key="GridCell.Tab.0.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1602258279152" />
<state width="1180" height="133" key="GridCell.Tab.0.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@3840.0.1920.1080" timestamp="1601928359431" />
<state width="1818" height="381" key="GridCell.Tab.1.bottom" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.1.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.1.center" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.1.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.1.left" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.1.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.1.right" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.1.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.2.bottom" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.2.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.2.center" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.2.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.2.left" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.2.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.2.right" timestamp="1600443942973">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.2.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942973" />
<state width="1818" height="381" key="GridCell.Tab.3.bottom" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.3.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.3.center" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.3.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.3.left" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.3.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.3.right" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.3.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.4.bottom" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.4.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.4.center" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.4.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.4.left" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.4.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state width="1818" height="381" key="GridCell.Tab.4.right" timestamp="1600443942974">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="381" key="GridCell.Tab.4.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600443942974" />
<state x="2179" y="266" width="1007" height="736" key="SettingsEditor" timestamp="1601215600233">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="485" y="172" width="1007" height="736" key="SettingsEditor/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1600272773944" />
<state x="2179" y="266" key="SettingsEditor/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1601215600233" />
<state x="2504" y="273" width="808" height="534" key="Vcs.Push.Dialog.v2" timestamp="1601928138833">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="584" y="273" key="Vcs.Push.Dialog.v2/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@0.0.1920.1080" timestamp="1601334692016" />
<state x="2504" y="273" width="808" height="534" key="Vcs.Push.Dialog.v2/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1601928138833" />
</component>
</project>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

View file

@ -0,0 +1 @@
TwitchPlaySwitch

View file

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelStore">
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/extResources" t="IncludeRecursive" />
<e p="$USER_HOME$/.cache/JetBrains/Rider2020.2/resharper-host/local/Transient/Rider/v202/SolutionCaches/_TwitchPlaySwitch.748819999.00" t="ExcludeRecursive" />
<e p="$PROJECT_DIR$" t="IncludeFlat">
<e p="TwitchPlaySwitch.sln" t="IncludeFlat" />
</e>
</component>
</project>

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" addBOMForNewFiles="with BOM under Windows, with no BOM otherwise" />
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ContentModelUserStore">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/.idea.TwitchPlaySwitch/riderModule.iml" filepath="$PROJECT_DIR$/.idea/.idea.TwitchPlaySwitch/riderModule.iml" />
</modules>
</component>
</project>

View file

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RiderProjectSettingsUpdater">
<option name="vcsConfiguration" value="2" />
</component>
</project>

View file

@ -0,0 +1,104 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AutoGeneratedRunConfigurationManager">
<projectFile>DiscordPlaySwitch/DiscordPlaySwitch.csproj</projectFile>
</component>
<component name="ChangeListManager">
<list default="true" id="04a73c96-f9fc-412c-804b-c956d93b257c" name="Default Changelist" comment="" />
<option name="SHOW_DIALOG" value="false" />
<option name="HIGHLIGHT_CONFLICTS" value="true" />
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
<option name="LAST_RESOLUTION" value="IGNORE" />
</component>
<component name="HighlightingSettingsPerFile">
<setting file="file://$PROJECT_DIR$/DiscordPlaySwitch/Program.cs" root0="SKIP_HIGHLIGHTING" />
</component>
<component name="IdeDocumentHistory">
<option name="CHANGED_PATHS">
<list>
<option value="$PROJECT_DIR$/DiscordPlaySwitch/DiscordPlaySwitch.csproj" />
<option value="$PROJECT_DIR$/DiscordPlaySwitch/Program.cs" />
</list>
</option>
</component>
<component name="ProjectId" id="1haeSO4owf0oebAsP8YZCPxc4ps" />
<component name="ProjectViewState">
<option name="hideEmptyMiddlePackages" value="true" />
<option name="showLibraryContents" value="true" />
</component>
<component name="PropertiesComponent">
<property name="RunOnceActivity.OpenProjectViewOnStart" value="true" />
<property name="WebServerToolWindowFactoryState" value="false" />
<property name="last_opened_file_path" value="$PROJECT_DIR$/DiscordPlaySwitch.sln" />
<property name="restartRequiresConfirmation" value="false" />
<property name="settings.editor.selected.configurable" value="preferences.pluginManager" />
<property name="vue.rearranger.settings.migration" value="true" />
</component>
<component name="RunManager">
<configuration name="DiscordPlaySwitch" type="DotNetProject" factoryName=".NET Project">
<option name="EXE_PATH" value="" />
<option name="PROGRAM_PARAMETERS" value="" />
<option name="WORKING_DIRECTORY" value="" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/DiscordPlaySwitch/DiscordPlaySwitch.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value="" />
<method v="2">
<option name="Build" />
</method>
</configuration>
</component>
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
<component name="TaskManager">
<task active="true" id="Default" summary="Default task">
<changelist id="04a73c96-f9fc-412c-804b-c956d93b257c" name="Default Changelist" comment="" />
<created>1600253629021</created>
<option name="number" value="Default" />
<option name="presentableId" value="Default" />
<updated>1600253629021</updated>
<workItem from="1600253631484" duration="326000" />
<workItem from="1600253972860" duration="39000" />
</task>
<servers />
</component>
<component name="TypeScriptGeneratedFilesManager">
<option name="version" value="3" />
</component>
<component name="UnityProjectConfiguration" hasMinimizedUI="false" />
<component name="UnityUnitTestConfiguration" currentTestLauncher="NUnit" />
<component name="VcsManagerConfiguration">
<option name="CLEAR_INITIAL_COMMIT_MESSAGE" value="true" />
</component>
<component name="WindowStateProjectService">
<state x="2692" y="295" width="432" height="490" key="FileChooserDialogImpl" timestamp="1600254010415">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2692" y="295" width="432" height="490" key="FileChooserDialogImpl/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600254010415" />
<state width="1818" height="126" key="GridCell.Tab.0.bottom" timestamp="1600253926404">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="126" key="GridCell.Tab.0.bottom/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253926404" />
<state width="1818" height="126" key="GridCell.Tab.0.center" timestamp="1600253926404">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="126" key="GridCell.Tab.0.center/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253926404" />
<state width="1818" height="126" key="GridCell.Tab.0.left" timestamp="1600253926404">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="126" key="GridCell.Tab.0.left/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253926404" />
<state width="1818" height="126" key="GridCell.Tab.0.right" timestamp="1600253926404">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state width="1818" height="126" key="GridCell.Tab.0.right/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253926404" />
<state x="2405" y="172" key="SettingsEditor" timestamp="1600253957287">
<screen x="1920" y="0" width="1920" height="1080" />
</state>
<state x="2405" y="172" key="SettingsEditor/1920.0.1920.1080/3840.0.1920.1080/0.0.1920.1080@1920.0.1920.1080" timestamp="1600253957287" />
</component>
</project>

View file

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RIDER_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$/../.." />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

51
DiscordPlaySwitch.sln Normal file
View file

@ -0,0 +1,51 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.30413.136
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiscordPlaySwitch", "DiscordPlaySwitch\DiscordPlaySwitch.csproj", "{D1112CE7-7826-4F61-9468-F20FBE186990}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SysBot.Base", "SysBot.NET\SysBot.Base\SysBot.Base.csproj", "{8A67E2C6-E320-43AE-B68A-F12B6443C769}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TwitchPlaySwitch", "TwitchPlaySwitch\TwitchPlaySwitch.csproj", "{92EB7C14-C59E-4415-B5B0-0831CD432BF7}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{D1112CE7-7826-4F61-9468-F20FBE186990}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D1112CE7-7826-4F61-9468-F20FBE186990}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D1112CE7-7826-4F61-9468-F20FBE186990}.Debug|x64.ActiveCfg = Debug|x64
{D1112CE7-7826-4F61-9468-F20FBE186990}.Debug|x64.Build.0 = Debug|x64
{D1112CE7-7826-4F61-9468-F20FBE186990}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D1112CE7-7826-4F61-9468-F20FBE186990}.Release|Any CPU.Build.0 = Release|Any CPU
{D1112CE7-7826-4F61-9468-F20FBE186990}.Release|x64.ActiveCfg = Release|x64
{D1112CE7-7826-4F61-9468-F20FBE186990}.Release|x64.Build.0 = Release|x64
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Debug|x64.ActiveCfg = Debug|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Debug|x64.Build.0 = Debug|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Release|Any CPU.Build.0 = Release|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Release|x64.ActiveCfg = Release|Any CPU
{8A67E2C6-E320-43AE-B68A-F12B6443C769}.Release|x64.Build.0 = Release|Any CPU
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Debug|x64.ActiveCfg = Debug|x64
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Debug|x64.Build.0 = Debug|x64
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Release|Any CPU.Build.0 = Release|Any CPU
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Release|x64.ActiveCfg = Release|x64
{92EB7C14-C59E-4415-B5B0-0831CD432BF7}.Release|x64.Build.0 = Release|x64
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {FD16F689-9F69-4462-A639-C85753141DF0}
EndGlobalSection
EndGlobal

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
<RootNamespace>DiscordPlaySwitch</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="2.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SysBot.NET\SysBot.Base\SysBot.Base.csproj" />
</ItemGroup>
</Project>

View file

@ -0,0 +1,343 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Discord;
using Discord.WebSocket;
using Newtonsoft.Json.Linq;
using SysBot.Base;
namespace DiscordPlaySwitch
{
class Program
{
private DiscordSocketClient _client;
private SwitchConnectionAsync _connection;
private static readonly JObject Config = JObject.Parse(File.ReadAllText("config.json"));
private readonly JObject _nSwitch = JObject.Parse(Config.GetValue("nSwitch").ToString());
private readonly string[] _control =
{
"DLEFT", "DRIGHT", "DUP", "DDOWN", "A", "B", "X", "Y", "+", "-", "ZL", "ZR", "L", "R", "LSP", "RSP", "LSU",
"LSUR", "LSUL", "LSDR", "LSDL", "LSD", "LSL", "LSR", "RSU", "RSD", "RSL", "RSR", "SCREENSHOT"
};
private readonly string _prefix = ((string) Config.GetValue("prefix")).ToUpper();
public static void Main(string[] args)
=> new Program().MainAsync().GetAwaiter().GetResult();
private async Task MainAsync()
{
_client = new DiscordSocketClient();
_client.Log += Log;
await _client.LoginAsync(TokenType.Bot, (string) Config.GetValue("token"));
await _client.StartAsync();
_client.Ready += () =>
{
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine("==================================================================================");
Console.WriteLine($"Connected to discord as {_client.CurrentUser.Username}#{_client.CurrentUser.DiscriminatorValue} ({_client.CurrentUser.Id})");
Console.WriteLine($"Discord bot prefix is set as: {_prefix}");
Console.WriteLine("Attempting to connect to the Nintendo switch");
try
{
_connection = new SwitchConnectionAsync((string) _nSwitch.GetValue("IP"),
int.Parse((string) _nSwitch.GetValue("sysbotPORT")));
_connection.Connect();
}
catch (Exception e)
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(e);
Console.ResetColor();
}
if (_connection.Connected)
{
Console.WriteLine($"Connected to nintendo switch on {_connection.IP}:{_connection.Port}!");
Console.WriteLine($"Say \"{_prefix}exit\" in discord to quit the application!");
}
else
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Failed to connect to the console!");
Console.WriteLine("Press any key to exit the app.");
Console.ResetColor();
Console.ReadKey();
Environment.Exit(1);
}
Console.WriteLine("==================================================================================");
Console.ResetColor();
return Task.CompletedTask;
};
_client.MessageReceived += async message =>
{
if (message.Author.IsBot) return;
if (message.Author.Id == 595703186816499772) return;
if (_connection.Connected)
if (message.Content.Length > _prefix.Length)
await HandleInput(message);
};
await Task.Delay(-1);
}
private async Task HandleInput(SocketMessage message)
{
string msg = message.Content;
string args = msg.ToUpper().Substring(_prefix.Length, msg.Length - _prefix.Length);
string[] words = args.Split(' ');
if (msg.ToUpper().StartsWith(_prefix))
{
switch (args)
{
case "HELP":
await message.Channel.SendMessageAsync(
$"You can input one of those command and they will execute on my nintendo switch ( please don't destroy it ):\n{string.Join(" ", _control)}");
break;
case "EXIT GAME":
{
break;
if (message.Author.Id == 267065637183029248)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.HOME),
cancellationToken.Token);
cancellationToken.Cancel();
Thread.Sleep(500);
cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.X),
cancellationToken.Token);
cancellationToken.Cancel();
Thread.Sleep(500);
cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.A),
cancellationToken.Token);
cancellationToken.Cancel();
Console.WriteLine("Game exited");
await message.Channel.SendMessageAsync("Game exited");
}
else
{
await message.Channel.SendMessageAsync("Only for supositware");
}
break;
}
case "EXIT":
{
break;
if (message.Author.Id == 267065637183029248)
{
_connection.Disconnect();
Console.WriteLine("Bye bye!");
await message.Channel.SendMessageAsync("Bye bye!");
Environment.Exit(1);
}
else
{
await message.Channel.SendMessageAsync("Only for supositware");
}
break;
}
case "SCREENSHOT":
SendScreenshot(message);
break;
}
if (_control.Any(args.Contains))
{
short speed = short.MaxValue;
if (args.Contains("SLOWER"))
{
speed = 8000;
//i++;
}
else if (args.Contains("SLOW"))
{
speed = 10000;
//i++;
}
else if (args.Contains("MEDIUM"))
{
speed = 16382;
//i++;
}
foreach (var word in words)
{
if (Array.Exists(_control, e => e == word))
{
switch (word)
{
case "DLEFT":
PressButton(SwitchButton.DLEFT);
break;
case "DRIGHT":
PressButton(SwitchButton.DRIGHT);
break;
case "DUP":
PressButton(SwitchButton.DUP);
break;
case "DDOWN":
PressButton(SwitchButton.DDOWN);
break;
case "A":
PressButton(SwitchButton.A);
break;
case "B":
PressButton(SwitchButton.B);
break;
case "X":
PressButton(SwitchButton.X);
break;
case "Y":
PressButton(SwitchButton.Y);
break;
case "+":
PressButton(SwitchButton.PLUS);
break;
case "-":
PressButton(SwitchButton.MINUS);
break;
case "ZL":
PressButton(SwitchButton.ZL);
break;
case "ZR":
PressButton(SwitchButton.ZR);
break;
case "L":
PressButton(SwitchButton.L);
break;
case "R":
PressButton(SwitchButton.R);
break;
case "LSP":
PressButton(SwitchButton.LSTICK);
break;
case "RSP":
PressButton(SwitchButton.RSTICK);
break;
case "LSU":
MoveStick(SwitchStick.LEFT, 0, speed);
break;
case "LSUL":
MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), speed);
break;
case "LSUR":
MoveStick(SwitchStick.LEFT, speed, speed);
break;
case "LSD":
MoveStick(SwitchStick.LEFT, 0, short.Parse((speed * -1).ToString()));
break;
case "LSDL":
MoveStick(SwitchStick.LEFT, speed, short.Parse((speed * -1).ToString()));
break;
case "LSDR":
MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), short.Parse((speed * -1).ToString()));
break;
case "LSL":
MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), 0);
break;
case "LSR":
MoveStick(SwitchStick.LEFT, speed, 0);
break;
case "RSU":
MoveStick(SwitchStick.RIGHT, 0, speed);
break;
case "RSD":
MoveStick(SwitchStick.RIGHT, 0, short.Parse((speed * -1).ToString()));
break;
case "RSL":
MoveStick(SwitchStick.RIGHT, short.Parse((speed * -1).ToString()), 0);
break;
case "RSR":
MoveStick(SwitchStick.RIGHT, speed, 0);
break;
}
SendScreenshot(message);
}
}
}
}
}
private Task Log(LogMessage msg)
{
Console.WriteLine(msg.ToString());
return Task.CompletedTask;
}
private async void PressButton(SwitchButton button)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
if (button == SwitchButton.ZL || button == SwitchButton.ZR)
{
await _connection.SendAsync(SwitchCommand.Hold(button), cancellationToken.Token);
Thread.Sleep(2000);
//SendScreenshot(message);
await _connection.SendAsync(SwitchCommand.Release(button), cancellationToken.Token);
}
else
{
await _connection.SendAsync(SwitchCommand.Click(button), cancellationToken.Token);
//SendScreenshot(message);
}
cancellationToken.Cancel();
}
private async void MoveStick(SwitchStick stick, short x, short y)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.SetStick(stick, x, y), cancellationToken.Token);
Thread.Sleep(stick == SwitchStick.RIGHT ? 500 : 1000);
await _connection.SendAsync(SwitchCommand.ResetStick(stick), cancellationToken.Token);
//SendScreenshot(message);
cancellationToken.Cancel();
}
private void SendScreenshot(SocketMessage message)
{
using (Process pProcess = new Process())
{
pProcess.StartInfo.FileName = "ffmpeg";
pProcess.StartInfo.Arguments =
$"-hide_banner -loglevel panic -y -i rtsp://{(string) _nSwitch.GetValue("IP")}:{(string) _nSwitch.GetValue("sysDVRPORT")} -vframes 1 NintendoSwitch.jpg"; //argument
//pProcess.StartInfo.Arguments = $"-hide_banner -loglevel panic -y -i rtsp://127.0.0.1:6666 -vframes 1 NintendoSwitch.jpg"; //argument
pProcess.StartInfo.UseShellExecute = false;
pProcess.StartInfo.RedirectStandardOutput = true;
pProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
pProcess.StartInfo.CreateNoWindow = true; //not diplay a windows
pProcess.Start();
pProcess.WaitForExit();
}
message.Channel.SendFileAsync("NintendoSwitch.jpg");
}
}
}

BIN
SwitchPlaysLayout.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 234 KiB

BIN
SwitchPlaysLayout.xcf Normal file

Binary file not shown.

1
SysBot.NET Submodule

@ -0,0 +1 @@
Subproject commit 5ea3cb47cf64d5a4420337c94d59219c9f1187b5

668
TwitchPlaySwitch/Program.cs Normal file
View file

@ -0,0 +1,668 @@
using System;
using System.Collections;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using TwitchLib.Client;
using TwitchLib.Client.Events;
using TwitchLib.Client.Models;
using TwitchLib.Communication.Clients;
using TwitchLib.Communication.Models;
using Newtonsoft.Json.Linq;
using SysBot.Base;
using TwitchLib.Api;
using User = TwitchLib.Api.V5.Models.Users.User;
namespace TwitchPlaySwitch
{
class Program
{
private static SwitchConnectionAsync _connection;
private static readonly Queue StickQueue = new Queue();
private static readonly Queue ButtonQueue = new Queue();
private static bool _broadcasterOnly = false;
private class StickMovement
{
public SwitchStick Stick;
public short X = -1;
public short Y = -1;
public int Hold = 1000;
}
private static readonly JObject Config = JObject.Parse(File.ReadAllText("config.json"));
private static readonly JObject NSwitch = JObject.Parse(Config.GetValue("nSwitch").ToString());
private static readonly string[] Stick =
{
"LSU", "LSUR", "LSUL", "LSDR", "LSDL", "LSD", "LSL", "LSR", "RSU", "RSD", "RSL", "RSR"
};
private static readonly string[] Button =
{
"DLEFT", "DRIGHT", "DUP", "DDOWN", "A", "B", "X", "Y", "+", "-", "ZL", "ZR", "L", "R", "LSP", "RSP"
};
private static void Log(string msg, ConsoleColor color = default)
{
string log = $"{DateTime.Now}: {msg}";
if (!Directory.Exists("logs"))
{
Directory.CreateDirectory("logs");
}
File.AppendAllText($"logs/{Convert.ToDateTime(DateTime.Today).ToString("dd.MM.yy")}.txt",
log + Environment.NewLine);
Console.ForegroundColor = color;
Console.WriteLine(log);
Console.ResetColor();
}
private class WebhookContent
{
public string username = "Twitch Chat";
public string content;
public string avatar_url = "https://brand.twitch.tv/assets/logos/svg/glitch/purple.svg";
}
private static async Task SendWebhook(WebhookContent content)
{
if (_broadcasterOnly) return;
string json = JsonConvert.SerializeObject(content);
StringContent data = new StringContent(json, Encoding.UTF8, "application/json");
var url = (string) Config.GetValue("DiscordWebhook");
var client = new HttpClient();
await client.PostAsync(url, data);
client.Dispose();
}
private static void ConnectSwitch(string ip, int port = 6000)
{
_connection = new SwitchConnectionAsync(ip, port);
_connection.Connect();
if (_connection.Connected)
{
Log($"Connected to nintendo switch on {_connection.IP}:{_connection.Port}!", ConsoleColor.Green);
Log($"Say \"exit\" in twitch or press any key to quit the application!", ConsoleColor.Green);
}
}
public static void Main()
{
Log(
$@"{Environment.NewLine} _____ _ _ _ ____ _ ____ _ _ _
|_ ___ _(_| |_ ___| |__ | _ \| | __ _ _ _ ___/ _____ _(_| |_ ___| |__
| | \ \ /\ / | | __/ __| '_ \| |_) | |/ _` | | | / __\___ \ \ /\ / | | __/ __| '_ \
| | \ V V /| | || (__| | | | __/| | (_| | |_| \__ \___) \ V V /| | || (__| | | |
|_| \_/\_/ |_|\__\___|_| |_|_| |_|\__,_|\__, |___|____/ \_/\_/ |_|\__\___|_| |_|
|___/", ConsoleColor.Green);
ConnectSwitch((string) NSwitch.GetValue("IP"));
Bot bot = new Bot();
Console.ReadLine();
}
class Bot
{
TwitchClient _client;
TwitchAPI api;
public Bot()
{
api = new TwitchAPI();
api.Settings.ClientId = (string) Config.GetValue("ClientID");
api.Settings.AccessToken = (string) Config.GetValue("AccessToken");
ConnectionCredentials credentials =
new ConnectionCredentials((string) Config.GetValue("username"), (string) Config.GetValue("OAuth"));
var clientOptions = new ClientOptions
{
MessagesAllowedInPeriod = 750,
ThrottlingPeriod = TimeSpan.FromSeconds(30)
};
WebSocketClient customClient = new WebSocketClient(clientOptions);
_client = new TwitchClient(customClient);
_client.Initialize(credentials, (string) Config.GetValue("username"));
_client.OnLog += Client_OnLog;
_client.OnMessageReceived += Client_OnMessageReceived;
_client.OnConnected += Client_OnConnected;
_client.Connect();
}
private void Client_OnLog(object sender, OnLogArgs e)
{
Log($"{e.BotUsername} - {e.Data}");
}
private void Client_OnConnected(object sender, OnConnectedArgs e)
{
Log($"Connected to {e.AutoJoinChannel}", ConsoleColor.Green);
}
private async void Client_OnMessageReceived(object sender, OnMessageReceivedArgs e)
{
User user = await api.V5.Users.GetUserByIDAsync(e.ChatMessage.UserId);
WebhookContent webhookContent = new WebhookContent();
if (user.CreatedAt > DateTime.Now.AddDays(-7))
{
Log($"User {e.ChatMessage.DisplayName} account is too new: {user.CreatedAt}", ConsoleColor.DarkRed);
_client.SendMessage(e.ChatMessage.Channel, "Your account is too new... Wait a little more...");
webhookContent.username = "!WARNING!";
webhookContent.avatar_url = "https://upload.wikimedia.org/wikipedia/en/thumb/1/15/Ambox_warning_pn.svg/1178px-Ambox_warning_pn.svg.png";
webhookContent.content = $"User `{e.ChatMessage.DisplayName}` account is too new... Created at: `{user.CreatedAt}`";
SendWebhook(webhookContent);
}
else if (_broadcasterOnly && !e.ChatMessage.IsBroadcaster)
_client.SendMessage(e.ChatMessage.Channel, "Bot is in Broadcaster only mode.");
else
HandleInput(e, _client);
webhookContent.username = e.ChatMessage.DisplayName;
webhookContent.avatar_url = user.Logo;
webhookContent.content = e.ChatMessage.Message;
SendWebhook(webhookContent);
}
}
private static async Task HandleInput(OnMessageReceivedArgs message, TwitchClient client)
{
string msg = message.ChatMessage.Message;
string args = msg.ToUpper();
string[] words = args.Split(' ');
switch (args)
{
case "HELP":
client.SendMessage(message.ChatMessage.Channel, "You get to control the Nintendo Switch!");
client.SendMessage(message.ChatMessage.Channel, "You can say any of the following and they will execute on the console! They can also be chained together");
client.SendMessage(message.ChatMessage.Channel, $"{string.Join(" ", Button)} {string.Join(" ", Stick)}");
client.SendMessage(message.ChatMessage.Channel, "You can specify \"slower\", \"slow\" or \"medium\" to control the speed of the joystick");
client.SendMessage(message.ChatMessage.Channel, "You can also add \"short\" or \"long\" to control the duration of how long the joystick is held");
return;
case "EXIT GAME":
{
if (message.ChatMessage.IsBroadcaster)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.HOME),
cancellationToken.Token);
cancellationToken.Cancel();
Thread.Sleep(500);
cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.X),
cancellationToken.Token);
cancellationToken.Cancel();
Thread.Sleep(500);
cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.A),
cancellationToken.Token);
cancellationToken.Cancel();
Log("Game exited", ConsoleColor.Red);
client.SendMessage(message.ChatMessage.Channel, "Game exited");
}
else
{
client.SendMessage(message.ChatMessage.Channel,
"Command only available for the broadcaster.");
}
break;
}
case "EXIT":
{
if (message.ChatMessage.IsBroadcaster)
{
_connection.Disconnect();
Log("Bye bye!", ConsoleColor.Red);
client.SendMessage(message.ChatMessage.Channel, "Bye bye!");
Environment.Exit(1);
}
else
{
client.SendMessage(message.ChatMessage.Channel,
"Command only available for the broadcaster.");
}
break;
}
case "RESTART":
{
if (message.ChatMessage.IsBroadcaster)
{
_connection.Disconnect();
Log("Restarting!!!", ConsoleColor.DarkRed);
client.SendMessage(message.ChatMessage.Channel, "Restarting");
ConnectSwitch((string) NSwitch.GetValue("IP"));
}
else
{
client.SendMessage(message.ChatMessage.Channel,
"Command only available for the broadcaster.");
}
break;
}
case "HOME":
{
if (message.ChatMessage.IsBroadcaster)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.Click(SwitchButton.HOME),
cancellationToken.Token);
cancellationToken.Cancel();
}
else
{
client.SendMessage(message.ChatMessage.Channel,
"Command only available for the broadcaster.");
}
break;
}
case "BROADCASTERONLY":
if (message.ChatMessage.IsBroadcaster)
{
if (_broadcasterOnly)
{
_broadcasterOnly = false;
Log($"BroadcasterOnly mode turned off: {_broadcasterOnly}", ConsoleColor.Green);
client.SendMessage(message.ChatMessage.Channel,
"Bot is no longer in Broadcaster only mode.");
}
else
{
_broadcasterOnly = true;
Log($"BroadcasterOnly mode turned on: {_broadcasterOnly}", ConsoleColor.Red);
client.SendMessage(message.ChatMessage.Channel, "Bot is now in Broadcaster only mode.");
}
}
else
{
client.SendMessage(message.ChatMessage.Channel,
"Command only available for the broadcaster.");
}
break;
}
if (Stick.Any(args.Contains))
{
short speed = short.MaxValue;
int hold = 1000;
if (args.Contains("SLOWER"))
{
speed = 8000;
//speed = 10000;
}
else if (args.Contains("SLOW"))
{
speed = 10000;
//speed = 16382;
}
else if (args.Contains("MEDIUM"))
{
speed = 16382;
//speed = 20000;
}
if (args.Contains("SHORT"))
{
hold = 500;
}
else if (args.Contains("LONG"))
{
hold = 5000;
}
foreach (var word in words)
{
if (Array.Exists(Stick, e => e == word))
{
short x = 0;
short y = 0;
SwitchStick stick;
StickMovement stickMovement = new StickMovement {Hold = hold};
Log($"{message.ChatMessage.DisplayName} moved stick {word}", ConsoleColor.Green);
switch (word)
{
case "LSU":
stick = SwitchStick.LEFT;
x = 0;
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, 0, speed);
break;
case "LSUL":
stick = SwitchStick.LEFT;
x = short.Parse((speed * -1).ToString());
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), speed);
break;
case "LSUR":
stick = SwitchStick.LEFT;
x = speed;
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, speed, speed);
break;
case "LSD":
stick = SwitchStick.LEFT;
x = 0;
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, 0, short.Parse((speed * -1).ToString()));
break;
case "LSDL":
stick = SwitchStick.LEFT;
x = short.Parse((speed * -1).ToString());
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), short.Parse((speed * -1).ToString()));
break;
case "LSDR":
stick = SwitchStick.LEFT;
x = speed;
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, speed, short.Parse((speed * -1).ToString()));
break;
case "LSL":
stick = SwitchStick.LEFT;
x = short.Parse((speed * -1).ToString());
y = 0;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, short.Parse((speed * -1).ToString()), 0);
break;
case "LSR":
stick = SwitchStick.LEFT;
x = speed;
y = 0;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.LEFT, speed, 0);
break;
case "RSU":
stick = SwitchStick.RIGHT;
x = 0;
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, 0, speed);
break;
case "RSD":
stick = SwitchStick.RIGHT;
x = 0;
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, 0, short.Parse((speed * -1).ToString()));
break;
case "RSL":
stick = SwitchStick.RIGHT;
x = short.Parse((speed * -1).ToString());
y = 0;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, short.Parse((speed * -1).ToString()), 0);
break;
case "RSR":
stick = SwitchStick.RIGHT;
x = speed;
y = 0;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, speed, 0);
break;
case "RSUL":
stick = SwitchStick.RIGHT;
x = short.Parse((speed * -1).ToString());
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, short.Parse((speed * -1).ToString()), speed);
break;
case "RSUR":
stick = SwitchStick.RIGHT;
x = speed;
y = speed;
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, speed, speed);
break;
case "RSDL":
stick = SwitchStick.RIGHT;
x = short.Parse((speed * -1).ToString());
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, short.Parse((speed * -1).ToString()), short.Parse((speed * -1).ToString()));
break;
case "RSDR":
stick = SwitchStick.RIGHT;
x = speed;
y = short.Parse((speed * -1).ToString());
stickMovement.Stick = stick;
stickMovement.X = x;
stickMovement.Y = y;
//MoveStick(SwitchStick.RIGHT, speed, short.Parse((speed * -1).ToString()));
break;
}
Log("QUEUED", ConsoleColor.Yellow);
StickQueue.Enqueue(stickMovement);
}
}
foreach (StickMovement stick in StickQueue)
{
Log($"Moving {stick.Stick} stick x: {stick.X} y: {stick.Y} hold: {stick.Hold}", ConsoleColor.Red);
await MoveStick(stick.Stick, stick.X, stick.Y, stick.Hold);
}
StickQueue.Clear();
}
if (Button.Any(args.Contains))
{
foreach (var word in words)
{
if (Array.Exists(Button, e => e == word))
{
SwitchButton button = SwitchButton.CAPTURE; // Capture button is never used, let's use it as a "null" value
Log($"{message.ChatMessage.DisplayName} Pressed button {word}", ConsoleColor.Green);
switch (word)
{
case "DLEFT":
button = SwitchButton.DLEFT;
//PressButton(SwitchButton.DLEFT);
break;
case "DRIGHT":
button = SwitchButton.DRIGHT;
//PressButton(SwitchButton.DRIGHT);
break;
case "DUP":
button = SwitchButton.DUP;
//PressButton(SwitchButton.DUP);
break;
case "DDOWN":
button = SwitchButton.DDOWN;
//PressButton(SwitchButton.DDOWN);
break;
case "A":
button = SwitchButton.A;
//PressButton(SwitchButton.A);
break;
case "B":
button = SwitchButton.B;
//PressButton(SwitchButton.B);
break;
case "X":
button = SwitchButton.X;
//PressButton(SwitchButton.X);
break;
case "Y":
button = SwitchButton.Y;
//PressButton(SwitchButton.Y);
break;
case "+":
button = SwitchButton.PLUS;
//PressButton(SwitchButton.PLUS);
break;
case "-":
button = SwitchButton.MINUS;
//PressButton(SwitchButton.MINUS);
break;
case "ZL":
button = SwitchButton.ZL;
//PressButton(SwitchButton.ZL);
break;
case "ZR":
button = SwitchButton.ZR;
//PressButton(SwitchButton.ZR);
break;
case "L":
button = SwitchButton.L;
//PressButton(SwitchButton.L);
break;
case "R":
button = SwitchButton.R;
//PressButton(SwitchButton.R);
break;
case "LSP":
button = SwitchButton.LSTICK;
//PressButton(SwitchButton.LSTICK);
break;
case "RSP":
button = SwitchButton.RSTICK;
//PressButton(SwitchButton.RSTICK);
break;
}
Log("QUEUED", ConsoleColor.Yellow);
if (button != SwitchButton.CAPTURE
) // Capture button is never used, let's use it as a "null" value
ButtonQueue.Enqueue(button);
}
}
foreach (SwitchButton button in ButtonQueue)
{
Log($"Pressed {button}", ConsoleColor.Red);
await PressButton(button);
}
ButtonQueue.Clear();
}
}
private static async Task PressButton(SwitchButton button)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
if (button == SwitchButton.ZL || button == SwitchButton.ZR)
{
await _connection.SendAsync(SwitchCommand.Hold(button), cancellationToken.Token);
Thread.Sleep(2000);
await _connection.SendAsync(SwitchCommand.Release(button), cancellationToken.Token);
}
else
{
await _connection.SendAsync(SwitchCommand.Click(button), cancellationToken.Token);
}
Thread.Sleep(500);
cancellationToken.Cancel();
//StickQueue.Clear();
}
private static async Task MoveStick(SwitchStick stick, short x, short y, int hold)
{
CancellationTokenSource cancellationToken = new CancellationTokenSource();
await _connection.SendAsync(SwitchCommand.SetStick(stick, x, y), cancellationToken.Token);
//.Sleep(stick == SwitchStick.RIGHT ? 500 : 1000);
Thread.Sleep(hold);
await _connection.SendAsync(SwitchCommand.ResetStick(stick), cancellationToken.Token);
cancellationToken.Cancel();
//ButtonQueue.Clear();
}
}
}

View file

@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
<RootNamespace>TwitchPlaySwitch</RootNamespace>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Discord.Net" Version="2.2.0" />
<PackageReference Include="TwitchLib" Version="3.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\SysBot.NET\SysBot.Base\SysBot.Base.csproj" />
</ItemGroup>
</Project>

61
readme.md Normal file
View file

@ -0,0 +1,61 @@
# DiscordPlaysSwitch/TwitchPlaysSwitch
My attempt at making TwitchPlays type of thing with homebrew on my nintendo switch.
I'm not responsible for any ban that may happen to your account or console!
NOTE: I learned C# as i was doing this, therefore the code might not be of high quality
## Thing required
* [A non-ipatched switch](https://gbatemp.net/threads/switch-informations-by-serial-number-read-the-first-post-before-asking-questions.481215/) with [Atmosphere cfw](https://github.com/Atmosphere-NX/Atmosphere/) and [sys-botbase](https://github.com/olliz0r/sys-botbase)
* [SysBot.NET](https://github.com/kwsch/SysBot.NET) ( Included as a submodule in this repo )
* [SysDVR](https://github.com/exelix11/SysDVR/) ( Only for DiscordPlaysSwitch )
* [ffmpeg](https://ffmpeg.org/) ( Only for DiscordPlaysSwitch )
* [ldn_mitm](https://github.com/spacemeowx2/ldn_mitm) ( If playing a game that use local play like pokémon sword/shield )
**Don't forget to clone the submodule too!**
## DiscordPlaysSwitch
Currently DiscordPlaysSwitch also require SysDVR but it could be easily modified to use something else like a capture card.
This version might not be up-to-date compared to TwitchPlaysSwitch.
### config.json example
```json
{
"token": "Discord bot token",
"prefix": "Discord bot prefix ",
"nSwitch": {
"IP": "Nintendo switch IP",
"sysbotPORT": "6000",
"sysDVRPORT": "6666"
}
}
```
## TwitchPlaysSwitch
The capture is obviously done via another software so no change needed whether you use a capture card or sys-DVR.
### config.json example
```json
{
"username": "Twitch username",
"OAuth": "Twitch OAuth token",
"ClientID": "Twitch Client ID",
"AccessToken": "Twitch Access Token",
"DiscordWebhook": "Discord webhook to send messages to",
"nSwitch": {
"IP": "Nintendo Switch IP",
"sysbotPORT": "6000"
}
}
```
Thanks to [Jetbrains](https://www.jetbrains.com/?from=Hahayesdiscordbot) for providing their IDE free of charges!
<img src="https://its.gamingti.me/XT8F.svg" width=20%></img>