From 2af078b23dbdb5f74ae2073a8b2f9b7377aaca0b Mon Sep 17 00:00:00 2001 From: markus101 Date: Sun, 6 Mar 2011 12:45:35 -0800 Subject: [PATCH] ExternalNotifications, XBMC notification, building the framework for these, UI not implemented. --- NzbDrone.Core/Helpers/EpisodeRenameHelper.cs | 22 ++++ NzbDrone.Core/Helpers/ServerHelper.cs | 18 +++ NzbDrone.Core/Model/EpisodeRenameModel.cs | 1 + .../Providers/ExternalNotificationProvider.cs | 105 ++++++++++++++++++ .../Providers/IExtenalNotificationProvider.cs | 15 +++ NzbDrone.Core/Providers/IRenameProvider.cs | 2 +- NzbDrone.Core/Providers/IXbmcProvider.cs | 14 +++ .../Providers/PostProcessingProvider.cs | 2 +- NzbDrone.Core/Providers/RenameProvider.cs | 14 ++- NzbDrone.Core/Providers/XbmcProvider.cs | 79 +++++++++++++ NzbDrone.Web/Content/XbmcNotification.png | Bin 0 -> 6280 bytes NzbDrone.Web/Views/Settings/Index-Copy.aspx | 27 ----- 12 files changed, 268 insertions(+), 31 deletions(-) create mode 100644 NzbDrone.Core/Helpers/ServerHelper.cs create mode 100644 NzbDrone.Core/Providers/ExternalNotificationProvider.cs create mode 100644 NzbDrone.Core/Providers/IExtenalNotificationProvider.cs create mode 100644 NzbDrone.Core/Providers/IXbmcProvider.cs create mode 100644 NzbDrone.Core/Providers/XbmcProvider.cs create mode 100644 NzbDrone.Web/Content/XbmcNotification.png delete mode 100644 NzbDrone.Web/Views/Settings/Index-Copy.aspx diff --git a/NzbDrone.Core/Helpers/EpisodeRenameHelper.cs b/NzbDrone.Core/Helpers/EpisodeRenameHelper.cs index 3879893ae..f401c221a 100644 --- a/NzbDrone.Core/Helpers/EpisodeRenameHelper.cs +++ b/NzbDrone.Core/Helpers/EpisodeRenameHelper.cs @@ -33,5 +33,27 @@ namespace NzbDrone.Core.Helpers { return seasonFolderFormat.Replace("%s", seasonNumber.ToString()).Replace("%0s", seasonNumber.ToString("00")); } + + public static string GetNameForNotify(EpisodeRenameModel erm) + { + if (erm.EpisodeFile.Episodes.Count == 1) + { + return String.Format("{0} - S{1:00}E{2:00} - {3}", erm.SeriesName, + erm.EpisodeFile.Episodes[0].SeasonNumber, erm.EpisodeFile.Episodes[0].EpisodeNumber, + erm.EpisodeFile.Episodes[0].Title); + } + + var epNumberString = String.Empty; + var epNameString = String.Empty; + + foreach (var episode in erm.EpisodeFile.Episodes) + { + epNumberString = epNumberString + String.Format("E{0:00}", episode.EpisodeNumber); + epNameString = epNameString + String.Format("+ {0}", episode.Title).Trim(' ', '+'); + } + + return String.Format("{0} - S{1:00}E{2} - {3}", erm.SeriesName, erm.EpisodeFile.Episodes[0].SeasonNumber, + epNumberString, epNameString); + } } } \ No newline at end of file diff --git a/NzbDrone.Core/Helpers/ServerHelper.cs b/NzbDrone.Core/Helpers/ServerHelper.cs new file mode 100644 index 000000000..aeb91bb42 --- /dev/null +++ b/NzbDrone.Core/Helpers/ServerHelper.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; + +namespace NzbDrone.Core.Helpers +{ + public static class ServerHelper + { + public static string GetServerHostname() + { + //Both these seem to return the same result... Is on better than the other? + return Environment.MachineName; + //return Dns.GetHostName(); + } + } +} diff --git a/NzbDrone.Core/Model/EpisodeRenameModel.cs b/NzbDrone.Core/Model/EpisodeRenameModel.cs index 9583ce3e2..9a965a8e1 100644 --- a/NzbDrone.Core/Model/EpisodeRenameModel.cs +++ b/NzbDrone.Core/Model/EpisodeRenameModel.cs @@ -11,5 +11,6 @@ namespace NzbDrone.Core.Model public string SeriesName { get; set; } public string Folder { get; set; } public EpisodeFile EpisodeFile { get; set; } + public bool NewDownload { get; set; } } } diff --git a/NzbDrone.Core/Providers/ExternalNotificationProvider.cs b/NzbDrone.Core/Providers/ExternalNotificationProvider.cs new file mode 100644 index 000000000..fd6238157 --- /dev/null +++ b/NzbDrone.Core/Providers/ExternalNotificationProvider.cs @@ -0,0 +1,105 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NLog; +using NzbDrone.Core.Helpers; +using NzbDrone.Core.Model; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers +{ + public class ExternalNotificationProvider : IExtenalNotificationProvider + { + private readonly IConfigProvider _configProvider; + + + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public ExternalNotificationProvider(IConfigProvider configProvider) + { + _configProvider = configProvider; + } + + #region IExternalNotificationProvider Members + public void OnGrab(string message) + { + var header = "NzbDrone [TV] - Grabbed"; + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcEnabled", false, true))) + { + if (Convert.ToBoolean(_configProvider.GetValue("XbmcNotifyOnGrab", false, true))) + { + Logger.Trace("Sending Notifcation to XBMC"); + + return; + } + Logger.Trace("XBMC NotifyOnGrab is not enabled"); + } + + Logger.Trace("XBMC Notifier is not enabled"); + } + + public void OnDownload(EpisodeRenameModel erm) + { + var header = "NzbDrone [TV] - Downloaded"; + var message = EpisodeRenameHelper.GetNewName(erm); + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcEnabled", false, true))) + { + if (Convert.ToBoolean(_configProvider.GetValue("XbmcNotifyOnDownload", false, true))) + { + Logger.Trace("Sending Notifcation to XBMC"); + //Send to XBMC + } + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcUpdateOnDownload", false, true))) + { + Logger.Trace("Sending Update Request to XBMC"); + //Send to XBMC + //Send SeriesID + } + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcCleanOnDownload", false, true))) + { + Logger.Trace("Sending Clean DB Request to XBMC"); + //Send to XBMC + } + } + + Logger.Trace("XBMC Notifier is not enabled"); + + + throw new NotImplementedException(); + } + + public void OnRename(EpisodeRenameModel erm) + { + var header = "NzbDrone [TV] - Renamed"; + var message = EpisodeRenameHelper.GetNewName(erm); + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcNotifyOnRename", false, true))) + { + Logger.Trace("Sending Notifcation to XBMC"); + //Send to XBMC + } + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcUpdateOnRename", false, true))) + { + Logger.Trace("Sending Update Request to XBMC"); + //Send to XBMC + //Send SeriesID + } + + if (Convert.ToBoolean(_configProvider.GetValue("XbmcCleanOnRename", false, true))) + { + Logger.Trace("Sending Clean DB Request to XBMC"); + //Send to XBMC + } + + + throw new NotImplementedException(); + } + #endregion + } +} diff --git a/NzbDrone.Core/Providers/IExtenalNotificationProvider.cs b/NzbDrone.Core/Providers/IExtenalNotificationProvider.cs new file mode 100644 index 000000000..83d2752a2 --- /dev/null +++ b/NzbDrone.Core/Providers/IExtenalNotificationProvider.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using NzbDrone.Core.Repository; + +namespace NzbDrone.Core.Providers +{ + public interface IExtenalNotificationProvider + { + void OnGrab(string message); + void OnDownload(EpisodeFile episodeFile); + void OnRename(EpisodeFile episodeFile); + } +} diff --git a/NzbDrone.Core/Providers/IRenameProvider.cs b/NzbDrone.Core/Providers/IRenameProvider.cs index a3f691c7c..764608d0e 100644 --- a/NzbDrone.Core/Providers/IRenameProvider.cs +++ b/NzbDrone.Core/Providers/IRenameProvider.cs @@ -11,6 +11,6 @@ namespace NzbDrone.Core.Providers void RenameSeries(int seriesId); void RenameSeason(int seasonId); void RenameEpisode(int episodeId); - void RenameEpisodeFile(int episodeFileId); + void RenameEpisodeFile(int episodeFileId, bool newDownload); } } diff --git a/NzbDrone.Core/Providers/IXbmcProvider.cs b/NzbDrone.Core/Providers/IXbmcProvider.cs new file mode 100644 index 000000000..81c50696b --- /dev/null +++ b/NzbDrone.Core/Providers/IXbmcProvider.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace NzbDrone.Core.Providers +{ + public interface IXbmcProvider + { + void Notify(string header, string message); + void Update(int seriesId); + void Clean(); + } +} diff --git a/NzbDrone.Core/Providers/PostProcessingProvider.cs b/NzbDrone.Core/Providers/PostProcessingProvider.cs index 103303b8e..4345528a5 100644 --- a/NzbDrone.Core/Providers/PostProcessingProvider.cs +++ b/NzbDrone.Core/Providers/PostProcessingProvider.cs @@ -40,7 +40,7 @@ namespace NzbDrone.Core.Providers foreach (var file in fileList) { //Todo: Where should we handle XBMC notifying/library updating etc? RenameProvider seems like a likely place, since we want to update XBMC after renaming (might as well) - _renameProvider.RenameEpisodeFile(file.EpisodeFileId); + _renameProvider.RenameEpisodeFile(file.EpisodeFileId, true); } } diff --git a/NzbDrone.Core/Providers/RenameProvider.cs b/NzbDrone.Core/Providers/RenameProvider.cs index ec319b4ba..1329be90b 100644 --- a/NzbDrone.Core/Providers/RenameProvider.cs +++ b/NzbDrone.Core/Providers/RenameProvider.cs @@ -19,6 +19,8 @@ namespace NzbDrone.Core.Providers private readonly IMediaFileProvider _mediaFileProvider; private readonly IDiskProvider _diskProvider; private readonly IConfigProvider _configProvider; + private readonly IExtenalNotificationProvider _externalNotificationProvider; + private Thread _renameThread; private List _epsToRename = new List(); @@ -26,7 +28,8 @@ namespace NzbDrone.Core.Providers public RenameProvider(ISeriesProvider seriesProvider, ISeasonProvider seasonProvider, IEpisodeProvider episodeProvider, IMediaFileProvider mediaFileProvider, - IDiskProvider diskProvider, IConfigProvider configProvider) + IDiskProvider diskProvider, IConfigProvider configProvider, + IExtenalNotificationProvider extenalNotificationProvider) { _seriesProvider = seriesProvider; _seasonProvider = seasonProvider; @@ -34,6 +37,7 @@ namespace NzbDrone.Core.Providers _mediaFileProvider = mediaFileProvider; _diskProvider = diskProvider; _configProvider = configProvider; + _externalNotificationProvider = extenalNotificationProvider; } #region IRenameProvider Members @@ -122,7 +126,7 @@ namespace NzbDrone.Core.Providers StartRename(); } - public void RenameEpisodeFile(int episodeFileId) + public void RenameEpisodeFile(int episodeFileId, bool newDownload) { //This will properly rename multi-episode files if asked to rename either of the episode var episodeFile = _mediaFileProvider.GetEpisodeFile(episodeFileId); @@ -193,6 +197,12 @@ namespace NzbDrone.Core.Providers erm.EpisodeFile.Path = newFilename; _mediaFileProvider.Update(erm.EpisodeFile); + if (erm.NewDownload) + _externalNotificationProvider.OnDownload(); + + else + _externalNotificationProvider.OnRename(); + } catch (Exception ex) { diff --git a/NzbDrone.Core/Providers/XbmcProvider.cs b/NzbDrone.Core/Providers/XbmcProvider.cs new file mode 100644 index 000000000..d044a0ed0 --- /dev/null +++ b/NzbDrone.Core/Providers/XbmcProvider.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; +using NLog; + +namespace NzbDrone.Core.Providers +{ + public class XbmcProvider : IXbmcProvider + { + private readonly IConfigProvider _configProvider; + + private WebClient _webClient; + private static readonly Logger Logger = LogManager.GetCurrentClassLogger(); + + public XbmcProvider(IConfigProvider configProvider) + { + _webClient = new WebClient(); + _configProvider = configProvider; + } + + #region IXbmcProvider Members + + public void Notify(string header, string message) + { + //Get time in seconds and convert to ms + var time = Convert.ToInt32(_configProvider.GetValue("XbmcDisplayTime", "3", true)) * 1000; + + var command = String.Format("ExecBuiltIn(Notification({0},{1},{2}))", header, message, time); + + foreach (var host in _configProvider.GetValue("XbmcHosts", "localhost:80", true).Split(',')) + { + Logger.Trace("Sending Notifcation to XBMC Host: {0}", host); + + } + + + throw new NotImplementedException(); + } + + public void Update(int seriesId) + { + throw new NotImplementedException(); + } + + public void Clean() + { + throw new NotImplementedException(); + } + + #endregion + + private string SendCommand(string host, string command) + { + var username = _configProvider.GetValue("XbmcUsername", String.Empty, true); + var password = _configProvider.GetValue("XbmcPassword", String.Empty, true); + + if (!String.IsNullOrEmpty(username)) + { + _webClient.Credentials = new NetworkCredential(username, password); + } + + var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", host, command); + + try + { + return _webClient.DownloadString(url); + } + catch (Exception ex) + { + Logger.Warn("Unable to Connect to XBMC Host: {0}", host); + Logger.DebugException(ex.Message, ex); + } + + return string.Empty; + } + } +} diff --git a/NzbDrone.Web/Content/XbmcNotification.png b/NzbDrone.Web/Content/XbmcNotification.png new file mode 100644 index 0000000000000000000000000000000000000000..abbbe37bc0c0d5bc23c4fd396cebc84af691ec0b GIT binary patch literal 6280 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 - -<%@ Import Namespace="NzbDrone.Web.Controllers" %> - - Settings - - - <% using (Html.BeginForm()) - { %> - <%: Html.ValidationSummary(true, "Unable to save your settings. Please correct the errors and try again.") %> -
-
- General -
- <%: Html.LabelFor(m => m.TvFolder) %> -
-
- <%: Html.TextBoxFor(m => m.TvFolder) %> - <%: Html.ValidationMessageFor(m => m.TvFolder) %> -
-

- -

-
-
- <% } %> -