mirror of
https://github.com/Ombi-app/Ombi.git
synced 2025-07-16 02:02:55 -07:00
Initial impliementation of #739
This commit is contained in:
parent
88c0651b1e
commit
973688393f
18 changed files with 624 additions and 21 deletions
38
Ombi.Api.Interfaces/IDiscordApi.cs
Normal file
38
Ombi.Api.Interfaces/IDiscordApi.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: IDiscordApi.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 System.Threading.Tasks;
|
||||
using Ombi.Api.Models.Notifications;
|
||||
|
||||
namespace Ombi.Api.Interfaces
|
||||
{
|
||||
public interface IDiscordApi
|
||||
{
|
||||
void SendMessage(string message, string webhookId, string webhookToken, string username = null);
|
||||
Task SendMessageAsync(string message, string webhookId, string webhookToken, string username = null);
|
||||
}
|
||||
}
|
|
@ -47,6 +47,7 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="IApiRequest.cs" />
|
||||
<Compile Include="ICouchPotatoApi.cs" />
|
||||
<Compile Include="IDiscordApi.cs" />
|
||||
<Compile Include="IHeadphonesApi.cs" />
|
||||
<Compile Include="IMusicBrainzApi.cs" />
|
||||
<Compile Include="INetflixApi.cs" />
|
||||
|
|
34
Ombi.Api.Models/Notifications/DiscordWebhookRequest.cs
Normal file
34
Ombi.Api.Models/Notifications/DiscordWebhookRequest.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: DiscordWebhookRequest.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
|
||||
namespace Ombi.Api.Models.Notifications
|
||||
{
|
||||
public class DiscordWebhookRequest
|
||||
{
|
||||
public string content { get; set; }
|
||||
public string username { get; set; }
|
||||
}
|
||||
}
|
47
Ombi.Api.Models/Notifications/DiscordWebhookResponse.cs
Normal file
47
Ombi.Api.Models/Notifications/DiscordWebhookResponse.cs
Normal file
|
@ -0,0 +1,47 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: DiscordWebhookResponse.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;
|
||||
using Newtonsoft.Json.Serialization;
|
||||
|
||||
namespace Ombi.Api.Models.Notifications
|
||||
{
|
||||
public class DiscordWebhookResponse
|
||||
{
|
||||
public string name { get; set; }
|
||||
[JsonProperty(PropertyName = "channel_id")]
|
||||
public string channelid { get; set; }
|
||||
|
||||
public string token { get; set; }
|
||||
public string avatar { get; set; }
|
||||
[JsonProperty(PropertyName = "guild_id")]
|
||||
public string guildid { get; set; }
|
||||
|
||||
public string id { get; set; }
|
||||
|
||||
}
|
||||
}
|
|
@ -62,6 +62,8 @@
|
|||
<Compile Include="Music\MusicBrainzReleaseInfo.cs" />
|
||||
<Compile Include="Music\MusicBrainzSearchResults.cs" />
|
||||
<Compile Include="Netflix\NetflixMovieResult.cs" />
|
||||
<Compile Include="Notifications\DiscordWebhookRequest.cs" />
|
||||
<Compile Include="Notifications\DiscordWebhookResponse.cs" />
|
||||
<Compile Include="Notifications\PushbulletPush.cs" />
|
||||
<Compile Include="Notifications\PushbulletResponse.cs" />
|
||||
<Compile Include="Notifications\PushoverResponse.cs" />
|
||||
|
|
113
Ombi.Api/DiscordApi.cs
Normal file
113
Ombi.Api/DiscordApi.cs
Normal file
|
@ -0,0 +1,113 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2017 Jamie Rees
|
||||
// File: NetflixRouletteApi.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 System;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Netflix;
|
||||
using Ombi.Api.Models.Notifications;
|
||||
using RestSharp;
|
||||
|
||||
namespace Ombi.Api
|
||||
{
|
||||
public class DiscordApi : IDiscordApi
|
||||
{
|
||||
public DiscordApi(IApiRequest req)
|
||||
{
|
||||
Api = req;
|
||||
}
|
||||
|
||||
private IApiRequest Api { get; }
|
||||
private Uri Endpoint => new Uri("https://discordapp.com/api/"); //webhooks/270828242636636161/lLysOMhJ96AFO1kvev0bSqP-WCZxKUh1UwfubhIcLkpS0DtM3cg4Pgeraw3waoTXbZii
|
||||
|
||||
|
||||
public void SendMessage(string message, string webhookId, string webhookToken, string username = null)
|
||||
{
|
||||
var request = new RestRequest
|
||||
{
|
||||
Resource = "webhooks/{webhookId}/{webhookToken}"
|
||||
};
|
||||
|
||||
request.AddUrlSegment("webhookId", webhookId);
|
||||
request.AddUrlSegment("webhookToken", webhookToken);
|
||||
|
||||
var body = new DiscordWebhookRequest
|
||||
{
|
||||
content = message,
|
||||
username = username
|
||||
};
|
||||
request.AddJsonBody(body);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
Api.Execute(request, Endpoint);
|
||||
}
|
||||
|
||||
public async Task SendMessageAsync(string message, string webhookId, string webhookToken, string username = null)
|
||||
{
|
||||
var request = new RestRequest
|
||||
{
|
||||
Resource = "webhooks/{webhookId}/{webhookToken}"
|
||||
};
|
||||
|
||||
request.AddUrlSegment("webhookId", webhookId);
|
||||
request.AddUrlSegment("webhookToken", webhookToken);
|
||||
|
||||
var body = new DiscordWebhookRequest
|
||||
{
|
||||
content = message,
|
||||
username = username
|
||||
};
|
||||
request.AddJsonBody(body);
|
||||
|
||||
request.AddHeader("Content-Type", "application/json");
|
||||
|
||||
await Task.Run(
|
||||
() =>
|
||||
{
|
||||
Api.Execute(request, Endpoint);
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
public NetflixMovieResult CheckNetflix(string title, string year = null)
|
||||
{
|
||||
var request = new RestRequest();
|
||||
request.AddQueryParameter("title", title);
|
||||
if (!string.IsNullOrEmpty(year))
|
||||
{
|
||||
request.AddQueryParameter("year", year);
|
||||
}
|
||||
var result = Api.Execute(request, Endpoint);
|
||||
|
||||
return JsonConvert.DeserializeObject<NetflixMovieResult>(result.Content);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -69,6 +69,7 @@
|
|||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="ApiRequest.cs" />
|
||||
<Compile Include="DiscordApi.cs" />
|
||||
<Compile Include="NetflixRouletteApi.cs" />
|
||||
<Compile Include="WatcherApi.cs" />
|
||||
<Compile Include="MusicBrainzApi.cs" />
|
||||
|
|
|
@ -29,7 +29,10 @@ namespace Ombi.Core
|
|||
/// Gets the username this could be the alias! We should always use this method when getting the username
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <returns><c>null</c> if we cannot find a user</returns>
|
||||
/// <param name="session">The session.</param>
|
||||
/// <returns>
|
||||
/// <c>null</c> if we cannot find a user
|
||||
/// </returns>
|
||||
string GetUsername(string username, ISession session);
|
||||
}
|
||||
}
|
|
@ -122,6 +122,7 @@
|
|||
<Compile Include="Queue\TransientFaultQueue.cs" />
|
||||
<Compile Include="SecurityExtensions.cs" />
|
||||
<Compile Include="SettingModels\AuthenticationSettings.cs" />
|
||||
<Compile Include="SettingModels\DiscordNotificationSettings.cs" />
|
||||
<Compile Include="SettingModels\WatcherSettings.cs" />
|
||||
<Compile Include="SettingModels\ExternalSettings.cs" />
|
||||
<Compile Include="SettingModels\HeadphonesSettings.cs" />
|
||||
|
|
|
@ -94,34 +94,23 @@ namespace Ombi.Core
|
|||
/// Gets the username this could be the alias! We should always use this method when getting the username
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <returns><c>null</c> if we cannot find a user</returns>
|
||||
/// <param name="session"></param>
|
||||
/// <returns>
|
||||
/// <c>null</c> if we cannot find a user
|
||||
/// </returns>
|
||||
public string GetUsername(string username, ISession session)
|
||||
{
|
||||
var plexUser = PlexUsers.GetUserByUsername(username);
|
||||
if (plexUser != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(plexUser.UserAlias))
|
||||
{
|
||||
return plexUser.UserAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
return plexUser.Username;
|
||||
}
|
||||
return !string.IsNullOrEmpty(plexUser.UserAlias) ? plexUser.UserAlias : plexUser.Username;
|
||||
}
|
||||
|
||||
var dbUser = UserRepository.GetUserByUsername(username);
|
||||
if (dbUser != null)
|
||||
{
|
||||
var userProps = ByteConverterHelper.ReturnObject<UserProperties>(dbUser.UserProperties);
|
||||
if (!string.IsNullOrEmpty(userProps.UserAlias))
|
||||
{
|
||||
return userProps.UserAlias;
|
||||
}
|
||||
else
|
||||
{
|
||||
return dbUser.UserName;
|
||||
}
|
||||
return !string.IsNullOrEmpty(userProps.UserAlias) ? userProps.UserAlias : dbUser.UserName;
|
||||
}
|
||||
|
||||
// could be a local user
|
||||
|
|
31
Ombi.Core/SettingModels/DiscordNotificationSettings.cs
Normal file
31
Ombi.Core/SettingModels/DiscordNotificationSettings.cs
Normal file
|
@ -0,0 +1,31 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Ombi.Core.SettingModels
|
||||
{
|
||||
public sealed class DiscordNotificationSettings : NotificationSettings
|
||||
{
|
||||
public string WebhookUrl { get; set; }
|
||||
public string Username { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string WebookId => SplitWebUrl(4);
|
||||
|
||||
[JsonIgnore]
|
||||
public string Token => SplitWebUrl(5);
|
||||
|
||||
private string SplitWebUrl(int index)
|
||||
{
|
||||
if (!WebhookUrl.StartsWith("http", StringComparison.InvariantCulture))
|
||||
{
|
||||
WebhookUrl = "https://" + WebhookUrl;
|
||||
}
|
||||
var split = WebhookUrl.Split(new[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
return split.Length < index
|
||||
? string.Empty
|
||||
: split[index];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
165
Ombi.Services/Notification/DiscordNotification.cs
Normal file
165
Ombi.Services/Notification/DiscordNotification.cs
Normal file
|
@ -0,0 +1,165 @@
|
|||
#region Copyright
|
||||
// /************************************************************************
|
||||
// Copyright (c) 2016 Jamie Rees
|
||||
// File: SlackNotification.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 System;
|
||||
using System.Threading.Tasks;
|
||||
using NLog;
|
||||
using Ombi.Api.Interfaces;
|
||||
using Ombi.Api.Models.Notifications;
|
||||
using Ombi.Core;
|
||||
using Ombi.Core.Models;
|
||||
using Ombi.Core.SettingModels;
|
||||
using Ombi.Services.Interfaces;
|
||||
|
||||
namespace Ombi.Services.Notification
|
||||
{
|
||||
public class DiscordNotification : INotification
|
||||
{
|
||||
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn)
|
||||
{
|
||||
Api = api;
|
||||
Settings = sn;
|
||||
}
|
||||
|
||||
public string NotificationName => "DiscordNotification";
|
||||
|
||||
private IDiscordApi Api { get; }
|
||||
private ISettingsService<DiscordNotificationSettings> Settings { get; }
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
|
||||
|
||||
public async Task NotifyAsync(NotificationModel model)
|
||||
{
|
||||
var settings = Settings.GetSettings();
|
||||
|
||||
await NotifyAsync(model, settings);
|
||||
}
|
||||
|
||||
public async Task NotifyAsync(NotificationModel model, Settings settings)
|
||||
{
|
||||
if (settings == null) await NotifyAsync(model);
|
||||
|
||||
var pushSettings = (DiscordNotificationSettings)settings;
|
||||
if (!ValidateConfiguration(pushSettings))
|
||||
{
|
||||
Log.Error("Settings for Slack was not correct, we cannot push a notification");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (model.NotificationType)
|
||||
{
|
||||
case NotificationType.NewRequest:
|
||||
await PushNewRequestAsync(model, pushSettings);
|
||||
break;
|
||||
case NotificationType.Issue:
|
||||
await PushIssueAsync(model, pushSettings);
|
||||
break;
|
||||
case NotificationType.RequestAvailable:
|
||||
break;
|
||||
case NotificationType.RequestApproved:
|
||||
break;
|
||||
case NotificationType.AdminNote:
|
||||
break;
|
||||
case NotificationType.Test:
|
||||
await PushTest(pushSettings);
|
||||
break;
|
||||
case NotificationType.RequestDeclined:
|
||||
await PushRequestDeclinedAsync(model, pushSettings);
|
||||
break;
|
||||
case NotificationType.ItemAddedToFaultQueue:
|
||||
await PushFaultQueue(model, pushSettings);
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task PushNewRequestAsync(NotificationModel model, DiscordNotificationSettings settings)
|
||||
{
|
||||
var message = $"{model.Title} has been requested by user: {model.User}";
|
||||
await Push(settings, message);
|
||||
}
|
||||
|
||||
private async Task PushRequestDeclinedAsync(NotificationModel model, DiscordNotificationSettings settings)
|
||||
{
|
||||
var message = $"Hello! Your request for {model.Title} has been declined, Sorry!";
|
||||
await Push(settings, message);
|
||||
}
|
||||
|
||||
private async Task PushIssueAsync(NotificationModel model, DiscordNotificationSettings settings)
|
||||
{
|
||||
var message = $"A new issue: {model.Body} has been reported by user: {model.User} for the title: {model.Title}";
|
||||
await Push(settings, message);
|
||||
}
|
||||
|
||||
private async Task PushTest(DiscordNotificationSettings settings)
|
||||
{
|
||||
var message = $"This is a test from Ombi, if you can see this then we have successfully pushed a notification!";
|
||||
await Push(settings, message);
|
||||
}
|
||||
|
||||
private async Task PushFaultQueue(NotificationModel model, DiscordNotificationSettings settings)
|
||||
{
|
||||
var message = $"Hello! The user '{model.User}' has requested {model.Title} but it could not be added. This has been added into the requests queue and will keep retrying";
|
||||
await Push(settings, message);
|
||||
}
|
||||
|
||||
private async Task Push(DiscordNotificationSettings config, string message)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Api.SendMessageAsync(message, config.WebookId, config.Token, config.Username);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
private bool ValidateConfiguration(DiscordNotificationSettings settings)
|
||||
{
|
||||
if (!settings.Enabled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if (string.IsNullOrEmpty(settings.WebhookUrl))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
try
|
||||
{
|
||||
var a = settings.Token;
|
||||
var b = settings.WebookId;
|
||||
}
|
||||
catch (IndexOutOfRangeException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -126,6 +126,7 @@
|
|||
<Compile Include="Notification\NotificationService.cs" />
|
||||
<Compile Include="Notification\PushoverNotification.cs" />
|
||||
<Compile Include="Notification\PushbulletNotification.cs" />
|
||||
<Compile Include="Notification\DiscordNotification.cs" />
|
||||
<Compile Include="Notification\SlackNotification.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -93,6 +93,8 @@ namespace Ombi.UI.Modules.Admin
|
|||
private IAnalytics Analytics { get; }
|
||||
private IRecentlyAdded RecentlyAdded { get; }
|
||||
private ISettingsService<NotificationSettingsV2> NotifySettings { get; }
|
||||
private ISettingsService<DiscordNotificationSettings> DiscordSettings { get; }
|
||||
private IDiscordApi DiscordApi { get; }
|
||||
|
||||
private static Logger Log = LogManager.GetCurrentClassLogger();
|
||||
public AdminModule(ISettingsService<PlexRequestSettings> prService,
|
||||
|
@ -118,7 +120,9 @@ namespace Ombi.UI.Modules.Admin
|
|||
ISlackApi slackApi, ISettingsService<LandingPageSettings> lp,
|
||||
ISettingsService<ScheduledJobsSettings> scheduler, IJobRecord rec, IAnalytics analytics,
|
||||
ISettingsService<NotificationSettingsV2> notifyService, IRecentlyAdded recentlyAdded,
|
||||
ISettingsService<WatcherSettings> watcherSettings
|
||||
ISettingsService<WatcherSettings> watcherSettings ,
|
||||
ISettingsService<DiscordNotificationSettings> discord,
|
||||
IDiscordApi discordapi
|
||||
, ISecurityExtensions security) : base("admin", prService, security)
|
||||
{
|
||||
PrService = prService;
|
||||
|
@ -150,6 +154,8 @@ namespace Ombi.UI.Modules.Admin
|
|||
NotifySettings = notifyService;
|
||||
RecentlyAdded = recentlyAdded;
|
||||
WatcherSettings = watcherSettings;
|
||||
DiscordSettings = discord;
|
||||
DiscordApi = discordapi;
|
||||
|
||||
Before += (ctx) => Security.AdminLoginRedirect(Permissions.Administrator, ctx);
|
||||
|
||||
|
@ -208,10 +214,13 @@ namespace Ombi.UI.Modules.Admin
|
|||
|
||||
|
||||
Post["/testslacknotification", true] = async (x, ct) => await TestSlackNotification();
|
||||
|
||||
Get["/slacknotification"] = _ => SlackNotifications();
|
||||
Post["/slacknotification"] = _ => SaveSlackNotifications();
|
||||
|
||||
Post["/testdiscordnotification", true] = async (x, ct) => await TestDiscordNotification();
|
||||
Get["/discordnotification", true] = async (x, ct) => await DiscordNotification();
|
||||
Post["/discordnotification", true] = async (x, ct) => await SaveDiscordNotifications();
|
||||
|
||||
Get["/landingpage", true] = async (x, ct) => await LandingPage();
|
||||
Post["/landingpage", true] = async (x, ct) => await SaveLandingPage();
|
||||
|
||||
|
@ -918,6 +927,71 @@ namespace Ombi.UI.Modules.Admin
|
|||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||
}
|
||||
|
||||
private async Task<Negotiator> DiscordNotification()
|
||||
{
|
||||
var settings = await DiscordSettings.GetSettingsAsync();
|
||||
return View["DiscordNotification", settings];
|
||||
}
|
||||
|
||||
private async Task<Response> TestDiscordNotification()
|
||||
{
|
||||
var settings = this.BindAndValidate<DiscordNotificationSettings>();
|
||||
if (!ModelValidationResult.IsValid)
|
||||
{
|
||||
return Response.AsJson(ModelValidationResult.SendJsonError());
|
||||
}
|
||||
var notificationModel = new NotificationModel
|
||||
{
|
||||
NotificationType = NotificationType.Test,
|
||||
DateTime = DateTime.Now
|
||||
};
|
||||
|
||||
var currentDicordSettings = await DiscordSettings.GetSettingsAsync();
|
||||
try
|
||||
{
|
||||
NotificationService.Subscribe(new DiscordNotification(DiscordApi, DiscordSettings));
|
||||
settings.Enabled = true;
|
||||
await NotificationService.Publish(notificationModel, settings);
|
||||
Log.Info("Sent Discord notification test");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e, "Failed to subscribe and publish test Discord Notification");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (!currentDicordSettings.Enabled)
|
||||
{
|
||||
NotificationService.UnSubscribe(new DiscordNotification(DiscordApi, DiscordSettings));
|
||||
}
|
||||
}
|
||||
return Response.AsJson(new JsonResponseModel { Result = true, Message = "Successfully sent a test Discord Notification! If you do not receive it please check the logs." });
|
||||
}
|
||||
|
||||
private async Task<Response> SaveDiscordNotifications()
|
||||
{
|
||||
var settings = this.BindAndValidate<DiscordNotificationSettings>();
|
||||
if (!ModelValidationResult.IsValid)
|
||||
{
|
||||
return Response.AsJson(ModelValidationResult.SendJsonError());
|
||||
}
|
||||
|
||||
var result = await DiscordSettings.SaveSettingsAsync(settings);
|
||||
if (settings.Enabled)
|
||||
{
|
||||
NotificationService.Subscribe(new DiscordNotification(DiscordApi, DiscordSettings));
|
||||
}
|
||||
else
|
||||
{
|
||||
NotificationService.UnSubscribe(new DiscordNotification(DiscordApi, DiscordSettings));
|
||||
}
|
||||
|
||||
Log.Info("Saved discord settings, result: {0}", result);
|
||||
return Response.AsJson(result
|
||||
? new JsonResponseModel { Result = true, Message = "Successfully Updated the Settings for Discord Notifications!" }
|
||||
: new JsonResponseModel { Result = false, Message = "Could not update the settings, take a look at the logs." });
|
||||
}
|
||||
|
||||
private async Task<Negotiator> LandingPage()
|
||||
{
|
||||
var settings = await LandingSettings.GetSettingsAsync();
|
||||
|
|
|
@ -115,7 +115,7 @@ namespace Ombi.UI.Modules
|
|||
var username = Security.GetUsername(User.UserName, Session);
|
||||
if (string.IsNullOrEmpty(username))
|
||||
{
|
||||
return Session[SessionKeys.UsernameKey].ToString();
|
||||
return "Unknown User";
|
||||
}
|
||||
_username = username;
|
||||
}
|
||||
|
|
|
@ -789,6 +789,9 @@
|
|||
<Content Include="Views\UserLogin\Password.cshtml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<Content Include="Views\Admin\DiscordNotification.cshtml">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</Content>
|
||||
<None Include="Web.Debug.config">
|
||||
<DependentUpon>web.config</DependentUpon>
|
||||
</None>
|
||||
|
|
99
Ombi.UI/Views/Admin/DiscordNotification.cshtml
Normal file
99
Ombi.UI/Views/Admin/DiscordNotification.cshtml
Normal file
|
@ -0,0 +1,99 @@
|
|||
@using Ombi.UI.Helpers
|
||||
@inherits Nancy.ViewEngines.Razor.NancyRazorViewBase<Ombi.Core.SettingModels.DiscordNotificationSettings>
|
||||
@Html.Partial("Shared/Partial/_Sidebar")
|
||||
|
||||
<div class="col-sm-8 col-sm-push-1">
|
||||
<form class="form-horizontal" method="POST" id="mainForm">
|
||||
<fieldset>
|
||||
<legend>Discord Notifications</legend>
|
||||
|
||||
@Html.Checkbox(Model.Enabled, "Enabled", "Enabled")
|
||||
|
||||
<div class="form-group">
|
||||
<label for="WebhookUrl" class="control-label">Webhook Url</label>
|
||||
<small class="control-label">This is the full webhook url.</small>
|
||||
<small class="control-label"> Discord > Edit Channel > Webhooks > Create Webook > Copy the Webhook Url > Press Save</small>
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " id="WebhookUrl" name="WebhookUrl" value="@Model.WebhookUrl">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="Username" class="control-label">Username Override</label>
|
||||
<small class="control-label">You can override the default username</small>
|
||||
<div class="">
|
||||
<input type="text" class="form-control form-control-custom " id="Username" name="Username" value="@Model.Username">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button id="testDiscord" type="submit" class="btn btn-primary-outline">Test <div id="spinner"></div></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div>
|
||||
<button id="save" type="submit" class="btn btn-primary-outline">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(function () {
|
||||
|
||||
var base = '@Html.GetBaseUrl()';
|
||||
$('#save').click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
$('#spinner').attr("class", "fa fa-spinner fa-spin");
|
||||
var $form = $("#mainForm");
|
||||
$.ajax({
|
||||
type: $form.prop("method"),
|
||||
data: $form.serialize(),
|
||||
url: $form.prop("action"),
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (response.result === true) {
|
||||
generateNotify(response.message, "success");
|
||||
$('#spinner').attr("class", "fa fa-check");
|
||||
} else {
|
||||
generateNotify(response.message, "warning");
|
||||
$('#spinner').attr("class", "fa fa-times");
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
console.log(e);
|
||||
generateNotify("Something went wrong!", "danger");
|
||||
$('#spinner').attr("class", "fa fa-times");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
$('#testDiscord').click(function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
var url = createBaseUrl(base, '/admin/testdiscordnotification');
|
||||
var $form = $("#mainForm");
|
||||
$.ajax({
|
||||
type: $form.prop("method"),
|
||||
data: $form.serialize(),
|
||||
url: url,
|
||||
dataType: "json",
|
||||
success: function (response) {
|
||||
if (response.result === true) {
|
||||
generateNotify(response.message, "success");
|
||||
} else {
|
||||
generateNotify(response.message, "warning");
|
||||
}
|
||||
},
|
||||
error: function (e) {
|
||||
console.log(e);
|
||||
generateNotify("Something went wrong!", "danger");
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
|
@ -19,6 +19,7 @@
|
|||
@Html.GetSidebarUrl(Context, "/admin/pushbulletnotification", "Pushbullet Notifications")
|
||||
@Html.GetSidebarUrl(Context, "/admin/pushovernotification", "Pushover Notifications")
|
||||
@Html.GetSidebarUrl(Context, "/admin/slacknotification", "Slack Notifications")
|
||||
@Html.GetSidebarUrl(Context, "/admin/discordnotification", "Discord Notifications")
|
||||
@Html.GetSidebarUrl(Context, "/admin/logs", "Logs")
|
||||
@Html.GetSidebarUrl(Context, "/admin/status", "Status")
|
||||
@Html.GetSidebarUrl(Context, "/admin/scheduledjobs", "Scheduled Jobs")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue