Files
Martin Barker 49ea2ba2a6 Added Support for Debug Logging
Updated a couple of variables for better memory use.
Added Support for ignoring specific streamers
Moved to using a SingletonFactory for Singlton Classes
No Longer Using MessageBox for disconnected message
Added better detection for disconnected to stop it poping with other problems
Added Window and menu option to open window to manage ignored streamers
2023-02-21 21:25:38 +00:00

102 lines
4.1 KiB
C#

using System.Net;
using System.Text;
using System.Web;
using System.IO;
namespace TwitchDesktopNotifications.Core
{
public class WebServer : SingletonFactory<WebServer>, Singleton
{
public int Port = 32584;
private HttpListener listener;
public String TwitchCode { get; private set; }
public String TwitchState { get; set; }
public void Start()
{
listener = new HttpListener();
listener.Prefixes.Add("http://127.0.0.1:" + Port.ToString() + "/");
listener.Prefixes.Add("http://localhost:" + Port.ToString() + "/");
listener.Start();
new Thread(new ThreadStart(ThreadManagedServer)).Start();
}
public event EventHandler CodeRecived;
public void Stop()
{
listener.Stop();
}
private void RespondConnection(HttpListenerRequest request, HttpListenerResponse response)
{
var query = HttpUtility.ParseQueryString(request.Url.Query);
if (request.HttpMethod == "GET" && query["state"] == this.TwitchState)
{
this.TwitchCode = query["code"];
response.StatusCode = (int)HttpStatusCode.OK;
response.ContentType = "text/html";
response.OutputStream.Write(Encoding.ASCII.GetBytes("<!DOCTYPE html><html><head><title>Twitch Connected!</title><style>p.title{font-size:20px;font-weight:bold;margin-top:0px;}.container{width:240px;border:2px solid #bf94ff;padding:20px;margin:auto;border-radius:10px;}button{margin-left:195px;}</style></head><body><div class=\"container\"><p class=\"title\">Twitch Desktop Notification</p><p class=\"msg\">Twitch has been success fully connected. Please close this tab.</p><button onclick=\"javascript:window.close();\">Close</button></div></body></html>"));
response.OutputStream.Close();
CodeRecived?.Invoke(this, new EventArgs());
}
else
{;
response.StatusCode = (int)HttpStatusCode.Forbidden;
response.ContentType = "text/html";
response.OutputStream.Write(Encoding.ASCII.GetBytes("<!DOCTYPE html><html><head><title>State Missmatch</title></head><body><h1>State Missmatch</h1><p>State does not match up preventing XSS.</p></body></html>"));
response.OutputStream.Close();
}
}
private void RespondFavicon(HttpListenerResponse response)
{
response.StatusCode = (int)HttpStatusCode.OK;
response.ContentType = "image/x-icon";
response.OutputStream.Write(File.ReadAllBytes("Assets/icon.ico"));
response.OutputStream.Close();
}
private void processRequestThread(object? obj)
{
HttpListenerContext context = (HttpListenerContext)obj;
HttpListenerRequest request = context.Request;
if (request.Url.AbsolutePath == "/favicon.ico")
{
RespondFavicon(context.Response);
}
else if (request.Url.AbsolutePath == "/twitchRedirect")
{
RespondConnection(request, context.Response);
}
else
{
HttpListenerResponse response = context.Response;
response.StatusCode = (int)HttpStatusCode.NotFound;
response.ContentType = "text/html";
response.OutputStream.Write(Encoding.ASCII.GetBytes("<!DOCTYPE html><html><head><title>Not Found</title></head><body><h1>Not Found</h1><p>File not found</p></body></html>"));
response.OutputStream.Close();
}
}
private void ThreadManagedServer()
{
while (listener.IsListening)
{
try
{
HttpListenerContext context = listener.GetContext();
ParameterizedThreadStart pts = new ParameterizedThreadStart(processRequestThread);
pts.Invoke(context);
}
catch (Exception e)
{
}
}
}
}
}