Skip to content

Commit 1c4ba99

Browse files
committed
#52 Synology Chat WIP. Messaging working, but looks like the config will need a reference to SynoAI's URL to get the images from the ImageController.
1 parent 6ae06e9 commit 1c4ba99

8 files changed

+160
-4
lines changed

SynoAI/Controllers/ImageController.cs

+1-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@ namespace SynoAI.Controllers
66
public class ImageController : Controller
77
{
88
/// <summary>
9-
/// Return snapshot image as JPEG, either in original size or a scaled down version, if asked.
10-
//// In order to use System.Drawing.Common
11-
//// In Terminal, issue: dotnet add SynoAI package System.Drawing.Common
9+
/// Returns the file for the specified camera.
1210
/// </summary>
1311
[Route("Image/{cameraName}/{filename}")]
1412
public ActionResult Get(string cameraName, string filename)

SynoAI/Notifiers/NotifierFactory.cs

+4
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using SynoAI.Notifiers.Email;
44
using SynoAI.Notifiers.Pushbullet;
55
using SynoAI.Notifiers.Pushover;
6+
using SynoAI.Notifiers.SynologyChat;
67
using SynoAI.Notifiers.Telegram;
78
using SynoAI.Notifiers.Webhook;
89
using System;
@@ -31,6 +32,9 @@ public static INotifier Create(NotifierType type, ILogger logger, IConfiguration
3132
case NotifierType.Pushover:
3233
factory = new PushoverFactory();
3334
break;
35+
case NotifierType.SynologyChat:
36+
factory = new SynologyChatFactory();
37+
break;
3438
case NotifierType.Telegram:
3539
factory = new TelegramFactory();
3640
break;

SynoAI/Notifiers/NotifierType.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,16 @@ public enum NotifierType
1919
/// </summary>
2020
Pushover,
2121
/// <summary>
22+
/// Sends a notification message and image using the SynologyChat API.
23+
/// </summary>
24+
SynologyChat,
25+
/// <summary>
2226
/// Sends a notification to Telegram with the image attached.
2327
/// </summary>
2428
Telegram,
2529
/// <summary>
2630
/// Calls a webhook with the image attached.
2731
/// </summary>
28-
Webhook
32+
Webhook,
2933
}
3034
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
using Microsoft.Extensions.Logging;
2+
using Newtonsoft.Json;
3+
using SynoAI.Models;
4+
using SynoAI.Services;
5+
using System;
6+
using System.Collections.Generic;
7+
using System.IO;
8+
using System.Linq;
9+
using System.Net.Http;
10+
using System.Net.Http.Headers;
11+
using System.Net.Http.Json;
12+
using System.Text;
13+
using System.Threading.Tasks;
14+
15+
namespace SynoAI.Notifiers.SynologyChat
16+
{
17+
/// <summary>
18+
/// Calls a third party API.
19+
/// </summary>
20+
public class SynologyChat : NotifierBase
21+
{
22+
/// <summary>
23+
/// The URL to send the request to including the token.
24+
/// </summary>
25+
public string Url { get; set; }
26+
27+
/// <summary>
28+
/// Sends a notification to the Webhook.
29+
/// </summary>
30+
/// <param name="camera">The camera that triggered the notification.</param>
31+
/// <param name="notification">The notification data to process.</param>
32+
/// <param name="logger">A logger.</param>
33+
public override async Task SendAsync(Camera camera, Notification notification, ILogger logger)
34+
{
35+
logger.LogInformation($"{camera.Name}: SynologyChat: Processing");
36+
using (HttpClient client = new())
37+
{
38+
IEnumerable<string> foundTypes = notification.FoundTypes;
39+
string message = GetMessage(camera, foundTypes);
40+
41+
var request = new
42+
{
43+
text = message,
44+
file_url = new Uri(new Uri(Config.Url), new Uri($"Image/{camera.Name}/{notification.ProcessedImage.FileName}", UriKind.Relative))
45+
};
46+
47+
string requestJson = JsonConvert.SerializeObject(request);
48+
Dictionary<string, string> payload = new()
49+
{
50+
{ "payload", requestJson },
51+
};
52+
53+
using (FormUrlEncodedContent content = new(payload))
54+
{
55+
content.Headers.Clear();
56+
content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");
57+
58+
logger.LogInformation($"{camera.Name}: SynologyChat: POSTing message.");
59+
60+
HttpResponseMessage response = await client.PostAsync(Url, content);
61+
if (response.IsSuccessStatusCode)
62+
{
63+
// Check that it's actually successful, because Synology like to make things awkward
64+
string responseString = await response.Content.ReadAsStringAsync();
65+
SynologyChatResponse actualResponse = JsonConvert.DeserializeObject<SynologyChatResponse>(responseString);
66+
if (actualResponse.Success)
67+
{
68+
logger.LogInformation($"{camera.Name}: SynologyChat: Success.");
69+
}
70+
else
71+
{
72+
logger.LogInformation($"{camera.Name}: SynologyChat: Failed with error '{actualResponse.Error.Code}': {actualResponse.Error.Errors}.");
73+
}
74+
}
75+
else
76+
{
77+
logger.LogWarning($"{camera.Name}: SynologyChat: The end point responded with HTTP status code '{response.StatusCode}'.");
78+
}
79+
}
80+
}
81+
}
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using Newtonsoft.Json;
2+
3+
namespace SynoAI.Notifiers.SynologyChat
4+
{
5+
public class SynologyChatErrorReasonResponse
6+
{
7+
[JsonProperty("name")]
8+
public string Name { get; set; }
9+
[JsonProperty("reason")]
10+
public string Reason { get; set; }
11+
12+
public override string ToString()
13+
{
14+
return $"{Name} ({Reason})";
15+
}
16+
}
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using Newtonsoft.Json;
2+
using System.Collections.Generic;
3+
4+
namespace SynoAI.Notifiers.SynologyChat
5+
{
6+
public class SynologyChatErrorResponse
7+
{
8+
[JsonProperty("code")]
9+
public string Code { get; set; }
10+
[JsonProperty("errors")]
11+
public SynologyChatErrorReasonResponse Errors { get; set; }
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using Microsoft.Extensions.Configuration;
2+
using Microsoft.Extensions.Logging;
3+
4+
namespace SynoAI.Notifiers.SynologyChat
5+
{
6+
public class SynologyChatFactory : NotifierFactory
7+
{
8+
public override INotifier Create(ILogger logger, IConfigurationSection section)
9+
{
10+
using (logger.BeginScope(nameof(SynologyChatFactory)))
11+
{
12+
logger.LogInformation($"Processing {nameof(SynologyChat)} Config");
13+
14+
string url = section.GetValue<string>("Url");
15+
16+
SynologyChat webhook = new SynologyChat()
17+
{
18+
Url = url
19+
};
20+
21+
return webhook;
22+
}
23+
}
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using Newtonsoft.Json;
2+
3+
namespace SynoAI.Notifiers.SynologyChat
4+
{
5+
public class SynologyChatResponse
6+
{
7+
[JsonProperty("success")]
8+
public bool Success { get; set; }
9+
[JsonProperty("error")]
10+
public SynologyChatErrorResponse Error { get; set; }
11+
}
12+
}

0 commit comments

Comments
 (0)