mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-12 16:22:55 -07:00
Fixed some issues around the tv requests area
Added mattermost and telegram notifications #1459 #865 #1457
This commit is contained in:
parent
03e9852330
commit
bf043fc76e
48 changed files with 1164 additions and 192 deletions
10
src/Ombi.Api.Mattermost/IMattermostApi.cs
Normal file
10
src/Ombi.Api.Mattermost/IMattermostApi.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Mattermost.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Mattermost
|
||||||
|
{
|
||||||
|
public interface IMattermostApi
|
||||||
|
{
|
||||||
|
Task<string> PushAsync(string webhook, MattermostBody message);
|
||||||
|
}
|
||||||
|
}
|
27
src/Ombi.Api.Mattermost/MattermostApi.cs
Normal file
27
src/Ombi.Api.Mattermost/MattermostApi.cs
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Mattermost.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Mattermost
|
||||||
|
{
|
||||||
|
public class MattermostApi : IMattermostApi
|
||||||
|
{
|
||||||
|
public MattermostApi(IApi api)
|
||||||
|
{
|
||||||
|
_api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IApi _api;
|
||||||
|
|
||||||
|
public async Task<string> PushAsync(string webhook, MattermostBody message)
|
||||||
|
{
|
||||||
|
var request = new Request(string.Empty, webhook, HttpMethod.Post);
|
||||||
|
|
||||||
|
request.AddJsonBody(message);
|
||||||
|
|
||||||
|
var result = await _api.RequestContent(request);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
src/Ombi.Api.Mattermost/Models/MattermostBody.cs
Normal file
45
src/Ombi.Api.Mattermost/Models/MattermostBody.cs
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
#region Copyright
|
||||||
|
// /************************************************************************
|
||||||
|
// Copyright (c) 2017 Jamie Rees
|
||||||
|
// File: MattermostBody.cs
|
||||||
|
// Created By: Jamie Rees
|
||||||
|
//
|
||||||
|
// 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.Mattermost.Models
|
||||||
|
{
|
||||||
|
public class MattermostBody
|
||||||
|
{
|
||||||
|
[JsonConstructor]
|
||||||
|
public MattermostBody()
|
||||||
|
{
|
||||||
|
username = "Ombi";
|
||||||
|
}
|
||||||
|
|
||||||
|
public string username { get; set; } = "Ombi";
|
||||||
|
public string channel { get; set; }
|
||||||
|
public string text { get; set; }
|
||||||
|
public string icon_url { get; set; }
|
||||||
|
}
|
||||||
|
}
|
15
src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj
Normal file
15
src/Ombi.Api.Mattermost/Ombi.Api.Mattermost.csproj
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.6</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
10
src/Ombi.Api.Pushover/IPushoverApi.cs
Normal file
10
src/Ombi.Api.Pushover/IPushoverApi.cs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Pushover.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Pushover
|
||||||
|
{
|
||||||
|
public interface IPushoverApi
|
||||||
|
{
|
||||||
|
Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken);
|
||||||
|
}
|
||||||
|
}
|
12
src/Ombi.Api.Pushover/Models/PushoverResponse.cs
Normal file
12
src/Ombi.Api.Pushover/Models/PushoverResponse.cs
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Pushover.Models
|
||||||
|
{
|
||||||
|
public class PushoverResponse
|
||||||
|
{
|
||||||
|
public int status { get; set; }
|
||||||
|
public string request { get; set; }
|
||||||
|
}
|
||||||
|
}
|
11
src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj
Normal file
11
src/Ombi.Api.Pushover/Ombi.Api.Pushover.csproj
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard1.6</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Ombi.Api\Ombi.Api.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
26
src/Ombi.Api.Pushover/PushoverApi.cs
Normal file
26
src/Ombi.Api.Pushover/PushoverApi.cs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Ombi.Api.Pushover.Models;
|
||||||
|
|
||||||
|
namespace Ombi.Api.Pushover
|
||||||
|
{
|
||||||
|
public class PushoverApi : IPushoverApi
|
||||||
|
{
|
||||||
|
public PushoverApi(IApi api)
|
||||||
|
{
|
||||||
|
_api = api;
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IApi _api;
|
||||||
|
private const string PushoverEndpoint = "https://api.pushover.net/1";
|
||||||
|
|
||||||
|
public async Task<PushoverResponse> PushAsync(string accessToken, string message, string userToken)
|
||||||
|
{
|
||||||
|
var request = new Request($"messages.json?token={accessToken}&user={userToken}&message={message}", PushoverEndpoint, HttpMethod.Post);
|
||||||
|
|
||||||
|
var result = await _api.Request<PushoverResponse>(request);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -141,12 +141,9 @@ namespace Ombi.Core.Engine
|
||||||
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
|
public async Task<ChildRequests> UpdateChildRequest(ChildRequests request)
|
||||||
{
|
{
|
||||||
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
await Audit.Record(AuditType.Updated, AuditArea.TvRequest, $"Updated Request {request.Title}", Username);
|
||||||
var allRequests = TvRepository.GetChild();
|
|
||||||
var results = await allRequests.FirstOrDefaultAsync(x => x.Id == request.Id);
|
await TvRepository.UpdateChild(request);
|
||||||
|
return request;
|
||||||
// TODO need to check if we need to approve any child requests since they may have updated
|
|
||||||
await TvRepository.UpdateChild(results);
|
|
||||||
return results;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task RemoveTvChild(int requestId)
|
public async Task RemoveTvChild(int requestId)
|
||||||
|
|
21
src/Ombi.Core/Models/UI/MattermostNotificationsViewModel.cs
Normal file
21
src/Ombi.Core/Models/UI/MattermostNotificationsViewModel.cs
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Ombi.Settings.Settings.Models.Notifications;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Models.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The view model for the notification settings page
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="SlackNotificationSettings" />
|
||||||
|
public class MattermostNotificationsViewModel : MattermostNotificationSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the notification templates.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The notification templates.
|
||||||
|
/// </value>
|
||||||
|
public List<NotificationTemplates> NotificationTemplates { get; set; }
|
||||||
|
}
|
||||||
|
}
|
23
src/Ombi.Core/Models/UI/PushoverNotificationViewModel.cs
Normal file
23
src/Ombi.Core/Models/UI/PushoverNotificationViewModel.cs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Ombi.Settings.Settings.Models.Notifications;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
|
||||||
|
namespace Ombi.Core.Models.UI
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The view model for the notification settings page
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="DiscordNotificationSettings" />
|
||||||
|
public class PushoverNotificationViewModel : PushoverSettings
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the notification templates.
|
||||||
|
/// </summary>
|
||||||
|
/// <value>
|
||||||
|
/// The notification templates.
|
||||||
|
/// </value>
|
||||||
|
public List<NotificationTemplates> NotificationTemplates { get; set; }
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,9 @@ using Ombi.Notifications.Agents;
|
||||||
using Ombi.Schedule.Jobs.Radarr;
|
using Ombi.Schedule.Jobs.Radarr;
|
||||||
using Ombi.Api;
|
using Ombi.Api;
|
||||||
using Ombi.Api.FanartTv;
|
using Ombi.Api.FanartTv;
|
||||||
|
using Ombi.Api.Mattermost;
|
||||||
using Ombi.Api.Pushbullet;
|
using Ombi.Api.Pushbullet;
|
||||||
|
using Ombi.Api.Pushover;
|
||||||
using Ombi.Api.Service;
|
using Ombi.Api.Service;
|
||||||
using Ombi.Api.Slack;
|
using Ombi.Api.Slack;
|
||||||
using Ombi.Core.Rule.Interfaces;
|
using Ombi.Core.Rule.Interfaces;
|
||||||
|
@ -78,6 +80,8 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IPushbulletApi, PushbulletApi>();
|
services.AddTransient<IPushbulletApi, PushbulletApi>();
|
||||||
services.AddTransient<IOmbiService, OmbiService>();
|
services.AddTransient<IOmbiService, OmbiService>();
|
||||||
services.AddTransient<IFanartTvApi, FanartTvApi>();
|
services.AddTransient<IFanartTvApi, FanartTvApi>();
|
||||||
|
services.AddTransient<IPushoverApi, PushoverApi>();
|
||||||
|
services.AddTransient<IMattermostApi, MattermostApi>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterStore(this IServiceCollection services)
|
public static void RegisterStore(this IServiceCollection services)
|
||||||
|
@ -109,6 +113,9 @@ namespace Ombi.DependencyInjection
|
||||||
services.AddTransient<IEmailNotification, EmailNotification>();
|
services.AddTransient<IEmailNotification, EmailNotification>();
|
||||||
services.AddTransient<IPushbulletNotification, PushbulletNotification>();
|
services.AddTransient<IPushbulletNotification, PushbulletNotification>();
|
||||||
services.AddTransient<ISlackNotification, SlackNotification>();
|
services.AddTransient<ISlackNotification, SlackNotification>();
|
||||||
|
services.AddTransient<ISlackNotification, SlackNotification>();
|
||||||
|
services.AddTransient<IMattermostNotification, MattermostNotification>();
|
||||||
|
services.AddTransient<IPushoverNotification, PushoverNotification>();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void RegisterJobs(this IServiceCollection services)
|
public static void RegisterJobs(this IServiceCollection services)
|
||||||
|
|
|
@ -14,8 +14,10 @@
|
||||||
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Emby\Ombi.Api.Emby.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.FanartTv\Ombi.Api.FanartTv.csproj" />
|
<ProjectReference Include="..\Ombi.Api.FanartTv\Ombi.Api.FanartTv.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Plex\Ombi.Api.Plex.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Api.Pushover\Ombi.Api.Pushover.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Radarr\Ombi.Api.Radarr.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Service\Ombi.Api.Service.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Service\Ombi.Api.Service.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
||||||
|
|
|
@ -18,6 +18,8 @@ namespace Ombi.Helpers
|
||||||
public static EventId DiscordNotification => new EventId(4001);
|
public static EventId DiscordNotification => new EventId(4001);
|
||||||
public static EventId PushbulletNotification => new EventId(4002);
|
public static EventId PushbulletNotification => new EventId(4002);
|
||||||
public static EventId SlackNotification => new EventId(4003);
|
public static EventId SlackNotification => new EventId(4003);
|
||||||
|
public static EventId MattermostNotification => new EventId(4004);
|
||||||
|
public static EventId PushoverNotification => new EventId(4005);
|
||||||
|
|
||||||
public static EventId TvSender => new EventId(5000);
|
public static EventId TvSender => new EventId(5000);
|
||||||
public static EventId SonarrSender => new EventId(5001);
|
public static EventId SonarrSender => new EventId(5001);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
Pushbullet,
|
Pushbullet,
|
||||||
Pushover,
|
Pushover,
|
||||||
Telegram,
|
Telegram,
|
||||||
Slack
|
Slack,
|
||||||
|
Mattermost,
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -12,6 +12,8 @@ namespace Ombi.Mapping.Profiles
|
||||||
CreateMap<DiscordNotificationsViewModel, DiscordNotificationSettings>().ReverseMap();
|
CreateMap<DiscordNotificationsViewModel, DiscordNotificationSettings>().ReverseMap();
|
||||||
CreateMap<PushbulletNotificationViewModel, PushbulletSettings>().ReverseMap();
|
CreateMap<PushbulletNotificationViewModel, PushbulletSettings>().ReverseMap();
|
||||||
CreateMap<SlackNotificationsViewModel, SlackNotificationSettings>().ReverseMap();
|
CreateMap<SlackNotificationsViewModel, SlackNotificationSettings>().ReverseMap();
|
||||||
|
CreateMap<PushoverNotificationViewModel, PushoverSettings>().ReverseMap();
|
||||||
|
CreateMap<MattermostNotificationsViewModel, MattermostNotificationSettings>().ReverseMap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
6
src/Ombi.Notifications/Agents/IMattermostNotification.cs
Normal file
6
src/Ombi.Notifications/Agents/IMattermostNotification.cs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Ombi.Notifications.Agents
|
||||||
|
{
|
||||||
|
public interface IMattermostNotification : INotification
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
6
src/Ombi.Notifications/Agents/IPushoverNotification.cs
Normal file
6
src/Ombi.Notifications/Agents/IPushoverNotification.cs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
namespace Ombi.Notifications.Agents
|
||||||
|
{
|
||||||
|
public interface IPushoverNotification : INotification
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
164
src/Ombi.Notifications/Agents/MattermostNotification.cs
Normal file
164
src/Ombi.Notifications/Agents/MattermostNotification.cs
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.Discord;
|
||||||
|
using Ombi.Api.Discord.Models;
|
||||||
|
using Ombi.Api.Mattermost;
|
||||||
|
using Ombi.Api.Mattermost.Models;
|
||||||
|
using Ombi.Core.Settings;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Notifications.Interfaces;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
using Ombi.Settings.Settings.Models.Notifications;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
|
||||||
|
namespace Ombi.Notifications.Agents
|
||||||
|
{
|
||||||
|
public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification
|
||||||
|
{
|
||||||
|
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t) : base(sn, r, m, t)
|
||||||
|
{
|
||||||
|
Api = api;
|
||||||
|
Logger = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string NotificationName => "MattermostNotification";
|
||||||
|
|
||||||
|
private IMattermostApi Api { get; }
|
||||||
|
private ILogger<MattermostNotification> Logger { get; }
|
||||||
|
|
||||||
|
protected override bool ValidateConfiguration(MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
if (!settings.Enabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(settings.WebhookUrl))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task NewRequest(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.NewRequest, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
notification.Other.Add("image", parsed.Image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Issue(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.Issue, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
notification.Other.Add("image", parsed.Image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AddedToRequestQueue(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var user = string.Empty;
|
||||||
|
var title = string.Empty;
|
||||||
|
var image = string.Empty;
|
||||||
|
if (model.RequestType == RequestType.Movie)
|
||||||
|
{
|
||||||
|
user = MovieRequest.RequestedUser.UserAlias;
|
||||||
|
title = MovieRequest.Title;
|
||||||
|
image = MovieRequest.PosterPath;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = TvRequest.RequestedUser.UserAlias;
|
||||||
|
title = TvRequest.ParentRequest.Title;
|
||||||
|
image = TvRequest.ParentRequest.PosterPath;
|
||||||
|
}
|
||||||
|
var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying";
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
notification.Other.Add("image", image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task RequestDeclined(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestDeclined, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
notification.Other.Add("image", parsed.Image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task RequestApproved(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestApproved, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
notification.Other.Add("image", parsed.Image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AvailableRequest(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Mattermost, NotificationType.RequestAvailable, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
notification.Other.Add("image", parsed.Image);
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Send(NotificationMessage model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var body = new MattermostBody
|
||||||
|
{
|
||||||
|
username = string.IsNullOrEmpty(settings.Username) ? "Ombi" : settings.Username,
|
||||||
|
channel = settings.Channel,
|
||||||
|
text = model.Message,
|
||||||
|
icon_url = settings.IconUrl
|
||||||
|
};
|
||||||
|
await Api.PushAsync(settings.WebhookUrl, body);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError(LoggingEvents.MattermostNotification, e, "Failed to send Mattermost Notification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Test(NotificationOptions model, MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!";
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = message,
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
145
src/Ombi.Notifications/Agents/PushoverNotification.cs
Normal file
145
src/Ombi.Notifications/Agents/PushoverNotification.cs
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Ombi.Api.Pushbullet;
|
||||||
|
using Ombi.Api.Pushover;
|
||||||
|
using Ombi.Core.Settings;
|
||||||
|
using Ombi.Helpers;
|
||||||
|
using Ombi.Notifications.Interfaces;
|
||||||
|
using Ombi.Notifications.Models;
|
||||||
|
using Ombi.Settings.Settings.Models.Notifications;
|
||||||
|
using Ombi.Store.Entities;
|
||||||
|
using Ombi.Store.Repository;
|
||||||
|
using Ombi.Store.Repository.Requests;
|
||||||
|
|
||||||
|
namespace Ombi.Notifications.Agents
|
||||||
|
{
|
||||||
|
public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification
|
||||||
|
{
|
||||||
|
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t) : base(sn, r, m, t)
|
||||||
|
{
|
||||||
|
Api = api;
|
||||||
|
Logger = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string NotificationName => "PushoverNotification";
|
||||||
|
|
||||||
|
private IPushoverApi Api { get; }
|
||||||
|
private ILogger<PushbulletNotification> Logger { get; }
|
||||||
|
|
||||||
|
protected override bool ValidateConfiguration(PushoverSettings settings)
|
||||||
|
{
|
||||||
|
if (!settings.Enabled)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (string.IsNullOrEmpty(settings.AccessToken))
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task NewRequest(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.NewRequest, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Issue(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.Issue, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AddedToRequestQueue(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
string user;
|
||||||
|
string title;
|
||||||
|
if (model.RequestType == RequestType.Movie)
|
||||||
|
{
|
||||||
|
user = MovieRequest.RequestedUser.UserAlias;
|
||||||
|
title = MovieRequest.Title;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
user = TvRequest.RequestedUser.UserAlias;
|
||||||
|
title = TvRequest.ParentRequest.Title;
|
||||||
|
}
|
||||||
|
var message = $"Hello! The user '{user}' has requested {title} but it could not be added. This has been added into the requests queue and will keep retrying";
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = message
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task RequestDeclined(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestDeclined, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task RequestApproved(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestApproved, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task AvailableRequest(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var parsed = await LoadTemplate(NotificationAgent.Pushover, NotificationType.RequestAvailable, model);
|
||||||
|
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = parsed.Message,
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Send(NotificationMessage model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await Api.PushAsync(settings.AccessToken, model.Message, settings.UserToken);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Logger.LogError(LoggingEvents.PushoverNotification, e, "Failed to send Pushover Notification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override async Task Test(NotificationOptions model, PushoverSettings settings)
|
||||||
|
{
|
||||||
|
var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!";
|
||||||
|
var notification = new NotificationMessage
|
||||||
|
{
|
||||||
|
Message = message,
|
||||||
|
};
|
||||||
|
await Send(notification, settings);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,7 +10,9 @@
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Discord\Ombi.Api.Discord.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj" />
|
||||||
|
<ProjectReference Include="..\Ombi.Api.Pushover\Ombi.Api.Pushover.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
<ProjectReference Include="..\Ombi.Api.Slack\Ombi.Api.Slack.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Notifications.Templates\Ombi.Notifications.Templates.csproj" />
|
<ProjectReference Include="..\Ombi.Notifications.Templates\Ombi.Notifications.Templates.csproj" />
|
||||||
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
|
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
namespace Ombi.Settings.Settings.Models.Notifications
|
||||||
|
{
|
||||||
|
public class MattermostNotificationSettings : Settings
|
||||||
|
{
|
||||||
|
public string WebhookUrl { get; set; }
|
||||||
|
public string Channel { get; set; }
|
||||||
|
public string Username { get; set; }
|
||||||
|
public string IconUrl { get; set; }
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
|
||||||
|
namespace Ombi.Settings.Settings.Models.Notifications
|
||||||
|
{
|
||||||
|
public class PushoverSettings : Settings
|
||||||
|
{
|
||||||
|
public bool Enabled { get; set; }
|
||||||
|
public string AccessToken { get; set; }
|
||||||
|
public string UserToken { get; set; }
|
||||||
|
}
|
||||||
|
}
|
|
@ -71,18 +71,23 @@ namespace Ombi.Store.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Check if templates exist
|
//Check if templates exist
|
||||||
var templates = NotificationTemplates.ToList();
|
var templates = NotificationTemplates.ToList();
|
||||||
if (templates.Any())
|
//if (templates.Any())
|
||||||
{
|
//{
|
||||||
return;
|
// return;
|
||||||
}
|
//}
|
||||||
|
|
||||||
var allAgents = Enum.GetValues(typeof(NotificationAgent)).Cast<NotificationAgent>().ToList();
|
var allAgents = Enum.GetValues(typeof(NotificationAgent)).Cast<NotificationAgent>().ToList();
|
||||||
var allTypes = Enum.GetValues(typeof(NotificationType)).Cast<NotificationType>().ToList();
|
var allTypes = Enum.GetValues(typeof(NotificationType)).Cast<NotificationType>().ToList();
|
||||||
|
|
||||||
foreach (var agent in allAgents)
|
foreach (var agent in allAgents)
|
||||||
{
|
{
|
||||||
|
if (templates.Any(x => x.Agent == agent))
|
||||||
|
{
|
||||||
|
// We have all the templates for this notification agent
|
||||||
|
continue;
|
||||||
|
}
|
||||||
foreach (var notificationType in allTypes)
|
foreach (var notificationType in allTypes)
|
||||||
{
|
{
|
||||||
NotificationTemplates notificationToAdd;
|
NotificationTemplates notificationToAdd;
|
||||||
|
|
|
@ -74,11 +74,15 @@ namespace Ombi.Store.Repository.Requests
|
||||||
|
|
||||||
public async Task Update(TvRequests request)
|
public async Task Update(TvRequests request)
|
||||||
{
|
{
|
||||||
|
Db.Attach(request).State = EntityState.Modified;
|
||||||
|
|
||||||
await Db.SaveChangesAsync();
|
await Db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task UpdateChild(ChildRequests request)
|
public async Task UpdateChild(ChildRequests request)
|
||||||
{
|
{
|
||||||
|
Db.Attach(request).State = EntityState.Modified;
|
||||||
|
|
||||||
await Db.SaveChangesAsync();
|
await Db.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/Ombi.sln
22
src/Ombi.sln
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio 15
|
# Visual Studio 15
|
||||||
VisualStudioVersion = 15.0.26430.16
|
VisualStudioVersion = 15.0.26730.8
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi", "Ombi\Ombi.csproj", "{C987AA67-AFE1-468F-ACD3-EAD5A48E1F6A}"
|
||||||
EndProject
|
EndProject
|
||||||
|
@ -11,6 +11,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||||
..\build.cake = ..\build.cake
|
..\build.cake = ..\build.cake
|
||||||
..\BuildTask.ps1 = ..\BuildTask.ps1
|
..\BuildTask.ps1 = ..\BuildTask.ps1
|
||||||
..\CHANGELOG.md = ..\CHANGELOG.md
|
..\CHANGELOG.md = ..\CHANGELOG.md
|
||||||
|
..\global.json = ..\global.json
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Core", "Ombi.Core\Ombi.Core.csproj", "{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Core", "Ombi.Core\Ombi.Core.csproj", "{F56E79C7-791D-4668-A0EC-29E3BBC8D24B}"
|
||||||
|
@ -73,7 +74,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.FanartTv", "Ombi.A
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Pushbullet", "Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj", "{E237CDF6-D044-437D-B157-E9A3CC0BCF53}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Pushbullet", "Ombi.Api.Pushbullet\Ombi.Api.Pushbullet.csproj", "{E237CDF6-D044-437D-B157-E9A3CC0BCF53}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Slack", "Ombi.Api.Slack\Ombi.Api.Slack.csproj", "{71708256-9152-4E81-9FCA-E3181A185806}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ombi.Api.Slack", "Ombi.Api.Slack\Ombi.Api.Slack.csproj", "{71708256-9152-4E81-9FCA-E3181A185806}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Mattermost", "Ombi.Api.Mattermost\Ombi.Api.Mattermost.csproj", "{737B2620-FE5A-4135-A017-79C269A7D36C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ombi.Api.Pushover", "Ombi.Api.Pushover\Ombi.Api.Pushover.csproj", "{CA55DD4F-4EFF-4906-A848-35FCC7BD5654}"
|
||||||
EndProject
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
|
@ -185,6 +190,14 @@ Global
|
||||||
{71708256-9152-4E81-9FCA-E3181A185806}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{71708256-9152-4E81-9FCA-E3181A185806}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{71708256-9152-4E81-9FCA-E3181A185806}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{71708256-9152-4E81-9FCA-E3181A185806}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{71708256-9152-4E81-9FCA-E3181A185806}.Release|Any CPU.Build.0 = Release|Any CPU
|
{71708256-9152-4E81-9FCA-E3181A185806}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{737B2620-FE5A-4135-A017-79C269A7D36C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{737B2620-FE5A-4135-A017-79C269A7D36C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{737B2620-FE5A-4135-A017-79C269A7D36C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{737B2620-FE5A-4135-A017-79C269A7D36C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -210,5 +223,10 @@ Global
|
||||||
{FD947E63-A0D2-4878-8378-2005D5E9AB8A} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
{FD947E63-A0D2-4878-8378-2005D5E9AB8A} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
{E237CDF6-D044-437D-B157-E9A3CC0BCF53} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
{E237CDF6-D044-437D-B157-E9A3CC0BCF53} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
{71708256-9152-4E81-9FCA-E3181A185806} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
{71708256-9152-4E81-9FCA-E3181A185806} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
|
{737B2620-FE5A-4135-A017-79C269A7D36C} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
|
{CA55DD4F-4EFF-4906-A848-35FCC7BD5654} = {9293CA11-360A-4C20-A674-B9E794431BF5}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {192E9BF8-00B4-45E4-BCCC-4C215725C869}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
|
|
@ -15,30 +15,24 @@ import { ICustomizationSettings } from './interfaces/ISettings';
|
||||||
})
|
})
|
||||||
export class AppComponent implements OnInit {
|
export class AppComponent implements OnInit {
|
||||||
|
|
||||||
constructor(public notificationService: NotificationService, public authService: AuthService, private router: Router, private settingsService: SettingsService)
|
constructor(public notificationService: NotificationService, public authService: AuthService, private router: Router, private settingsService: SettingsService) { }
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
customizationSettings: ICustomizationSettings;
|
customizationSettings: ICustomizationSettings;
|
||||||
user: ILocalUser;
|
user: ILocalUser;
|
||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
this.user = this.authService.claims();
|
this.user = this.authService.claims();
|
||||||
|
|
||||||
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
this.settingsService.getCustomization().subscribe(x => this.customizationSettings = x);
|
||||||
|
|
||||||
this.router.events.subscribe(() => {
|
this.router.events.subscribe(() => {
|
||||||
|
|
||||||
this.user = this.authService.claims();
|
this.user = this.authService.claims();
|
||||||
this.showNav = this.authService.loggedIn();
|
this.showNav = this.authService.loggedIn();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
hasRole(role: string): boolean {
|
hasRole(role: string): boolean {
|
||||||
return this.user.roles.some(r => r === role)
|
return this.user.roles.some(r => r === role);
|
||||||
}
|
}
|
||||||
|
|
||||||
logOut() {
|
logOut() {
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Rx';
|
import { Observable } from 'rxjs/Rx';
|
||||||
|
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
|
||||||
|
import { Http, Headers } from '@angular/http';
|
||||||
|
|
||||||
import { ServiceHelpers } from '../services/service.helpers';
|
import { ServiceHelpers } from '../services/service.helpers';
|
||||||
|
|
||||||
import { IUserLogin, ILocalUser } from './IUserLogin';
|
import { IUserLogin, ILocalUser } from './IUserLogin';
|
||||||
|
|
||||||
import { tokenNotExpired, JwtHelper } from 'angular2-jwt';
|
|
||||||
|
|
||||||
import { Http, Headers } from '@angular/http';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AuthService extends ServiceHelpers {
|
export class AuthService extends ServiceHelpers {
|
||||||
constructor(http: Http) {
|
constructor(http: Http) {
|
||||||
|
@ -23,7 +20,6 @@ export class AuthService extends ServiceHelpers {
|
||||||
|
|
||||||
return this.http.post(`${this.url}/`, JSON.stringify(login), { headers: this.headers })
|
return this.http.post(`${this.url}/`, JSON.stringify(login), { headers: this.headers })
|
||||||
.map(this.extractData);
|
.map(this.extractData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loggedIn() {
|
loggedIn() {
|
||||||
|
@ -48,13 +44,16 @@ export class AuthService extends ServiceHelpers {
|
||||||
} else {
|
} else {
|
||||||
u.roles.push(roles);
|
u.roles.push(roles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return <ILocalUser>u;
|
return <ILocalUser>u;
|
||||||
|
|
||||||
}
|
}
|
||||||
return <ILocalUser>{};
|
return <ILocalUser>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
hasRole(role: string): boolean {
|
||||||
|
return this.claims().roles.some(r => r === role);
|
||||||
|
}
|
||||||
|
|
||||||
logout() {
|
logout() {
|
||||||
localStorage.removeItem('id_token');
|
localStorage.removeItem('id_token');
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,4 +64,18 @@ export interface IPushbulletNotificationSettings extends INotificationSettings {
|
||||||
accessToken: string,
|
accessToken: string,
|
||||||
notificationTemplates: INotificationTemplates[],
|
notificationTemplates: INotificationTemplates[],
|
||||||
channelTag: string;
|
channelTag: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IPushoverNotificationSettings extends INotificationSettings {
|
||||||
|
accessToken: string,
|
||||||
|
notificationTemplates: INotificationTemplates[],
|
||||||
|
userToken: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IMattermostNotifcationSettings extends INotificationSettings {
|
||||||
|
webhookUrl: string,
|
||||||
|
username: string,
|
||||||
|
channel: string,
|
||||||
|
iconUrl:string,
|
||||||
|
notificationTemplates: INotificationTemplates[],
|
||||||
|
}
|
||||||
|
|
|
@ -105,7 +105,8 @@ export interface IBaseRequest {
|
||||||
denied: boolean,
|
denied: boolean,
|
||||||
deniedReason: string,
|
deniedReason: string,
|
||||||
requestType: RequestType,
|
requestType: RequestType,
|
||||||
requestedUser: IUser
|
requestedUser: IUser,
|
||||||
|
canApprove:boolean,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITvRequests {
|
export interface ITvRequests {
|
||||||
|
|
|
@ -48,6 +48,7 @@ export class TvRequestManageComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public deny(request: IChildRequests) {
|
public deny(request: IChildRequests) {
|
||||||
|
debugger;
|
||||||
request.approved = false;
|
request.approved = false;
|
||||||
request.denied = true;
|
request.denied = true;
|
||||||
this.requestService.updateChild(request)
|
this.requestService.updateChild(request)
|
||||||
|
@ -55,6 +56,7 @@ export class TvRequestManageComponent {
|
||||||
}
|
}
|
||||||
|
|
||||||
public approve(request: IChildRequests) {
|
public approve(request: IChildRequests) {
|
||||||
|
debugger;
|
||||||
request.approved = true;
|
request.approved = true;
|
||||||
request.denied = false;
|
request.denied = false;
|
||||||
this.requestService.updateChild(request)
|
this.requestService.updateChild(request)
|
||||||
|
|
|
@ -54,7 +54,6 @@
|
||||||
</div>
|
</div>
|
||||||
<div>Release Date: {{node.data.releaseDate | date}}</div>
|
<div>Release Date: {{node.data.releaseDate | date}}</div>
|
||||||
<br />
|
<br />
|
||||||
<div>Requested Date: {{node.data.requestedDate | date}}</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="col-sm-3 col-sm-push-3">
|
<div class="col-sm-3 col-sm-push-3">
|
||||||
|
|
||||||
|
@ -72,19 +71,24 @@
|
||||||
|
|
||||||
<div class="col-md-2">
|
<div class="col-md-2">
|
||||||
<span>Requested By: {{child.requestedUser.userName}}</span>
|
<span>Requested By: {{child.requestedUser.userName}}</span>
|
||||||
|
<span>Requested Date: {{child.requestedDate | date}}</span>
|
||||||
|
|
||||||
|
<span *ngIf="child.available" class="label label-success">Available</span>
|
||||||
|
<span *ngIf="child.denied" class="label label-danger">Denied</span>
|
||||||
|
<span *ngIf="child.approved && !child.available && !child.denied" class="label label-info">Processing Request</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="col-md-1 col-md-push-9">
|
<div class="col-md-1 col-md-push-9" *ngIf="admin">
|
||||||
<!--// TODO ADMIN-->
|
<!--// TODO ADMIN-->
|
||||||
<form>
|
<form>
|
||||||
<button style="text-align: right" *ngIf="child.CanApprove" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> Approve</button>
|
<button style="text-align: right" *ngIf="child.canApprove" (click)="approve(child)" class="btn btn-sm btn-success-outline" type="submit"><i class="fa fa-plus"></i> Approve</button>
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form>
|
||||||
<button type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
|
<button type="button" *ngIf="!child.denied" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Deny</button>
|
||||||
</form>
|
</form>
|
||||||
<form>
|
<form>
|
||||||
<button type="button" (click)="deny(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Remove</button>
|
<button type="button" (click)="removeChildRequest(child)" class="btn btn-sm btn-danger-outline deny"><i class="fa fa-times"></i> Remove</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -100,24 +104,16 @@
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>#</a>
|
||||||
#
|
|
||||||
</a>
|
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>Title</a>
|
||||||
Title
|
|
||||||
</a>
|
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>Air Date</a>
|
||||||
Air Date
|
|
||||||
</a>
|
|
||||||
</th>
|
</th>
|
||||||
<th>
|
<th>
|
||||||
<a>
|
<a>Status</a>
|
||||||
Status
|
|
||||||
</a>
|
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
|
@ -10,6 +10,7 @@ import 'rxjs/add/operator/distinctUntilChanged';
|
||||||
import 'rxjs/add/operator/map';
|
import 'rxjs/add/operator/map';
|
||||||
|
|
||||||
import { RequestService } from '../services/request.service';
|
import { RequestService } from '../services/request.service';
|
||||||
|
import { AuthService } from '../auth/auth.service';
|
||||||
import { IdentityService } from '../services/identity.service';
|
import { IdentityService } from '../services/identity.service';
|
||||||
|
|
||||||
import { ITvRequests, IChildRequests, INewSeasonRequests, IEpisodesRequests } from '../interfaces/IRequestModel';
|
import { ITvRequests, IChildRequests, INewSeasonRequests, IEpisodesRequests } from '../interfaces/IRequestModel';
|
||||||
|
@ -25,7 +26,8 @@ import { TreeNode, } from "primeng/primeng";
|
||||||
encapsulation: ViewEncapsulation.None
|
encapsulation: ViewEncapsulation.None
|
||||||
})
|
})
|
||||||
export class TvRequestsComponent implements OnInit, OnDestroy {
|
export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
constructor(private requestService: RequestService, private identityService: IdentityService) {
|
constructor(private requestService: RequestService,
|
||||||
|
private identityService: IdentityService, private authService : AuthService) {
|
||||||
this.searchChanged
|
this.searchChanged
|
||||||
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
.debounceTime(600) // Wait Xms afterthe last event before emitting last event
|
||||||
.distinctUntilChanged() // only emit if value is different from previous value
|
.distinctUntilChanged() // only emit if value is different from previous value
|
||||||
|
@ -41,6 +43,17 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
.subscribe(m => this.tvRequests = this.transformData(m));
|
.subscribe(m => this.tvRequests = this.transformData(m));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this.amountToLoad = 5;
|
||||||
|
this.currentlyLoaded = 5;
|
||||||
|
this.tvRequests = [];
|
||||||
|
this.loadInit();
|
||||||
|
this.admin = this.authService.hasRole("admin");
|
||||||
|
}
|
||||||
|
|
||||||
|
public admin = false;
|
||||||
|
|
||||||
openClosestTab(el:any): void {
|
openClosestTab(el:any): void {
|
||||||
var rowclass = "undefined";
|
var rowclass = "undefined";
|
||||||
el = el.toElement;
|
el = el.toElement;
|
||||||
|
@ -70,17 +83,21 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
transformData(datain: ITvRequests[]): any {
|
transformData(datain: ITvRequests[]): any {
|
||||||
var temp: TreeNode[] = [];
|
var temp: TreeNode[] = [];
|
||||||
datain.forEach(function (value) {
|
datain.forEach(function(value) {
|
||||||
temp.push({
|
temp.push({
|
||||||
"data": value,
|
"data": value,
|
||||||
"children": [{
|
"children": [
|
||||||
"data": this.fixEpisodeSort(value.childRequests), leaf: true
|
{
|
||||||
}],
|
"data": this.fixEpisodeSort(value.childRequests),
|
||||||
leaf: false
|
leaf: true
|
||||||
});
|
}
|
||||||
}, this)
|
],
|
||||||
|
leaf: false
|
||||||
|
});
|
||||||
|
},
|
||||||
|
this);
|
||||||
console.log(temp);
|
console.log(temp);
|
||||||
return <TreeNode[]>temp;
|
return temp;
|
||||||
}
|
}
|
||||||
private subscriptions = new Subject<void>();
|
private subscriptions = new Subject<void>();
|
||||||
|
|
||||||
|
@ -97,22 +114,16 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
public showChildDialogue = false; // This is for the child modal popup
|
public showChildDialogue = false; // This is for the child modal popup
|
||||||
public selectedSeason: ITvRequests;
|
public selectedSeason: ITvRequests;
|
||||||
|
|
||||||
fixEpisodeSort(items: IChildRequests[]) {
|
private fixEpisodeSort(items: IChildRequests[]) : IChildRequests[] {
|
||||||
items.forEach(function (value) {
|
items.forEach(value => {
|
||||||
value.seasonRequests.forEach(function (requests: INewSeasonRequests) {
|
value.seasonRequests.forEach((requests: INewSeasonRequests) => {
|
||||||
requests.episodes.sort(function (a: IEpisodesRequests, b: IEpisodesRequests) {
|
requests.episodes.sort(
|
||||||
return a.episodeNumber - b.episodeNumber;
|
(a: IEpisodesRequests, b: IEpisodesRequests) => a.episodeNumber - b.episodeNumber)
|
||||||
})
|
});
|
||||||
})
|
});
|
||||||
})
|
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
ngOnInit() {
|
|
||||||
this.amountToLoad = 5;
|
|
||||||
this.currentlyLoaded = 5;
|
|
||||||
this.tvRequests = [];
|
|
||||||
this.loadInit();
|
|
||||||
}
|
|
||||||
|
|
||||||
public loadMore() {
|
public loadMore() {
|
||||||
this.requestService.getTvRequests(this.amountToLoad, this.currentlyLoaded + 1)
|
this.requestService.getTvRequests(this.amountToLoad, this.currentlyLoaded + 1)
|
||||||
|
@ -143,25 +154,15 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
//this.updateRequest(request);
|
//this.updateRequest(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Was already here but not sure what's using it...'
|
|
||||||
//public approve(request: IChildRequests) {
|
|
||||||
// request.approved = true;
|
|
||||||
// request.denied = false;
|
|
||||||
// //this.updateRequest(request);
|
|
||||||
//}
|
|
||||||
public approve(request: IChildRequests) {
|
public approve(request: IChildRequests) {
|
||||||
request.approved = true;
|
request.approved = true;
|
||||||
request.denied = false;
|
request.denied = false;
|
||||||
this.requestService.updateChild(request)
|
this.requestService.updateChild(request)
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
//Was already here but not sure what's using it...'
|
|
||||||
//public deny(request: IChildRequests) {
|
|
||||||
// request.approved = false;
|
|
||||||
// request.denied = true;
|
|
||||||
// //this.updateRequest(request);
|
|
||||||
//}
|
|
||||||
public deny(request: IChildRequests) {
|
public deny(request: IChildRequests) {
|
||||||
|
debugger;
|
||||||
request.approved = false;
|
request.approved = false;
|
||||||
request.denied = true;
|
request.denied = true;
|
||||||
this.requestService.updateChild(request)
|
this.requestService.updateChild(request)
|
||||||
|
@ -230,11 +231,13 @@ export class TvRequestsComponent implements OnInit, OnDestroy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private removeChildRequestFromUi(key: IChildRequests) {
|
private removeChildRequestFromUi(key: IChildRequests) {
|
||||||
//var index = this.childRequests.indexOf(key, 0);
|
this.tvRequests.forEach((val) => {
|
||||||
//if (index > -1) {
|
var data = (<any>val).data;
|
||||||
// this.childRequests.splice(index, 1);
|
var index = data.childRequests.indexOf(key, 0);
|
||||||
//}
|
if (index > -1) {
|
||||||
//TODO FIX THIS
|
data.childRequests.splice(index, 1);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,9 @@ import {
|
||||||
IDiscordNotifcationSettings,
|
IDiscordNotifcationSettings,
|
||||||
IEmailNotificationSettings,
|
IEmailNotificationSettings,
|
||||||
IPushbulletNotificationSettings,
|
IPushbulletNotificationSettings,
|
||||||
ISlackNotificationSettings
|
ISlackNotificationSettings,
|
||||||
|
IPushoverNotificationSettings,
|
||||||
|
IMattermostNotifcationSettings
|
||||||
} from '../../interfaces/INotifcationSettings'
|
} from '../../interfaces/INotifcationSettings'
|
||||||
|
|
||||||
|
|
||||||
|
@ -25,6 +27,13 @@ export class TesterService extends ServiceAuthHelpers {
|
||||||
pushbulletTest(settings: IPushbulletNotificationSettings): Observable<boolean> {
|
pushbulletTest(settings: IPushbulletNotificationSettings): Observable<boolean> {
|
||||||
return this.http.post(`${this.url}pushbullet`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
return this.http.post(`${this.url}pushbullet`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||||
}
|
}
|
||||||
|
pushoverTest(settings: IPushoverNotificationSettings): Observable<boolean> {
|
||||||
|
return this.http.post(`${this.url}pushover`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
|
mattermostTest(settings: IMattermostNotifcationSettings): Observable<boolean> {
|
||||||
|
return this.http.post(`${this.url}mattermost`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||||
|
}
|
||||||
|
|
||||||
slackTest(settings: ISlackNotificationSettings): Observable<boolean> {
|
slackTest(settings: ISlackNotificationSettings): Observable<boolean> {
|
||||||
return this.http.post(`${this.url}slack`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
return this.http.post(`${this.url}slack`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData);
|
||||||
|
|
|
@ -17,7 +17,9 @@ import {
|
||||||
IEmailNotificationSettings,
|
IEmailNotificationSettings,
|
||||||
IDiscordNotifcationSettings,
|
IDiscordNotifcationSettings,
|
||||||
IPushbulletNotificationSettings,
|
IPushbulletNotificationSettings,
|
||||||
ISlackNotificationSettings
|
ISlackNotificationSettings,
|
||||||
|
IPushoverNotificationSettings,
|
||||||
|
IMattermostNotifcationSettings
|
||||||
} from '../interfaces/INotifcationSettings';
|
} from '../interfaces/INotifcationSettings';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
|
@ -31,23 +33,31 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveOmbi(settings: IOmbiSettings): Observable<boolean> {
|
saveOmbi(settings: IOmbiSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/Ombi/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/Ombi/`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
resetOmbiApi(): Observable<string> {
|
||||||
|
return this.httpAuth.post(`${this.url}/Ombi/resetApi`, { headers: this.headers }).map(this.extractData)
|
||||||
|
.catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEmby(): Observable<IEmbySettings> {
|
getEmby(): Observable<IEmbySettings> {
|
||||||
return this.httpAuth.get(`${this.url}/Emby/`).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.get(`${this.url}/Emby/`).map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveEmby(settings: IEmbySettings): Observable<boolean> {
|
saveEmby(settings: IEmbySettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/Emby/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/Emby/`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getPlex(): Observable<IPlexSettings> {
|
getPlex(): Observable<IPlexSettings> {
|
||||||
return this.httpAuth.get(`${this.url}/Plex/`).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.get(`${this.url}/Plex/`).map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
savePlex(settings: IPlexSettings): Observable<boolean> {
|
savePlex(settings: IPlexSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/Plex/`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/Plex/`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSonarr(): Observable<ISonarrSettings> {
|
getSonarr(): Observable<ISonarrSettings> {
|
||||||
|
@ -56,7 +66,8 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSonarr(settings: ISonarrSettings): Observable<boolean> {
|
saveSonarr(settings: ISonarrSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/Sonarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/Sonarr`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getRadarr(): Observable<IRadarrSettings> {
|
getRadarr(): Observable<IRadarrSettings> {
|
||||||
|
@ -65,16 +76,18 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveRadarr(settings: IRadarrSettings): Observable<boolean> {
|
saveRadarr(settings: IRadarrSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/Radarr`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/Radarr`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using http since we need it not to be authenticated to get the landing page settings
|
// Using http since we need it not to be authenticated to get the landing page settings
|
||||||
getLandingPage(): Observable<ILandingPageSettings> {
|
getLandingPage(): Observable<ILandingPageSettings> {
|
||||||
return this.nonAuthHttp.get(`${this.url}/LandingPage`).map(this.extractData).catch(this.handleError)
|
return this.nonAuthHttp.get(`${this.url}/LandingPage`).map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
saveLandingPage(settings: ILandingPageSettings): Observable<boolean> {
|
saveLandingPage(settings: ILandingPageSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/LandingPage`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/LandingPage`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using http since we need it not to be authenticated to get the customization settings
|
// Using http since we need it not to be authenticated to get the customization settings
|
||||||
|
@ -83,7 +96,8 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveCustomization(settings: ICustomizationSettings): Observable<boolean> {
|
saveCustomization(settings: ICustomizationSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/customization`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.post(`${this.url}/customization`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getEmailNotificationSettings(): Observable<IEmailNotificationSettings> {
|
getEmailNotificationSettings(): Observable<IEmailNotificationSettings> {
|
||||||
|
@ -91,22 +105,46 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveEmailNotificationSettings(settings: IEmailNotificationSettings): Observable<boolean> {
|
saveEmailNotificationSettings(settings: IEmailNotificationSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/notifications/email`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/email`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDiscordNotificationSettings(): Observable<IDiscordNotifcationSettings> {
|
getDiscordNotificationSettings(): Observable<IDiscordNotifcationSettings> {
|
||||||
return this.httpAuth.get(`${this.url}/notifications/discord`).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.get(`${this.url}/notifications/discord`).map(this.extractData).catch(this.handleError)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMattermostNotificationSettings(): Observable<IMattermostNotifcationSettings> {
|
||||||
|
return this.httpAuth.get(`${this.url}/notifications/mattermost`).map(this.extractData).catch(this.handleError)
|
||||||
|
}
|
||||||
|
|
||||||
saveDiscordNotificationSettings(settings: IDiscordNotifcationSettings): Observable<boolean> {
|
saveDiscordNotificationSettings(settings: IDiscordNotifcationSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/notifications/discord`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/discord`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
|
}
|
||||||
|
|
||||||
|
saveMattermostNotificationSettings(settings: IMattermostNotifcationSettings): Observable<boolean> {
|
||||||
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/mattermost`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
getPushbulletNotificationSettings(): Observable<IPushbulletNotificationSettings> {
|
getPushbulletNotificationSettings(): Observable<IPushbulletNotificationSettings> {
|
||||||
return this.httpAuth.get(`${this.url}/notifications/pushbullet`).map(this.extractData).catch(this.handleError)
|
return this.httpAuth.get(`${this.url}/notifications/pushbullet`).map(this.extractData).catch(this.handleError)
|
||||||
}
|
}
|
||||||
|
getPushoverNotificationSettings(): Observable<IPushoverNotificationSettings> {
|
||||||
|
return this.httpAuth.get(`${this.url}/notifications/pushover`).map(this.extractData).catch(this.handleError)
|
||||||
|
}
|
||||||
|
|
||||||
savePushbulletNotificationSettings(settings: IPushbulletNotificationSettings): Observable<boolean> {
|
savePushbulletNotificationSettings(settings: IPushbulletNotificationSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/notifications/pushbullet`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/pushbullet`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
|
}
|
||||||
|
savePushoverNotificationSettings(settings: IPushoverNotificationSettings): Observable<boolean> {
|
||||||
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/pushover`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
|
|
||||||
getSlackNotificationSettings(): Observable<ISlackNotificationSettings> {
|
getSlackNotificationSettings(): Observable<ISlackNotificationSettings> {
|
||||||
|
@ -114,6 +152,8 @@ export class SettingsService extends ServiceAuthHelpers {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveSlackNotificationSettings(settings: ISlackNotificationSettings): Observable<boolean> {
|
saveSlackNotificationSettings(settings: ISlackNotificationSettings): Observable<boolean> {
|
||||||
return this.httpAuth.post(`${this.url}/notifications/slack`, JSON.stringify(settings), { headers: this.headers }).map(this.extractData).catch(this.handleError)
|
return this.httpAuth
|
||||||
|
.post(`${this.url}/notifications/slack`, JSON.stringify(settings), { headers: this.headers })
|
||||||
|
.map(this.extractData).catch(this.handleError);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
|
||||||
|
<settings-menu></settings-menu>
|
||||||
|
<div *ngIf="form">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Mattermost Notifications</legend>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="enable" formControlName="enabled">
|
||||||
|
<label for="enable">Enabled</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||||
|
<div *ngIf="form.get('webhookUrl').hasError('required')">The Incoming Webhook Url is required</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<small class="control-label"> Mattermost > Integrations > Incoming Webhook > Add Incoming Webhook. You will then have a Webhook</small>
|
||||||
|
<label for="webhookUrl" class="control-label">Incoming Webhook Url</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="webhookUrl" name="webhookUrl" formControlName="webhookUrl">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="channel" class="control-label">Channel Override</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="channel" name="channel" formControlName="channel" pTooltip="Optional, you can override the default channel">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="username" class="control-label">Username Override</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="username" name="username" formControlName="username" pTooltip="Optional, this will override the username you used for the Webhook">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="iconUrl" class="control-label">Icon Override</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="iconUrl" name="iconUrl" formControlName="iconUrl" pTooltip="Optional, this will override the icon you use for the Webhook">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-primary-outline">
|
||||||
|
Test
|
||||||
|
<div id="spinner"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="form.invalid" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<notification-templates [templates]="templates"></notification-templates>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
|
@ -0,0 +1,72 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
|
||||||
|
|
||||||
|
import { INotificationTemplates, IMattermostNotifcationSettings, NotificationType } from '../../interfaces/INotifcationSettings';
|
||||||
|
import { SettingsService } from '../../services/settings.service';
|
||||||
|
import { NotificationService } from "../../services/notification.service";
|
||||||
|
import { TesterService } from "../../services/applications/tester.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './mattermost.component.html'
|
||||||
|
})
|
||||||
|
export class MattermostComponent implements OnInit {
|
||||||
|
constructor(private settingsService: SettingsService,
|
||||||
|
private notificationService: NotificationService,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private testerService : TesterService) { }
|
||||||
|
|
||||||
|
NotificationType = NotificationType;
|
||||||
|
templates: INotificationTemplates[];
|
||||||
|
|
||||||
|
form: FormGroup;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.settingsService.getMattermostNotificationSettings().subscribe(x => {
|
||||||
|
this.templates = x.notificationTemplates;
|
||||||
|
|
||||||
|
this.form = this.fb.group({
|
||||||
|
enabled: [x.enabled],
|
||||||
|
username: [x.username],
|
||||||
|
webhookUrl: [x.webhookUrl, [Validators.required]],
|
||||||
|
channel: [x.channel],
|
||||||
|
iconUrl:[x.iconUrl]
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: FormGroup) {
|
||||||
|
if (form.invalid) {
|
||||||
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = <IMattermostNotifcationSettings>form.value;
|
||||||
|
settings.notificationTemplates = this.templates;
|
||||||
|
|
||||||
|
this.settingsService.saveMattermostNotificationSettings(settings).subscribe(x => {
|
||||||
|
if (x) {
|
||||||
|
this.notificationService.success("Settings Saved", "Successfully saved the Mattermost settings");
|
||||||
|
} else {
|
||||||
|
this.notificationService.success("Settings Saved", "There was an error when saving the Mattermost settings");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test(form: FormGroup) {
|
||||||
|
if (form.invalid) {
|
||||||
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.testerService.mattermostTest(form.value).subscribe(x => {
|
||||||
|
if (x) {
|
||||||
|
this.notificationService.success("Successful", "Successfully sent a Mattermost message, please check the discord channel");
|
||||||
|
} else {
|
||||||
|
this.notificationService.success("Error", "There was an error when sending the Mattermost message. Please check your settings");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,7 +2,7 @@
|
||||||
<settings-menu></settings-menu>
|
<settings-menu></settings-menu>
|
||||||
<div *ngIf="form">
|
<div *ngIf="form">
|
||||||
<fieldset>
|
<fieldset>
|
||||||
<legend>Pushbyllet Notifications</legend>
|
<legend>Pushbullet Notifications</legend>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
<settings-menu></settings-menu>
|
||||||
|
<div *ngIf="form">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Pushover Notifications</legend>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<form novalidate [formGroup]="form" (ngSubmit)="onSubmit(form)">
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="checkbox">
|
||||||
|
<input type="checkbox" id="enable" formControlName="enabled">
|
||||||
|
<label for="enable">Enabled</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||||
|
<div *ngIf="form.get('accessToken').hasError('required')">The Access Token is required</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="accessToken" class="control-label">Access Token</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="accessToken" name="accessToken" formControlName="accessToken" pTooltip="Enter your API Key from Pushover.">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="userToken" class="control-label">User Token</label>
|
||||||
|
<div>
|
||||||
|
<input type="text" class="form-control form-control-custom " id="userToken" name="userToken" formControlName="userToken" pTooltip="Your user or group key from Pushover.">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="form.invalid" type="button" (click)="test(form)" class="btn btn-primary-outline">
|
||||||
|
Test
|
||||||
|
<div id="spinner"></div>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div>
|
||||||
|
<button [disabled]="form.invalid" type="submit" id="save" class="btn btn-primary-outline">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-md-6">
|
||||||
|
<notification-templates [templates]="templates"></notification-templates>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
|
@ -0,0 +1,69 @@
|
||||||
|
import { Component, OnInit } from '@angular/core';
|
||||||
|
import { FormGroup, Validators, FormBuilder } from '@angular/forms';
|
||||||
|
|
||||||
|
import { INotificationTemplates, IPushoverNotificationSettings, NotificationType } from '../../interfaces/INotifcationSettings';
|
||||||
|
import { SettingsService } from '../../services/settings.service';
|
||||||
|
import { NotificationService } from "../../services/notification.service";
|
||||||
|
import { TesterService } from "../../services/applications/tester.service";
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
templateUrl: './pushover.component.html',
|
||||||
|
})
|
||||||
|
export class PushoverComponent implements OnInit {
|
||||||
|
constructor(private settingsService: SettingsService,
|
||||||
|
private notificationService: NotificationService,
|
||||||
|
private fb: FormBuilder,
|
||||||
|
private testerService : TesterService) { }
|
||||||
|
|
||||||
|
NotificationType = NotificationType;
|
||||||
|
templates: INotificationTemplates[];
|
||||||
|
|
||||||
|
form: FormGroup;
|
||||||
|
|
||||||
|
ngOnInit(): void {
|
||||||
|
this.settingsService.getPushoverNotificationSettings().subscribe(x => {
|
||||||
|
this.templates = x.notificationTemplates;
|
||||||
|
|
||||||
|
this.form = this.fb.group({
|
||||||
|
enabled: [x.enabled],
|
||||||
|
userToken: [x.userToken],
|
||||||
|
accessToken: [x.accessToken, [Validators.required]],
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onSubmit(form: FormGroup) {
|
||||||
|
if (form.invalid) {
|
||||||
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = <IPushoverNotificationSettings>form.value;
|
||||||
|
settings.notificationTemplates = this.templates;
|
||||||
|
|
||||||
|
this.settingsService.savePushoverNotificationSettings(settings).subscribe(x => {
|
||||||
|
if (x) {
|
||||||
|
this.notificationService.success("Settings Saved", "Successfully saved the Pushover settings");
|
||||||
|
} else {
|
||||||
|
this.notificationService.success("Settings Saved", "There was an error when saving the Pushover settings");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
test(form: FormGroup) {
|
||||||
|
if (form.invalid) {
|
||||||
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.testerService.pushoverTest(form.value).subscribe(x => {
|
||||||
|
if (x) {
|
||||||
|
this.notificationService.success("Successful", "Successfully sent a Pushbullet message, please check the discord channel");
|
||||||
|
} else {
|
||||||
|
this.notificationService.success("Error", "There was an error when sending the Pushbullet message. Please check your settings");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -11,7 +11,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
<!--<div *ngIf="form.invalid && form.dirty" class="alert alert-danger">
|
||||||
<div>The External URL is incorrect</div>
|
<div>The External URL is incorrect</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
<div>
|
<div>
|
||||||
<input type="text" class="form-control form-control-custom " id="externalUrl" name="externalUrl" placeholder="http://ombi.io/" formControlName="externalUrl" tooltipPosition="top" pTooltip="This will be the link that will be in any emails/notifications sent to the users.">
|
<input type="text" class="form-control form-control-custom " id="externalUrl" name="externalUrl" placeholder="http://ombi.io/" formControlName="externalUrl" tooltipPosition="top" pTooltip="This will be the link that will be in any emails/notifications sent to the users.">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>-->
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
|
@ -29,20 +29,20 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="ApiKey" class="control-label">Api Key</label>
|
<label for="ApiKey" class="control-label">Api Key</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey">
|
<input type="text" class="form-control form-control-custom" id="ApiKey" name="ApiKey" formControlName="apiKey">
|
||||||
|
|
||||||
<div class="input-group-addon">
|
<div class="input-group-addon">
|
||||||
<div (click)="refreshApiKey()" id="refreshKey" class="fa fa-refresh" title="Reset API Key"></div>
|
<div (click)="refreshApiKey()" id="refreshKey" class="fa fa-refresh" title="Reset API Key" pTooltip="This will invalidate the old API key"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="input-group-addon">
|
<div class="input-group-addon">
|
||||||
<div class="fa fa-clipboard"></div>
|
<div class="fa fa-clipboard"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
|
|
|
@ -29,13 +29,17 @@ export class OmbiComponent implements OnInit {
|
||||||
|
|
||||||
|
|
||||||
refreshApiKey() {
|
refreshApiKey() {
|
||||||
|
this.settingsService.resetOmbiApi().subscribe(x => {
|
||||||
|
this.form.patchValue({
|
||||||
|
apiKey: x
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
onSubmit(form: FormGroup) {
|
onSubmit(form: FormGroup) {
|
||||||
if (form.invalid) {
|
if (form.invalid) {
|
||||||
this.notificationService.error("Validation", "Please check your entered values");
|
this.notificationService.error("Validation", "Please check your entered values");
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
this.settingsService.saveOmbi(form.value).subscribe(x => {
|
this.settingsService.saveOmbi(form.value).subscribe(x => {
|
||||||
if (x) {
|
if (x) {
|
||||||
|
|
|
@ -22,6 +22,9 @@ import { CustomizationComponent } from './customization/customization.component'
|
||||||
import { EmailNotificationComponent } from './notifications/emailnotification.component';
|
import { EmailNotificationComponent } from './notifications/emailnotification.component';
|
||||||
import { DiscordComponent } from './notifications/discord.component';
|
import { DiscordComponent } from './notifications/discord.component';
|
||||||
import { SlackComponent } from './notifications/slack.component';
|
import { SlackComponent } from './notifications/slack.component';
|
||||||
|
import { PushoverComponent } from './notifications/pushover.component';
|
||||||
|
import { PushbulletComponent } from './notifications/pushbullet.component';
|
||||||
|
import { MattermostComponent } from './notifications/mattermost.component';
|
||||||
import { NotificationTemplate } from './notifications/notificationtemplate.component';
|
import { NotificationTemplate } from './notifications/notificationtemplate.component';
|
||||||
|
|
||||||
import { SettingsMenuComponent } from './settingsmenu.component';
|
import { SettingsMenuComponent } from './settingsmenu.component';
|
||||||
|
@ -40,6 +43,9 @@ const routes: Routes = [
|
||||||
{ path: 'Settings/Email', component: EmailNotificationComponent, canActivate: [AuthGuard] },
|
{ path: 'Settings/Email', component: EmailNotificationComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'Settings/Discord', component: DiscordComponent, canActivate: [AuthGuard] },
|
{ path: 'Settings/Discord', component: DiscordComponent, canActivate: [AuthGuard] },
|
||||||
{ path: 'Settings/Slack', component: SlackComponent, canActivate: [AuthGuard] },
|
{ path: 'Settings/Slack', component: SlackComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'Settings/Pushover', component: PushoverComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'Settings/Pushbullet', component: PushbulletComponent, canActivate: [AuthGuard] },
|
||||||
|
{ path: 'Settings/Mattermost', component: MattermostComponent, canActivate: [AuthGuard] },
|
||||||
];
|
];
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -72,6 +78,9 @@ const routes: Routes = [
|
||||||
EmailNotificationComponent,
|
EmailNotificationComponent,
|
||||||
HumanizePipe,
|
HumanizePipe,
|
||||||
NotificationTemplate,
|
NotificationTemplate,
|
||||||
|
PushoverComponent,
|
||||||
|
MattermostComponent,
|
||||||
|
PushbulletComponent
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
RouterModule
|
RouterModule
|
||||||
|
|
|
@ -47,7 +47,8 @@
|
||||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Discord']">Discord</a></li>
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Discord']">Discord</a></li>
|
||||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Slack']">Slack</a></li>
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Slack']">Slack</a></li>
|
||||||
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Pushbullet']">Pushbullet</a></li>
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Pushbullet']">Pushbullet</a></li>
|
||||||
<!--<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Pushover']">Pushover</a></li>-->
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Pushover']">Pushover</a></li>
|
||||||
|
<li [routerLinkActive]="['active']"><a [routerLink]="['/Settings/Mattermost']">Mattermost</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -27,13 +27,15 @@ namespace Ombi.Controllers.External
|
||||||
/// <param name="pushbullet">The pushbullet.</param>
|
/// <param name="pushbullet">The pushbullet.</param>
|
||||||
/// <param name="slack">The slack.</param>
|
/// <param name="slack">The slack.</param>
|
||||||
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
|
public TesterController(INotificationService service, IDiscordNotification notification, IEmailNotification emailN,
|
||||||
IPushbulletNotification pushbullet, ISlackNotification slack)
|
IPushbulletNotification pushbullet, ISlackNotification slack, IPushoverNotification po, IMattermostNotification mm)
|
||||||
{
|
{
|
||||||
Service = service;
|
Service = service;
|
||||||
DiscordNotification = notification;
|
DiscordNotification = notification;
|
||||||
EmailNotification = emailN;
|
EmailNotification = emailN;
|
||||||
PushbulletNotification = pushbullet;
|
PushbulletNotification = pushbullet;
|
||||||
SlackNotification = slack;
|
SlackNotification = slack;
|
||||||
|
PushoverNotification = po;
|
||||||
|
MattermostNotification = mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
private INotificationService Service { get; }
|
private INotificationService Service { get; }
|
||||||
|
@ -41,6 +43,8 @@ namespace Ombi.Controllers.External
|
||||||
private IEmailNotification EmailNotification { get; }
|
private IEmailNotification EmailNotification { get; }
|
||||||
private IPushbulletNotification PushbulletNotification { get; }
|
private IPushbulletNotification PushbulletNotification { get; }
|
||||||
private ISlackNotification SlackNotification { get; }
|
private ISlackNotification SlackNotification { get; }
|
||||||
|
private IPushoverNotification PushoverNotification { get; }
|
||||||
|
private IMattermostNotification MattermostNotification { get; }
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -73,6 +77,36 @@ namespace Ombi.Controllers.External
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a test message to Pushover using the provided settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">The settings.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("pushover")]
|
||||||
|
public bool Pushover([FromBody] PushoverSettings settings)
|
||||||
|
{
|
||||||
|
settings.Enabled = true;
|
||||||
|
PushoverNotification.NotifyAsync(
|
||||||
|
new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a test message to mattermost using the provided settings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">The settings.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("mattermost")]
|
||||||
|
public bool Mattermost([FromBody] MattermostNotificationSettings settings)
|
||||||
|
{
|
||||||
|
settings.Enabled = true;
|
||||||
|
MattermostNotification.NotifyAsync(
|
||||||
|
new NotificationOptions { NotificationType = NotificationType.Test, RequestId = -1 }, settings);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends a test message to Slack using the provided settings
|
/// Sends a test message to Slack using the provided settings
|
||||||
|
|
|
@ -65,6 +65,16 @@ namespace Ombi.Controllers
|
||||||
return await Save(ombi);
|
return await Save(ombi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpPost("ombi/resetApi")]
|
||||||
|
public async Task<string> ResetApiKey()
|
||||||
|
{
|
||||||
|
var currentSettings = await Get<OmbiSettings>();
|
||||||
|
currentSettings.ApiKey = Guid.NewGuid().ToString("N");
|
||||||
|
await Save(currentSettings);
|
||||||
|
|
||||||
|
return currentSettings.ApiKey;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the Plex Settings.
|
/// Gets the Plex Settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -295,6 +305,40 @@ namespace Ombi.Controllers
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the pushover notification settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="model">The model.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("notifications/pushover")]
|
||||||
|
public async Task<bool> PushoverNotificationSettings([FromBody] PushoverNotificationViewModel model)
|
||||||
|
{
|
||||||
|
// Save the email settings
|
||||||
|
var settings = Mapper.Map<PushoverSettings>(model);
|
||||||
|
var result = await Save(settings);
|
||||||
|
|
||||||
|
// Save the templates
|
||||||
|
await TemplateRepository.UpdateRange(model.NotificationTemplates);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the pushover Notification Settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("notifications/pushover")]
|
||||||
|
public async Task<PushoverNotificationViewModel> PushoverNotificationSettings()
|
||||||
|
{
|
||||||
|
var settings = await Get<PushoverSettings>();
|
||||||
|
var model = Mapper.Map<PushoverNotificationViewModel>(settings);
|
||||||
|
|
||||||
|
// Lookup to see if we have any templates saved
|
||||||
|
model.NotificationTemplates = await BuildTemplates(NotificationAgent.Pushover);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the slack notification settings.
|
/// Saves the slack notification settings.
|
||||||
|
@ -330,6 +374,40 @@ namespace Ombi.Controllers
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves the Mattermost notification settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="model">The model.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpPost("notifications/mattermost")]
|
||||||
|
public async Task<bool> MattermostNotificationSettings([FromBody] MattermostNotificationsViewModel model)
|
||||||
|
{
|
||||||
|
// Save the email settings
|
||||||
|
var settings = Mapper.Map<MattermostNotificationSettings>(model);
|
||||||
|
var result = await Save(settings);
|
||||||
|
|
||||||
|
// Save the templates
|
||||||
|
await TemplateRepository.UpdateRange(model.NotificationTemplates);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the Mattermost Notification Settings.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
[HttpGet("notifications/mattermost")]
|
||||||
|
public async Task<MattermostNotificationsViewModel> MattermostNotificationSettings()
|
||||||
|
{
|
||||||
|
var settings = await Get<MattermostNotificationSettings>();
|
||||||
|
var model = Mapper.Map<MattermostNotificationsViewModel>(settings);
|
||||||
|
|
||||||
|
// Lookup to see if we have any templates saved
|
||||||
|
model.NotificationTemplates = await BuildTemplates(NotificationAgent.Mattermost);
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<List<NotificationTemplates>> BuildTemplates(NotificationAgent agent)
|
private async Task<List<NotificationTemplates>> BuildTemplates(NotificationAgent agent)
|
||||||
{
|
{
|
||||||
var templates = await TemplateRepository.GetAllTemplates(agent);
|
var templates = await TemplateRepository.GetAllTemplates(agent);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||||
<RuntimeIdentifiers>win10-x64;osx.10.12-x64;ubuntu.16.04-x64;debian.8-x64;centos.7-x64;</RuntimeIdentifiers>
|
<RuntimeIdentifiers>win10-x64;osx.10.12-x64;ubuntu.16.04-x64;debian.8-x64;centos.7-x64;</RuntimeIdentifiers>
|
||||||
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
|
||||||
|
<TypeScriptToolsVersion>2.3</TypeScriptToolsVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Security.Principal;
|
using System.Security.Principal;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using AutoMapper;
|
using AutoMapper;
|
||||||
|
@ -31,8 +30,6 @@ using Ombi.Store.Context;
|
||||||
using Ombi.Store.Entities;
|
using Ombi.Store.Entities;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
using Serilog.Events;
|
using Serilog.Events;
|
||||||
using StackExchange.Profiling;
|
|
||||||
using StackExchange.Profiling.Storage;
|
|
||||||
using Swashbuckle.AspNetCore.Swagger;
|
using Swashbuckle.AspNetCore.Swagger;
|
||||||
|
|
||||||
namespace Ombi
|
namespace Ombi
|
||||||
|
@ -80,17 +77,6 @@ namespace Ombi
|
||||||
.AddEntityFrameworkStores<OmbiContext>()
|
.AddEntityFrameworkStores<OmbiContext>()
|
||||||
.AddDefaultTokenProviders();
|
.AddDefaultTokenProviders();
|
||||||
|
|
||||||
|
|
||||||
//services.AddIdentityServer()
|
|
||||||
// .AddTemporarySigningCredential()
|
|
||||||
// .AddInMemoryPersistedGrants()
|
|
||||||
// .AddInMemoryIdentityResources(IdentityConfig.GetIdentityResources())
|
|
||||||
// .AddInMemoryApiResources(IdentityConfig.GetApiResources())
|
|
||||||
// .AddInMemoryClients(IdentityConfig.GetClients())
|
|
||||||
// .AddAspNetIdentity<OmbiUser>()
|
|
||||||
// .Services.AddTransient<IResourceOwnerPasswordValidator, OmbiOwnerPasswordValidator>()
|
|
||||||
// .AddTransient<IProfileService, OmbiProfileService>();
|
|
||||||
|
|
||||||
services.Configure<IdentityOptions>(options =>
|
services.Configure<IdentityOptions>(options =>
|
||||||
{
|
{
|
||||||
options.Password.RequireDigit = false;
|
options.Password.RequireDigit = false;
|
||||||
|
@ -144,8 +130,6 @@ namespace Ombi
|
||||||
c.DescribeAllParametersInCamelCase();
|
c.DescribeAllParametersInCamelCase();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
|
||||||
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
|
services.AddScoped<IPrincipal>(sp => sp.GetService<IHttpContextAccessor>().HttpContext.User);
|
||||||
|
|
||||||
|
@ -156,21 +140,10 @@ namespace Ombi
|
||||||
|
|
||||||
services.AddHangfire(x =>
|
services.AddHangfire(x =>
|
||||||
{
|
{
|
||||||
|
|
||||||
x.UseMemoryStorage(new MemoryStorageOptions());
|
x.UseMemoryStorage(new MemoryStorageOptions());
|
||||||
|
|
||||||
//x.UseSQLiteStorage("Data Source=Ombi.db;");
|
//x.UseSQLiteStorage("Data Source=Ombi.db;");
|
||||||
|
|
||||||
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
x.UseActivator(new IoCJobActivator(services.BuildServiceProvider()));
|
||||||
});
|
});
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
// Note .AddMiniProfiler() returns a IMiniProfilerBuilder for easy intellisense
|
|
||||||
//services.AddMiniProfiler();
|
|
||||||
#endif
|
|
||||||
// Make sure you have memory cache available unless you're using another storage provider
|
|
||||||
services.AddMemoryCache();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
|
||||||
|
@ -181,20 +154,6 @@ namespace Ombi
|
||||||
|
|
||||||
var ctx = (IOmbiContext)app.ApplicationServices.GetService(typeof(IOmbiContext));
|
var ctx = (IOmbiContext)app.ApplicationServices.GetService(typeof(IOmbiContext));
|
||||||
|
|
||||||
// Get the url
|
|
||||||
var url = ctx.ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.Url);
|
|
||||||
var port = ctx.ApplicationConfigurations.FirstOrDefault(x => x.Type == ConfigurationTypes.Port);
|
|
||||||
|
|
||||||
Console.WriteLine($"Using Url {url.Value}:{port.Value} for Identity Server");
|
|
||||||
app.UseIdentity();
|
|
||||||
|
|
||||||
#if !DEBUG
|
|
||||||
var audience = $"{url.Value}:{port.Value}";
|
|
||||||
#else
|
|
||||||
|
|
||||||
var audience = $"http://localhost:52038/";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
var tokenValidationParameters = new TokenValidationParameters
|
var tokenValidationParameters = new TokenValidationParameters
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -212,28 +171,10 @@ namespace Ombi
|
||||||
{
|
{
|
||||||
Audience = "Ombi",
|
Audience = "Ombi",
|
||||||
AutomaticAuthenticate = true,
|
AutomaticAuthenticate = true,
|
||||||
TokenValidationParameters = tokenValidationParameters
|
TokenValidationParameters = tokenValidationParameters,
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// app.UseIdentityServer();
|
|
||||||
// app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
|
|
||||||
// {
|
|
||||||
//#if !DEBUG
|
|
||||||
// Authority = $"{url.Value}:{port.Value}",
|
|
||||||
//#else
|
|
||||||
// Authority = $"http://localhost:52038/",
|
|
||||||
//#endif
|
|
||||||
// ApiName = "api",
|
|
||||||
// ApiSecret = "secret",
|
|
||||||
|
|
||||||
// EnableCaching = true,
|
|
||||||
// CacheDuration = TimeSpan.FromMinutes(10), // that's the default
|
|
||||||
// RequireHttpsMetadata = options.Value.UseHttps, // FOR DEV set to false
|
|
||||||
// AutomaticAuthenticate = true,
|
|
||||||
// AutomaticChallenge = true,
|
|
||||||
|
|
||||||
|
|
||||||
// });
|
|
||||||
|
|
||||||
loggerFactory.AddSerilog();
|
loggerFactory.AddSerilog();
|
||||||
|
|
||||||
|
@ -244,20 +185,6 @@ namespace Ombi
|
||||||
{
|
{
|
||||||
HotModuleReplacement = true
|
HotModuleReplacement = true
|
||||||
});
|
});
|
||||||
|
|
||||||
//app.UseMiniProfiler(new MiniProfilerOptions
|
|
||||||
//{
|
|
||||||
// // Path to use for profiler URLs
|
|
||||||
// RouteBasePath = "~/profiler",
|
|
||||||
|
|
||||||
// // (Optional) Control which SQL formatter to use
|
|
||||||
// // (default is no formatter)
|
|
||||||
// SqlFormatter = new StackExchange.Profiling.SqlFormatters.InlineFormatter(),
|
|
||||||
|
|
||||||
// // (Optional) Control storage
|
|
||||||
// // (default is 30 minutes in MemoryCacheStorage)
|
|
||||||
// Storage = new MemoryCacheStorage(cache, TimeSpan.FromMinutes(60)),
|
|
||||||
//});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHangfireServer();
|
app.UseHangfireServer();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue