diff --git a/Ombi.Api.Interfaces/IMattermostApi.cs b/Ombi.Api.Interfaces/IMattermostApi.cs new file mode 100644 index 000000000..281902277 --- /dev/null +++ b/Ombi.Api.Interfaces/IMattermostApi.cs @@ -0,0 +1,37 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: IMattermostApi.cs +// Created By: Michel Zaleski +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System.Threading.Tasks; +using Ombi.Api.Models.Notifications; + +namespace Ombi.Api.Interfaces +{ + public interface IMattermostApi + { + Task PushAsync(string webhook, MattermostNotificationBody message); + } +} \ No newline at end of file diff --git a/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj b/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj index cf50e513d..ca7ad260c 100644 --- a/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj +++ b/Ombi.Api.Interfaces/Ombi.Api.Interfaces.csproj @@ -65,6 +65,7 @@ + diff --git a/Ombi.Api.Models/Notifications/MattermostNotificationBody.cs b/Ombi.Api.Models/Notifications/MattermostNotificationBody.cs new file mode 100644 index 000000000..0c5b17685 --- /dev/null +++ b/Ombi.Api.Models/Notifications/MattermostNotificationBody.cs @@ -0,0 +1,45 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: MattermostNotificationBody.cs +// Created By: Michel Zaleski +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using Newtonsoft.Json; + +namespace Ombi.Api.Models.Notifications +{ + public class MattermostNotificationBody + { + [JsonConstructor] + public MattermostNotificationBody() + { + username = "Ombi"; + } + + public string username { get; set; } = "Ombi"; + public string channel { get; set; } + public string text { get; set; } + public string icon_url { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Api.Models/Ombi.Api.Models.csproj b/Ombi.Api.Models/Ombi.Api.Models.csproj index e13506d5b..b35217e12 100644 --- a/Ombi.Api.Models/Ombi.Api.Models.csproj +++ b/Ombi.Api.Models/Ombi.Api.Models.csproj @@ -96,6 +96,7 @@ + diff --git a/Ombi.Api/MattermostApi.cs b/Ombi.Api/MattermostApi.cs new file mode 100644 index 000000000..9edbef7b6 --- /dev/null +++ b/Ombi.Api/MattermostApi.cs @@ -0,0 +1,58 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: PlexApi.cs +// Created By: Michel Zaleski +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Threading.Tasks; +using Ombi.Api.Interfaces; +using Ombi.Api.Models.Notifications; +using RestSharp; + +namespace Ombi.Api +{ + public class MattermostApi : IMattermostApi + { + public async Task PushAsync(string webhook, MattermostNotificationBody message) + { + var request = new RestRequest + { + Method = Method.POST, + Resource = "/" + }; + + request.AddJsonBody(message); + + var api = new ApiRequest(); + return await Task.Run( + () => + { + var result = api.Execute(request, new Uri(webhook)); + return result.Content; + }); + } + } +} + diff --git a/Ombi.Api/Ombi.Api.csproj b/Ombi.Api/Ombi.Api.csproj index d004e1c3f..7c628391e 100644 --- a/Ombi.Api/Ombi.Api.csproj +++ b/Ombi.Api/Ombi.Api.csproj @@ -85,6 +85,7 @@ + diff --git a/Ombi.Core/Notification/NotificationMessageResolver.cs b/Ombi.Core/Notification/NotificationMessageResolver.cs index f5f0b90f9..fee5eeb00 100644 --- a/Ombi.Core/Notification/NotificationMessageResolver.cs +++ b/Ombi.Core/Notification/NotificationMessageResolver.cs @@ -70,6 +70,9 @@ namespace Ombi.Core.Notification case TransportType.Slack: content = notification.SlackNotification; break; + case TransportType.Mattermost: + content = notification.MattermostNotification; + break; default: throw new ArgumentOutOfRangeException(nameof(transportType), transportType, null); } diff --git a/Ombi.Core/Notification/TransportType.cs b/Ombi.Core/Notification/TransportType.cs index f37ab4404..fbed9b3b0 100644 --- a/Ombi.Core/Notification/TransportType.cs +++ b/Ombi.Core/Notification/TransportType.cs @@ -31,6 +31,7 @@ namespace Ombi.Core.Notification Email, Pushbullet, Pushover, - Slack + Slack, + Mattermost } } \ No newline at end of file diff --git a/Ombi.Core/Ombi.Core.csproj b/Ombi.Core/Ombi.Core.csproj index 3ad547420..9c2660df3 100644 --- a/Ombi.Core/Ombi.Core.csproj +++ b/Ombi.Core/Ombi.Core.csproj @@ -138,6 +138,7 @@ + diff --git a/Ombi.Core/SettingModels/MattermostNotificationSettings.cs b/Ombi.Core/SettingModels/MattermostNotificationSettings.cs new file mode 100644 index 000000000..03ae5af3e --- /dev/null +++ b/Ombi.Core/SettingModels/MattermostNotificationSettings.cs @@ -0,0 +1,13 @@ +using System; +using Newtonsoft.Json; + +namespace Ombi.Core.SettingModels +{ + public sealed class MattermostNotificationSettings : NotificationSettings + { + public string WebhookUrl { get; set; } + public string Channel { get; set; } + public string Username { get; set; } + public string IconUrl { get; set; } + } +} \ No newline at end of file diff --git a/Ombi.Core/SettingModels/NotificationSettingsV2.cs b/Ombi.Core/SettingModels/NotificationSettingsV2.cs index 2380d70f1..cf0209692 100644 --- a/Ombi.Core/SettingModels/NotificationSettingsV2.cs +++ b/Ombi.Core/SettingModels/NotificationSettingsV2.cs @@ -51,11 +51,13 @@ namespace Ombi.Core.SettingModels } }; SlackNotification = new List(); + MattermostNotification = new List(); PushoverNotification = new List(); PushbulletNotification = new List(); } public List EmailNotification { get; set; } public List SlackNotification { get; set; } + public List MattermostNotification { get; set; } public List PushbulletNotification { get; set; } public List PushoverNotification { get; set; } } diff --git a/Ombi.Services/Jobs/PlexUserChecker.cs b/Ombi.Services/Jobs/PlexUserChecker.cs index 1ea679b02..4e888c72e 100644 --- a/Ombi.Services/Jobs/PlexUserChecker.cs +++ b/Ombi.Services/Jobs/PlexUserChecker.cs @@ -190,10 +190,22 @@ namespace Ombi.Services.Jobs LoginId = Guid.NewGuid().ToString() }; - a.Permissions += (int)Permissions.Administrator; // Make admin + a.Permissions += (int) Permissions.Administrator; // Make admin Repo.Insert(a); } + else + { + // does the account need updating? + if (dbMainAcc != null) + { + dbMainAcc.PlexUserId = mainPlexAccount.Id; + dbMainAcc.EmailAddress = mainPlexAccount.Email; + dbMainAcc.Username = mainPlexAccount.Username; + + Repo.Update(dbMainAcc); + } + } } diff --git a/Ombi.Services/Notification/MattermostNotification.cs b/Ombi.Services/Notification/MattermostNotification.cs new file mode 100644 index 000000000..671974bf5 --- /dev/null +++ b/Ombi.Services/Notification/MattermostNotification.cs @@ -0,0 +1,156 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: MattermostNotification.cs +// Created By: Michel Zaleski +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using System; +using System.Threading.Tasks; +using NLog; +using Ombi.Api.Interfaces; +using Ombi.Api.Models.Notifications; +using Ombi.Core; +using Ombi.Core.Models; +using Ombi.Core.SettingModels; +using Ombi.Services.Interfaces; + +namespace Ombi.Services.Notification +{ + public class MattermostNotification : INotification + { + public MattermostNotification(IMattermostApi api, ISettingsService sn) + { + Api = api; + Settings = sn; + } + + public string NotificationName => "MattermostNotification"; + + private IMattermostApi Api { get; } + private ISettingsService Settings { get; } + private static Logger Log = LogManager.GetCurrentClassLogger(); + + + public async Task NotifyAsync(NotificationModel model) + { + var settings = Settings.GetSettings(); + + await NotifyAsync(model, settings); + } + + public async Task NotifyAsync(NotificationModel model, Settings settings) + { + if (settings == null) await NotifyAsync(model); + + var pushSettings = (MattermostNotificationSettings)settings; + if (!ValidateConfiguration(pushSettings)) + { + Log.Error("Settings for Mattermost was not correct, we cannot push a notification"); + return; + } + + switch (model.NotificationType) + { + case NotificationType.NewRequest: + await PushNewRequestAsync(model, pushSettings); + break; + case NotificationType.Issue: + await PushIssueAsync(model, pushSettings); + break; + case NotificationType.RequestAvailable: + break; + case NotificationType.RequestApproved: + break; + case NotificationType.AdminNote: + break; + case NotificationType.Test: + await PushTest(pushSettings); + break; + case NotificationType.RequestDeclined: + break; + case NotificationType.ItemAddedToFaultQueue: + await PushFaultQueue(model, pushSettings); + break; + default: + throw new ArgumentOutOfRangeException(); + } + } + + private async Task PushNewRequestAsync(NotificationModel model, MattermostNotificationSettings settings) + { + var message = $"{model.Title} has been requested by user: {model.User}"; + await Push(settings, message); + } + + private async Task PushIssueAsync(NotificationModel model, MattermostNotificationSettings settings) + { + var message = $"A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}"; + await Push(settings, message); + } + + private async Task PushTest(MattermostNotificationSettings settings) + { + var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!"; + await Push(settings, message); + } + + private async Task PushFaultQueue(NotificationModel model, MattermostNotificationSettings settings) + { + var message = $"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying"; + await Push(settings, message); + } + + private async Task Push(MattermostNotificationSettings config, string message) + { + try + { + var notification = new MattermostNotificationBody { username = config.Username, channel = config.Channel ?? string.Empty, icon_url = config.IconUrl ?? string.Empty, text = message }; + + var result = await Api.PushAsync(config.WebhookUrl, notification); + if (!result.Equals("ok")) + { + Log.Error("Mattermost returned a message that was not 'ok', the notification did not get pushed"); + Log.Error($"Message that mattermost returned: {result}"); + } + } + catch (Exception e) + { + Log.Error(e); + } + } + + private bool ValidateConfiguration(MattermostNotificationSettings settings) + { + if (!settings.Enabled) + { + return false; + } + if (string.IsNullOrEmpty(settings.WebhookUrl)) + { + return false; + } + return true; + } + } +} \ No newline at end of file diff --git a/Ombi.Services/Ombi.Services.csproj b/Ombi.Services/Ombi.Services.csproj index d3ca25f5d..0eca0f558 100644 --- a/Ombi.Services/Ombi.Services.csproj +++ b/Ombi.Services/Ombi.Services.csproj @@ -157,6 +157,7 @@ + diff --git a/Ombi.UI.Tests/AdminModuleTests.cs b/Ombi.UI.Tests/AdminModuleTests.cs index 30da77591..5935f9c26 100644 --- a/Ombi.UI.Tests/AdminModuleTests.cs +++ b/Ombi.UI.Tests/AdminModuleTests.cs @@ -73,8 +73,10 @@ namespace Ombi.UI.Tests private Mock Cache { get; set; } private Mock> Log { get; set; } private Mock> SlackSettings { get; set; } + private Mock> MattermostSettings { get; set; } private Mock> LandingPageSettings { get; set; } private Mock SlackApi { get; set; } + private Mock MattermostApi { get; set; } private Mock Analytics { get; set; } private Mock> NotifyV2 { get; set; } private Mock RecentlyAdded { get; set; } @@ -114,6 +116,8 @@ namespace Ombi.UI.Tests Log = new Mock>(); SlackApi = new Mock(); SlackSettings = new Mock>(); + MattermostApi = new Mock(); + MattermostSettings = new Mock>(); LandingPageSettings = new Mock>(); ScheduledJobsSettingsMock = new Mock>(); RecorderMock = new Mock(); @@ -147,8 +151,10 @@ namespace Ombi.UI.Tests with.Dependency(Cache.Object); with.Dependency(Log.Object); with.Dependency(SlackApi.Object); + with.Dependency(MattermostApi.Object); with.Dependency(LandingPageSettings.Object); with.Dependency(SlackSettings.Object); + with.Dependency(MattermostSettings.Object); with.Dependency(ScheduledJobsSettingsMock.Object); with.Dependency(RecorderMock.Object); with.Dependency(RecentlyAdded.Object); diff --git a/Ombi.UI/Modules/Admin/AdminModule.cs b/Ombi.UI/Modules/Admin/AdminModule.cs index f3c8acb8a..60de03907 100644 --- a/Ombi.UI/Modules/Admin/AdminModule.cs +++ b/Ombi.UI/Modules/Admin/AdminModule.cs @@ -87,9 +87,11 @@ namespace Ombi.UI.Modules.Admin private INotificationService NotificationService { get; } private ICacheProvider Cache { get; } private ISettingsService SlackSettings { get; } + private ISettingsService MattermostSettings { get; } private ISettingsService LandingSettings { get; } private ISettingsService ScheduledJobSettings { get; } private ISlackApi SlackApi { get; } + private IMattermostApi MattermostApi { get; } private IJobRecord JobRecorder { get; } private IAnalytics Analytics { get; } private IRecentlyAdded RecentlyAdded { get; } @@ -123,7 +125,8 @@ namespace Ombi.UI.Modules.Admin ISettingsService headphones, ISettingsService logs, ICacheProvider cache, ISettingsService slackSettings, - ISlackApi slackApi, ISettingsService lp, + ISlackApi slackApi, ISettingsService mattermostSettings, + IMattermostApi mattermostApi, ISettingsService lp, ISettingsService scheduler, IJobRecord rec, IAnalytics analytics, ISettingsService notifyService, IRecentlyAdded recentlyAdded, IMassEmail massEmail, ISettingsService watcherSettings, @@ -154,6 +157,8 @@ namespace Ombi.UI.Modules.Admin Cache = cache; SlackSettings = slackSettings; SlackApi = slackApi; + MattermostSettings = mattermostSettings; + MattermostApi = mattermostApi; LandingSettings = lp; ScheduledJobSettings = scheduler; JobRecorder = rec; @@ -239,6 +244,10 @@ namespace Ombi.UI.Modules.Admin Get["/slacknotification"] = _ => SlackNotifications(); Post["/slacknotification"] = _ => SaveSlackNotifications(); + Post["/testmattermostnotification", true] = async (x, ct) => await TestMattermostNotification(); + Get["/mattermostnotification"] = _ => MattermostNotifications(); + Post["/mattermostnotification"] = _ => SaveMattermostNotifications(); + Post["/testdiscordnotification", true] = async (x, ct) => await TestDiscordNotification(); Get["/discordnotification", true] = async (x, ct) => await DiscordNotification(); Post["/discordnotification", true] = async (x, ct) => await SaveDiscordNotifications(); @@ -1051,6 +1060,71 @@ namespace Ombi.UI.Modules.Admin : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); } + private async Task TestMattermostNotification() + { + var settings = this.BindAndValidate(); + if (!ModelValidationResult.IsValid) + { + return Response.AsJson(ModelValidationResult.SendJsonError()); + } + var notificationModel = new NotificationModel + { + NotificationType = NotificationType.Test, + DateTime = DateTime.Now + }; + + var currentMattermostSettings = await MattermostSettings.GetSettingsAsync(); + try + { + NotificationService.Subscribe(new MattermostNotification(MattermostApi, MattermostSettings)); + settings.Enabled = true; + await NotificationService.Publish(notificationModel, settings); + Log.Info("Sent mattermost notification test"); + } + catch (Exception e) + { + Log.Error(e, "Failed to subscribe and publish test Mattermost Notification"); + } + finally + { + if (!currentMattermostSettings.Enabled) + { + NotificationService.UnSubscribe(new MattermostNotification(MattermostApi, MattermostSettings)); + } + } + return Response.AsJson(new JsonResponseModel { Result = true, Message = "Successfully sent a test Mattermost Notification! If you do not receive it please check the logs." }); + } + + private Negotiator MattermostNotifications() + { + var settings = MattermostSettings.GetSettings(); + return View["MattermostNotifications", settings]; + } + + private Response SaveMattermostNotifications() + { + var settings = this.BindAndValidate(); + if (!ModelValidationResult.IsValid) + { + return Response.AsJson(ModelValidationResult.SendJsonError()); + } + + var result = MattermostSettings.SaveSettings(settings); + if (settings.Enabled) + { + NotificationService.Subscribe(new MattermostNotification(MattermostApi, MattermostSettings)); + } + else + { + NotificationService.UnSubscribe(new MattermostNotification(MattermostApi, MattermostSettings)); + } + + Log.Info("Saved mattermost settings, result: {0}", result); + return Response.AsJson(result + ? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Mattermost Notifications!" } + : new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." }); + } + private async Task DiscordNotification() { var settings = await DiscordSettings.GetSettingsAsync(); diff --git a/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs b/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs index 083eb57d9..c8d40d081 100644 --- a/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs +++ b/Ombi.UI/Modules/Admin/ScheduledJobsRunnerModule.cs @@ -152,7 +152,7 @@ namespace Ombi.UI.Modules.Admin } if (key.Equals(JobNames.PlexUserChecker, StringComparison.CurrentCultureIgnoreCase)) { - RequestLimit.Start(); + PlexUserChecker.Start(); } if (key.Equals(JobNames.EmbyEpisodeCacher, StringComparison.CurrentCultureIgnoreCase)) { diff --git a/Ombi.UI/Modules/RequestsModule.cs b/Ombi.UI/Modules/RequestsModule.cs index 8fc65c515..b1222be9b 100644 --- a/Ombi.UI/Modules/RequestsModule.cs +++ b/Ombi.UI/Modules/RequestsModule.cs @@ -526,18 +526,21 @@ namespace Ombi.UI.Modules var result = await Service.UpdateRequestAsync(originalRequest); var plexSettings = await PlexSettings.GetSettingsAsync(); - if (plexSettings.Enable) + if (available) { - await - PlexNotificationEngine.NotifyUsers(originalRequest, - available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined); - } + if (plexSettings.Enable) + { + await + PlexNotificationEngine.NotifyUsers(originalRequest, + NotificationType.RequestAvailable); + } - var embySettings = await EmbySettings.GetSettingsAsync(); - if (embySettings.Enable) - { - await EmbyNotificationEngine.NotifyUsers(originalRequest, - available ? NotificationType.RequestAvailable : NotificationType.RequestDeclined); + var embySettings = await EmbySettings.GetSettingsAsync(); + if (embySettings.Enable) + { + await EmbyNotificationEngine.NotifyUsers(originalRequest, + NotificationType.RequestAvailable); + } } return Response.AsJson(result ? new { Result = true, Available = available, Message = string.Empty } diff --git a/Ombi.UI/NinjectModules/ApiModule.cs b/Ombi.UI/NinjectModules/ApiModule.cs index d8b40cb33..b7346cc44 100644 --- a/Ombi.UI/NinjectModules/ApiModule.cs +++ b/Ombi.UI/NinjectModules/ApiModule.cs @@ -44,6 +44,7 @@ namespace Ombi.UI.NinjectModules Bind().To(); Bind().To(); Bind().To(); + Bind().To(); Bind().To(); Bind().To(); Bind().To(); diff --git a/Ombi.UI/Ombi.UI.csproj b/Ombi.UI/Ombi.UI.csproj index 1118a196f..0c7273d8a 100644 --- a/Ombi.UI/Ombi.UI.csproj +++ b/Ombi.UI/Ombi.UI.csproj @@ -299,6 +299,7 @@ + @@ -834,6 +835,9 @@ Always + + Always + Always diff --git a/Ombi.UI/Startup.cs b/Ombi.UI/Startup.cs index 73ef53250..1ed5db99c 100644 --- a/Ombi.UI/Startup.cs +++ b/Ombi.UI/Startup.cs @@ -127,6 +127,10 @@ namespace Ombi.UI var slackSettings = slackService.GetSettings(); SubScribeOvserver(slackSettings, notificationService, new SlackNotification(container.Get(), slackService)); + var mattermostService = container.Get>(); + var mattermostSettings = mattermostService.GetSettings(); + SubScribeOvserver(mattermostSettings, notificationService, new MattermostNotification(container.Get(), mattermostService)); + var discordSettings = container.Get>(); var discordService = discordSettings.GetSettings(); SubScribeOvserver(discordService, notificationService, new DiscordNotification(container.Get(), discordSettings)); diff --git a/Ombi.UI/Validators/MattermostSettingsValidator.cs b/Ombi.UI/Validators/MattermostSettingsValidator.cs new file mode 100644 index 000000000..333762d79 --- /dev/null +++ b/Ombi.UI/Validators/MattermostSettingsValidator.cs @@ -0,0 +1,40 @@ +#region Copyright +// /************************************************************************ +// Copyright (c) 2016 Jamie Rees +// File: MattermostSettingsValidator.cs +// Created By: Michel Zaleski +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +// ************************************************************************/ +#endregion + +using FluentValidation; +using Ombi.Core.SettingModels; + +namespace Ombi.UI.Validators +{ + public class MattermostSettingsValidator : AbstractValidator + { + public MattermostSettingsValidator() + { + RuleFor(request => request.WebhookUrl).NotEmpty().WithMessage("You must specify a Webhook Url"); + } + } +} \ No newline at end of file diff --git a/Ombi.UI/Views/Admin/MattermostNotifications.cshtml b/Ombi.UI/Views/Admin/MattermostNotifications.cshtml new file mode 100644 index 000000000..b48256319 --- /dev/null +++ b/Ombi.UI/Views/Admin/MattermostNotifications.cshtml @@ -0,0 +1,127 @@ +@using Ombi.UI.Helpers +@Html.Partial("Shared/Partial/_Sidebar") + +
+
+
+ Mattermost Notifications + +
+
+ + @if (Model.Enabled) + { + + } + else + { + + } + +
+
+ +
+ + This is the full webhook url. + Mattermost > Integrations > Incoming Webhook > Add Incoming Webhook. You will then have a Webhook Url +
+ +
+
+ +
+ + You can override the default channel here +
+ +
+
+ +
+ + You can override the default username (Ombi) here +
+ +
+
+ +
+ + You can override the default icon here +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + \ No newline at end of file diff --git a/Ombi.UI/Views/Shared/Partial/_Sidebar.cshtml b/Ombi.UI/Views/Shared/Partial/_Sidebar.cshtml index 03d533097..bbf3abaa4 100644 --- a/Ombi.UI/Views/Shared/Partial/_Sidebar.cshtml +++ b/Ombi.UI/Views/Shared/Partial/_Sidebar.cshtml @@ -33,6 +33,7 @@ @Html.GetSidebarUrl(Context, "/admin/pushbulletnotification", "Pushbullet Notifications","fa fa-bell-o") @Html.GetSidebarUrl(Context, "/admin/pushovernotification", "Pushover Notifications", "fa fa-bell-o") @Html.GetSidebarUrl(Context, "/admin/slacknotification", "Slack Notifications", "fa fa-slack") + @Html.GetSidebarUrl(Context, "/admin/mattermostnotification", "Mattermost Notifications", "fa fa-bell-o") @Html.GetSidebarUrl(Context, "/admin/discordnotification", "Discord Notifications", "fa fa-bell-o")