You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
343 lines
15 KiB
C#
343 lines
15 KiB
C#
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");
|
|
}
|
|
}
|
|
} |