Files
ntfysh-windows/ntfysh_client/NotificationListener.cs
2022-06-27 08:26:11 -03:00

155 lines
5.2 KiB
C#

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web;
namespace ntfysh_client
{
class NotificationListener : IDisposable
{
private HttpClient httpClient;
private bool disposedValue;
public Dictionary<string, StreamReader> subscribedTopics;
public delegate void NotificationReceiveHandler(object sender, NotificationReceiveEventArgs e);
public event NotificationReceiveHandler OnNotificationReceive;
public NotificationListener()
{
httpClient = new HttpClient();
subscribedTopics = new Dictionary<string, StreamReader>();
httpClient.Timeout = TimeSpan.FromMilliseconds(Timeout.Infinite);
ServicePointManager.DefaultConnectionLimit = 100;
}
public async Task SubscribeToTopic(string topicId)
{
HttpRequestMessage msg = new HttpRequestMessage(HttpMethod.Get, $"https://ntfy.sh/{HttpUtility.UrlEncode(topicId)}/json");
using (var response = await httpClient.SendAsync(msg, HttpCompletionOption.ResponseHeadersRead))
{
using (var body = await response.Content.ReadAsStreamAsync())
{
using (StreamReader reader = new StreamReader(body))
{
subscribedTopics.Add(topicId, reader);
try
{
// The loop will be broken when this stream is closed
while (true)
{
var line = await reader.ReadLineAsync();
Debug.WriteLine(line);
NtfyEventObject nev = JsonConvert.DeserializeObject<NtfyEventObject>(line);
if (nev.Event == "message")
{
if (OnNotificationReceive != null)
{
var evArgs = new NotificationReceiveEventArgs(nev.Title, nev.Message);
OnNotificationReceive(this, evArgs);
}
}
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
// If the topic is still registered, then that stream wasn't mean to be closed (maybe network failure?)
// Restart it
if (subscribedTopics.ContainsKey(topicId))
{
SubscribeToTopic(topicId);
}
}
}
}
}
}
public void RemoveTopic(string topicId)
{
Debug.WriteLine($"Removing topic {topicId}");
if (subscribedTopics.ContainsKey(topicId))
{
// Not moronic to store it in a variable; this solves a race condition in SubscribeToTopic
var topic = subscribedTopics[topicId];
subscribedTopics.Remove(topicId);
topic.Close();
}
}
protected virtual void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
// TODO: dispose managed state (managed objects)
}
// TODO: free unmanaged resources (unmanaged objects) and override finalizer
// TODO: set large fields to null
disposedValue = true;
}
}
// // TODO: override finalizer only if 'Dispose(bool disposing)' has code to free unmanaged resources
// ~NotificationListener()
// {
// // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
// Dispose(disposing: false);
// }
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
public class NotificationReceiveEventArgs : EventArgs
{
public string Title { get; private set; }
public string Message { get; private set; }
public NotificationReceiveEventArgs(string title, string message)
{
Title = title;
Message = message;
}
}
public class NtfyEventObject
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("time")]
public Int64 Time { get; set; }
[JsonProperty("event")]
public string Event { get; set; }
[JsonProperty("topic")]
public string Topic { get; set; }
[JsonProperty("message")]
public string Message { get; set; }
[JsonProperty("title")]
public string Title { get; set; }
}
}