mirror of
https://github.com/lidarr/lidarr.git
synced 2025-08-21 14:03:29 -07:00
external notifications are now based on Events.
This commit is contained in:
parent
a866c419e1
commit
5fc25b6095
32 changed files with 542 additions and 619 deletions
149
NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs
Normal file
149
NzbDrone.Core/ExternalNotification/ExternalNotificationBase.cs
Normal file
|
@ -0,0 +1,149 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Eventing;
|
||||
using NzbDrone.Core.Download;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public abstract class ExternalNotificationBase
|
||||
: IHandle<EpisodeGrabbedEvent>,
|
||||
IHandle<EpisodeDownloadedEvent>,
|
||||
IHandle<SeriesRenamedEvent>
|
||||
{
|
||||
private readonly IExternalNotificationRepository _externalNotificationRepository;
|
||||
private readonly Logger _logger;
|
||||
|
||||
protected ExternalNotificationBase(IExternalNotificationRepository externalNotificationRepository, Logger logger)
|
||||
{
|
||||
_externalNotificationRepository = externalNotificationRepository;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public abstract string Name { get; }
|
||||
|
||||
public bool NotifyOnGrab
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetEnableStatus(c => c.OnGrab);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetEnableStatus(c => c.OnGrab = value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool NotifyOnDownload
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetEnableStatus(c => c.OnDownload);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetEnableStatus(c => c.OnDownload = value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool NotifyOnRename
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetEnableStatus(c => c.OnRename);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetEnableStatus(c => c.OnRename = value);
|
||||
}
|
||||
}
|
||||
|
||||
private void SetEnableStatus(Action<ExternalNotificationDefinition> updateAction)
|
||||
{
|
||||
var def = _externalNotificationRepository.Get(Name) ??
|
||||
new ExternalNotificationDefinition { Name = Name };
|
||||
|
||||
updateAction(def);
|
||||
_externalNotificationRepository.Upsert(def);
|
||||
}
|
||||
|
||||
private bool GetEnableStatus(Func<ExternalNotificationDefinition, bool> readFunction)
|
||||
{
|
||||
var def = _externalNotificationRepository.Get(Name) ??
|
||||
new ExternalNotificationDefinition { Name = Name };
|
||||
|
||||
return readFunction(def);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void Handle(EpisodeGrabbedEvent message)
|
||||
{
|
||||
if (NotifyOnGrab)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Trace("Sending grab notification to {0}", Name);
|
||||
OnGrab(message.ParseResult.GetDownloadTitle());
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.WarnException("Couldn't send grab notification to " + Name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(EpisodeDownloadedEvent message)
|
||||
{
|
||||
if (NotifyOnDownload)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Trace("Sending download notification to {0}", Name);
|
||||
OnDownload(message.ParseResult.GetDownloadTitle(), message.ParseResult.Series);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.WarnException("Couldn't send download notification to " + Name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Handle(SeriesRenamedEvent message)
|
||||
{
|
||||
if (NotifyOnRename)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.Trace("Sending rename notification to {0}", Name);
|
||||
AfterRename(message.Series);
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.WarnException("Couldn't send rename notification to " + Name, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual void OnGrab(string message)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void OnDownload(string message, Series series)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected virtual void AfterRename(Series series)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using PetaPoco;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class ExternalNotificationDefinition : ModelBase
|
||||
{
|
||||
public string Name { get; set; }
|
||||
public bool OnGrab { get; set; }
|
||||
public bool OnDownload { get; set; }
|
||||
public bool OnRename { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
using System.Linq;
|
||||
using NzbDrone.Core.Datastore;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public interface IExternalNotificationRepository : IBasicRepository<ExternalNotificationDefinition>
|
||||
{
|
||||
ExternalNotificationDefinition Get(string name);
|
||||
}
|
||||
|
||||
public class ExternalNotificationRepository : BasicRepository<ExternalNotificationDefinition>, IExternalNotificationRepository
|
||||
{
|
||||
public ExternalNotificationRepository(IObjectDatabase objectDatabase)
|
||||
: base(objectDatabase)
|
||||
{
|
||||
}
|
||||
|
||||
public ExternalNotificationDefinition Get(string name)
|
||||
{
|
||||
return Queryable.SingleOrDefault(c => c.Name.ToLower() == name.ToLower());
|
||||
}
|
||||
}
|
||||
}
|
48
NzbDrone.Core/ExternalNotification/Growl.cs
Normal file
48
NzbDrone.Core/ExternalNotification/Growl.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Growl : ExternalNotificationBase
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly GrowlProvider _growlProvider;
|
||||
|
||||
public Growl(IExternalNotificationRepository repository, IConfigService configService, GrowlProvider growlProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_growlProvider = growlProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Growl"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
|
||||
var growlHost = _configService.GrowlHost.Split(':');
|
||||
var host = growlHost[0];
|
||||
var port = Convert.ToInt32(growlHost[1]);
|
||||
|
||||
_growlProvider.SendNotification(title, message, "GRAB", host, port, _configService.GrowlPassword);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
var growlHost = _configService.GrowlHost.Split(':');
|
||||
var host = growlHost[0];
|
||||
var port = Convert.ToInt32(growlHost[1]);
|
||||
|
||||
_growlProvider.SendNotification(title, message, "DOWNLOAD", host, port, _configService.GrowlPassword);
|
||||
}
|
||||
}
|
||||
}
|
60
NzbDrone.Core/ExternalNotification/GrowlProvider.cs
Normal file
60
NzbDrone.Core/ExternalNotification/GrowlProvider.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Growl.Connector;
|
||||
using NLog;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class GrowlProvider
|
||||
{
|
||||
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
private readonly Application _growlApplication = new Application("NzbDrone");
|
||||
private GrowlConnector _growlConnector;
|
||||
private List<NotificationType> _notificationTypes;
|
||||
|
||||
public GrowlProvider()
|
||||
{
|
||||
_notificationTypes = GetNotificationTypes();
|
||||
_growlApplication.Icon = "https://github.com/NzbDrone/NzbDrone/raw/master/NzbDrone.Core/NzbDrone.jpg";
|
||||
}
|
||||
|
||||
public virtual void Register(string hostname, int port, string password)
|
||||
{
|
||||
Logger.Trace("Registering NzbDrone with Growl host: {0}:{1}", hostname, port);
|
||||
_growlConnector = new GrowlConnector(password, hostname, port);
|
||||
_growlConnector.Register(_growlApplication, _notificationTypes.ToArray());
|
||||
}
|
||||
|
||||
public virtual void TestNotification(string hostname, int port, string password)
|
||||
{
|
||||
const string title = "Test Notification";
|
||||
const string message = "This is a test message from NzbDrone";
|
||||
|
||||
SendNotification(title, message, "TEST", hostname, port, password);
|
||||
}
|
||||
|
||||
public virtual void SendNotification(string title, string message, string notificationTypeName, string hostname, int port, string password)
|
||||
{
|
||||
var notificationType = _notificationTypes.Single(n => n.Name == notificationTypeName);
|
||||
|
||||
var notification = new Notification("NzbDrone", notificationType.Name, DateTime.Now.Ticks.ToString(), title, message);
|
||||
|
||||
_growlConnector = new GrowlConnector(password, hostname, port);
|
||||
|
||||
Logger.Trace("Sending Notification to: {0}:{1}", hostname, port);
|
||||
_growlConnector.Notify(notification);
|
||||
}
|
||||
|
||||
private List<NotificationType> GetNotificationTypes()
|
||||
{
|
||||
var notificationTypes = new List<NotificationType>();
|
||||
notificationTypes.Add(new NotificationType("TEST", "Test"));
|
||||
notificationTypes.Add(new NotificationType("GRAB", "Episode Grabbed"));
|
||||
notificationTypes.Add(new NotificationType("DOWNLOAD", "Episode Complete"));
|
||||
|
||||
return notificationTypes;
|
||||
}
|
||||
}
|
||||
}
|
51
NzbDrone.Core/ExternalNotification/Plex.cs
Normal file
51
NzbDrone.Core/ExternalNotification/Plex.cs
Normal file
|
@ -0,0 +1,51 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Plex : ExternalNotificationBase
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly PlexProvider _plexProvider;
|
||||
|
||||
public Plex(IConfigService configService, IExternalNotificationRepository repository, PlexProvider plexProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_plexProvider = plexProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Plex"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Grabbed";
|
||||
_plexProvider.Notify(header, message);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Downloaded";
|
||||
_plexProvider.Notify(header, message);
|
||||
UpdateIfEnabled();
|
||||
}
|
||||
|
||||
protected override void AfterRename( Series series)
|
||||
{
|
||||
UpdateIfEnabled();
|
||||
}
|
||||
|
||||
private void UpdateIfEnabled()
|
||||
{
|
||||
if (_configService.PlexUpdateLibrary)
|
||||
{
|
||||
_plexProvider.UpdateLibrary();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
104
NzbDrone.Core/ExternalNotification/PlexProvider.cs
Normal file
104
NzbDrone.Core/ExternalNotification/PlexProvider.cs
Normal file
|
@ -0,0 +1,104 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Core.Configuration;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class PlexProvider
|
||||
{
|
||||
private readonly HttpProvider _httpProvider;
|
||||
private readonly IConfigService _configService;
|
||||
private static readonly Logger logger = LogManager.GetCurrentClassLogger();
|
||||
|
||||
public PlexProvider(HttpProvider httpProvider, IConfigService configService)
|
||||
{
|
||||
_httpProvider = httpProvider;
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
public PlexProvider()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public virtual void Notify(string header, string message)
|
||||
{
|
||||
//Foreach plex client send a notification
|
||||
foreach(var host in _configService.PlexClientHosts.Split(','))
|
||||
{
|
||||
try
|
||||
{
|
||||
var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", header, message);
|
||||
SendCommand(host.Trim(), command, _configService.PlexUsername, _configService.PlexPassword);
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
logger.WarnException("Failed to send notification to Plex Client: " + host.Trim(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void UpdateLibrary()
|
||||
{
|
||||
var host = _configService.PlexServerHost;
|
||||
|
||||
try
|
||||
{
|
||||
logger.Trace("Sending Update Request to Plex Server");
|
||||
var sections = GetSectionKeys(host);
|
||||
sections.ForEach(s => UpdateSection(host, s));
|
||||
}
|
||||
|
||||
catch(Exception ex)
|
||||
{
|
||||
logger.WarnException("Failed to Update Plex host: " + host, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public List<int> GetSectionKeys(string host)
|
||||
{
|
||||
logger.Trace("Getting sections from Plex host: {0}", host);
|
||||
var url = String.Format("http://{0}/library/sections", host);
|
||||
var xmlStream = _httpProvider.DownloadStream(url, null);
|
||||
var xDoc = XDocument.Load(xmlStream);
|
||||
var mediaContainer = xDoc.Descendants("MediaContainer").FirstOrDefault();
|
||||
var directories = mediaContainer.Descendants("Directory").Where(x => x.Attribute("type").Value == "show");
|
||||
|
||||
return directories.Select(d => Int32.Parse(d.Attribute("key").Value)).ToList();
|
||||
}
|
||||
|
||||
public void UpdateSection(string host, int key)
|
||||
{
|
||||
logger.Trace("Updating Plex host: {0}, Section: {1}", host, key);
|
||||
var url = String.Format("http://{0}/library/sections/{1}/refresh", host, key);
|
||||
_httpProvider.DownloadString(url);
|
||||
}
|
||||
|
||||
public virtual string SendCommand(string host, string command, string username, string password)
|
||||
{
|
||||
var url = String.Format("http://{0}/xbmcCmds/xbmcHttp?command={1}", host, command);
|
||||
|
||||
if (!String.IsNullOrEmpty(username))
|
||||
{
|
||||
return _httpProvider.DownloadString(url, username, password);
|
||||
}
|
||||
|
||||
return _httpProvider.DownloadString(url);
|
||||
}
|
||||
|
||||
public virtual void TestNotification(string hosts, string username, string password)
|
||||
{
|
||||
foreach (var host in hosts.Split(','))
|
||||
{
|
||||
logger.Trace("Sending Test Notifcation to XBMC Host: {0}", host);
|
||||
var command = String.Format("ExecBuiltIn(Notification({0}, {1}))", "Test Notification", "Success! Notifications are setup correctly");
|
||||
SendCommand(host.Trim(), command, _configService.PlexUsername, _configService.PlexPassword);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
48
NzbDrone.Core/ExternalNotification/Prowl.cs
Normal file
48
NzbDrone.Core/ExternalNotification/Prowl.cs
Normal file
|
@ -0,0 +1,48 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Tv;
|
||||
using Prowlin;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Prowl : ExternalNotificationBase
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly ProwlProvider _prowlProvider;
|
||||
|
||||
public Prowl(IConfigService configService, IExternalNotificationRepository repository, ProwlProvider prowlProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_prowlProvider = prowlProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Prowl"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
const string title = "Episode Grabbed";
|
||||
|
||||
var apiKeys = _configService.ProwlApiKeys;
|
||||
var priority = _configService.ProwlPriority;
|
||||
|
||||
_prowlProvider.SendNotification(title, message, apiKeys, (NotificationPriority)priority);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
const string title = "Episode Downloaded";
|
||||
|
||||
var apiKeys = _configService.ProwlApiKeys;
|
||||
var priority = _configService.ProwlPriority;
|
||||
|
||||
_prowlProvider.SendNotification(title, message, apiKeys, (NotificationPriority)priority);
|
||||
}
|
||||
}
|
||||
}
|
39
NzbDrone.Core/ExternalNotification/Smtp.cs
Normal file
39
NzbDrone.Core/ExternalNotification/Smtp.cs
Normal file
|
@ -0,0 +1,39 @@
|
|||
using System.Linq;
|
||||
using System;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Smtp : ExternalNotificationBase
|
||||
{
|
||||
private readonly SmtpProvider _smtpProvider;
|
||||
|
||||
public Smtp(IExternalNotificationRepository repository, SmtpProvider smtpProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_smtpProvider = smtpProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "SMTP"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
const string subject = "NzbDrone [TV] - Grabbed";
|
||||
var body = String.Format("{0} sent to SABnzbd queue.", message);
|
||||
_smtpProvider.SendEmail(subject, body);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
const string subject = "NzbDrone [TV] - Downloaded";
|
||||
var body = String.Format("{0} Downloaded and sorted.", message);
|
||||
|
||||
_smtpProvider.SendEmail(subject, body);
|
||||
}
|
||||
}
|
||||
}
|
35
NzbDrone.Core/ExternalNotification/Twitter.cs
Normal file
35
NzbDrone.Core/ExternalNotification/Twitter.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Twitter : ExternalNotificationBase
|
||||
{
|
||||
private readonly TwitterProvider _twitterProvider;
|
||||
|
||||
public Twitter(IExternalNotificationRepository repository, TwitterProvider twitterProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_twitterProvider = twitterProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "Twitter"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
_twitterProvider.SendTweet("Download Started: " + message);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
_twitterProvider.SendTweet("Download Completed: " + message);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
59
NzbDrone.Core/ExternalNotification/Xbmc.cs
Normal file
59
NzbDrone.Core/ExternalNotification/Xbmc.cs
Normal file
|
@ -0,0 +1,59 @@
|
|||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.Configuration;
|
||||
using NzbDrone.Core.Providers;
|
||||
using NzbDrone.Core.Tv;
|
||||
|
||||
namespace NzbDrone.Core.ExternalNotification
|
||||
{
|
||||
public class Xbmc : ExternalNotificationBase
|
||||
{
|
||||
private readonly IConfigService _configService;
|
||||
private readonly XbmcProvider _xbmcProvider;
|
||||
|
||||
public Xbmc(IConfigService configService, IExternalNotificationRepository repository, XbmcProvider xbmcProvider, Logger logger)
|
||||
: base(repository, logger)
|
||||
{
|
||||
_configService = configService;
|
||||
_xbmcProvider = xbmcProvider;
|
||||
}
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get { return "XBMC"; }
|
||||
}
|
||||
|
||||
protected override void OnGrab(string message)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Grabbed";
|
||||
|
||||
_xbmcProvider.Notify(header, message);
|
||||
}
|
||||
|
||||
protected override void OnDownload(string message, Series series)
|
||||
{
|
||||
const string header = "NzbDrone [TV] - Downloaded";
|
||||
|
||||
_xbmcProvider.Notify(header, message);
|
||||
UpdateAndClean(series);
|
||||
}
|
||||
|
||||
protected override void AfterRename(Series series)
|
||||
{
|
||||
UpdateAndClean(series);
|
||||
}
|
||||
|
||||
private void UpdateAndClean(Series series)
|
||||
{
|
||||
if (_configService.XbmcUpdateLibrary)
|
||||
{
|
||||
_xbmcProvider.Update(series);
|
||||
}
|
||||
|
||||
if (_configService.XbmcCleanLibrary)
|
||||
{
|
||||
_xbmcProvider.Clean();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue