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 @@ public static string GetSeasonFolder(int seasonNumber, string seasonFolderFormat { 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 @@ public class EpisodeRenameModel 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 @@ public interface IRenameProvider 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 @@ public void ProcessEpisode(string dir, string nzbName) 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 @@ public class RenameProvider : IRenameProvider 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 @@ public class RenameProvider : IRenameProvider 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 @@ public RenameProvider(ISeriesProvider seriesProvider, ISeasonProvider seasonProv _mediaFileProvider = mediaFileProvider; _diskProvider = diskProvider; _configProvider = configProvider; + _externalNotificationProvider = extenalNotificationProvider; } #region IRenameProvider Members @@ -122,7 +126,7 @@ public void RenameEpisode(int episodeId) 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 @@ private void RenameFile(EpisodeRenameModel erm) 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 000000000..abbbe37bc Binary files /dev/null and b/NzbDrone.Web/Content/XbmcNotification.png differ diff --git a/NzbDrone.Web/Views/Settings/Index-Copy.aspx b/NzbDrone.Web/Views/Settings/Index-Copy.aspx deleted file mode 100644 index 166186ae9..000000000 --- a/NzbDrone.Web/Views/Settings/Index-Copy.aspx +++ /dev/null @@ -1,27 +0,0 @@ -<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> - -<%@ 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) %> -
-

- -

-
-
- <% } %> -