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
102 lines
4.1 KiB
C#
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)
|
|
{
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|