move classes to portable server project

This commit is contained in:
Luke Pulverenti 2016-11-03 18:06:00 -04:00
parent 13dcb5abb1
commit 1d62a88fd8
21 changed files with 382 additions and 292 deletions

View File

@ -51,6 +51,15 @@
<Compile Include="Collections\CollectionManager.cs" />
<Compile Include="Devices\DeviceManager.cs" />
<Compile Include="Dto\DtoService.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
<Compile Include="EntryPoints\LoadRegistrations.cs" />
<Compile Include="EntryPoints\RecordingNotifier.cs" />
<Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
<Compile Include="EntryPoints\ServerEventNotifier.cs" />
<Compile Include="EntryPoints\UsageEntryPoint.cs" />
<Compile Include="EntryPoints\UsageReporter.cs" />
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="FileOrganization\EpisodeFileOrganizer.cs" />
<Compile Include="FileOrganization\Extensions.cs" />
<Compile Include="FileOrganization\FileOrganizationNotifier.cs" />
@ -100,6 +109,8 @@
<Compile Include="Library\Validators\StudiosValidator.cs" />
<Compile Include="Library\Validators\YearsPostScanTask.cs" />
<Compile Include="Logging\PatternsLogger.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="News\NewsService.cs" />
<Compile Include="Notifications\CoreNotificationTypes.cs" />
<Compile Include="Notifications\IConfigurableNotificationService.cs" />

View File

@ -10,8 +10,9 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Model.LiveTv;
using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
public class AutomaticRestartEntryPoint : IServerEntryPoint
{
@ -21,10 +22,11 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly ISessionManager _sessionManager;
private readonly IServerConfigurationManager _config;
private readonly ILiveTvManager _liveTvManager;
private readonly ITimerFactory _timerFactory;
private Timer _timer;
private ITimer _timer;
public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager)
public AutomaticRestartEntryPoint(IServerApplicationHost appHost, ILogger logger, ITaskManager iTaskManager, ISessionManager sessionManager, IServerConfigurationManager config, ILiveTvManager liveTvManager, ITimerFactory timerFactory)
{
_appHost = appHost;
_logger = logger;
@ -32,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_sessionManager = sessionManager;
_config = config;
_liveTvManager = liveTvManager;
_timerFactory = timerFactory;
}
public void Run()
@ -48,7 +51,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
if (_appHost.HasPendingRestart)
{
_timer = new Timer(TimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
_timer = _timerFactory.Create(TimerCallback, null, TimeSpan.FromMinutes(10), TimeSpan.FromMinutes(10));
}
}

View File

@ -10,8 +10,9 @@ using System.Linq;
using System.Threading;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
public class LibraryChangedNotifier : IServerEntryPoint
{
@ -23,6 +24,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly ISessionManager _sessionManager;
private readonly IUserManager _userManager;
private readonly ILogger _logger;
private readonly ITimerFactory _timerFactory;
/// <summary>
/// The _library changed sync lock
@ -40,19 +42,20 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// Gets or sets the library update timer.
/// </summary>
/// <value>The library update timer.</value>
private Timer LibraryUpdateTimer { get; set; }
private ITimer LibraryUpdateTimer { get; set; }
/// <summary>
/// The library update duration
/// </summary>
private const int LibraryUpdateDuration = 5000;
public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger)
public LibraryChangedNotifier(ILibraryManager libraryManager, ISessionManager sessionManager, IUserManager userManager, ILogger logger, ITimerFactory timerFactory)
{
_libraryManager = libraryManager;
_sessionManager = sessionManager;
_userManager = userManager;
_logger = logger;
_timerFactory = timerFactory;
}
public void Run()
@ -79,7 +82,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
if (LibraryUpdateTimer == null)
{
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
Timeout.Infinite);
}
else
@ -112,7 +115,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
if (LibraryUpdateTimer == null)
{
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
Timeout.Infinite);
}
else
@ -140,7 +143,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
if (LibraryUpdateTimer == null)
{
LibraryUpdateTimer = new Timer(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
LibraryUpdateTimer = _timerFactory.Create(LibraryUpdateTimerCallback, null, LibraryUpdateDuration,
Timeout.Infinite);
}
else

View File

@ -3,9 +3,9 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using System;
using System.Threading.Tasks;
using MediaBrowser.Server.Implementations.Threading;
using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class LoadRegistrations
@ -22,16 +22,18 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
private readonly ILogger _logger;
private PeriodicTimer _timer;
private ITimer _timer;
private readonly ITimerFactory _timerFactory;
/// <summary>
/// Initializes a new instance of the <see cref="LoadRegistrations" /> class.
/// </summary>
/// <param name="securityManager">The security manager.</param>
/// <param name="logManager">The log manager.</param>
public LoadRegistrations(ISecurityManager securityManager, ILogManager logManager)
public LoadRegistrations(ISecurityManager securityManager, ILogManager logManager, ITimerFactory timerFactory)
{
_securityManager = securityManager;
_timerFactory = timerFactory;
_logger = logManager.GetLogger("Registration Loader");
}
@ -41,7 +43,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
/// </summary>
public void Run()
{
_timer = new PeriodicTimer(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12));
_timer = _timerFactory.Create(s => LoadAllRegistrations(), null, TimeSpan.FromMilliseconds(100), TimeSpan.FromHours(12));
}
private async Task LoadAllRegistrations()

View File

@ -7,7 +7,7 @@ using MediaBrowser.Controller.Plugins;
using MediaBrowser.Controller.Session;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
public class RecordingNotifier : IServerEntryPoint
{
@ -32,22 +32,22 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
_liveTvManager.SeriesTimerCreated += _liveTvManager_SeriesTimerCreated;
}
private void _liveTvManager_SeriesTimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
private void _liveTvManager_SeriesTimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCreated", e.Argument);
}
private void _liveTvManager_TimerCreated(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
private void _liveTvManager_TimerCreated(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCreated", e.Argument);
}
private void _liveTvManager_SeriesTimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
private void _liveTvManager_SeriesTimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("SeriesTimerCancelled", e.Argument);
}
private void _liveTvManager_TimerCancelled(object sender, Model.Events.GenericEventArgs<TimerEventInfo> e)
private void _liveTvManager_TimerCancelled(object sender, MediaBrowser.Model.Events.GenericEventArgs<TimerEventInfo> e)
{
SendMessage("TimerCancelled", e.Argument);
}

View File

@ -2,7 +2,7 @@
using MediaBrowser.Controller.Plugins;
using System.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class RefreshUsersMetadata

View File

@ -14,7 +14,7 @@ using System.Collections.Generic;
using System.Threading;
using MediaBrowser.Model.Tasks;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class WebSocketEvents

View File

@ -12,7 +12,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Controller.Configuration;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
/// <summary>
/// Class UsageEntryPoint

View File

@ -10,7 +10,7 @@ using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Logging;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
public class UsageReporter
{

View File

@ -11,8 +11,9 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.Extensions;
using MediaBrowser.Model.Threading;
namespace MediaBrowser.Server.Implementations.EntryPoints
namespace Emby.Server.Implementations.EntryPoints
{
class UserDataChangeNotifier : IServerEntryPoint
{
@ -22,17 +23,19 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
private readonly IUserManager _userManager;
private readonly object _syncLock = new object();
private Timer UpdateTimer { get; set; }
private ITimer UpdateTimer { get; set; }
private readonly ITimerFactory _timerFactory;
private const int UpdateDuration = 500;
private readonly Dictionary<Guid, List<IHasUserData>> _changedItems = new Dictionary<Guid, List<IHasUserData>>();
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager)
public UserDataChangeNotifier(IUserDataManager userDataManager, ISessionManager sessionManager, ILogger logger, IUserManager userManager, ITimerFactory timerFactory)
{
_userDataManager = userDataManager;
_sessionManager = sessionManager;
_logger = logger;
_userManager = userManager;
_timerFactory = timerFactory;
}
public void Run()
@ -51,7 +54,7 @@ namespace MediaBrowser.Server.Implementations.EntryPoints
{
if (UpdateTimer == null)
{
UpdateTimer = new Timer(UpdateTimerCallback, null, UpdateDuration,
UpdateTimer = _timerFactory.Create(UpdateTimerCallback, null, UpdateDuration,
Timeout.Infinite);
}
else

View File

@ -18,7 +18,7 @@ using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Controller.Library;
namespace MediaBrowser.Server.Implementations.MediaEncoder
namespace Emby.Server.Implementations.MediaEncoder
{
public class EncodingManager : IEncodingManager
{
@ -143,11 +143,11 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
var container = video.Container;
var tempFile = await _encoder.ExtractVideoImage(inputPath, container, protocol, video.Video3DFormat, time, cancellationToken).ConfigureAwait(false);
File.Copy(tempFile, path, true);
_fileSystem.CopyFile(tempFile, path, true);
try
{
File.Delete(tempFile);
_fileSystem.DeleteFile(tempFile);
}
catch
{
@ -205,7 +205,7 @@ namespace MediaBrowser.Server.Implementations.MediaEncoder
return _fileSystem.GetFilePaths(path)
.ToList();
}
catch (DirectoryNotFoundException)
catch (IOException)
{
return new List<string>();
}

View File

@ -0,0 +1,260 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.News;
using MediaBrowser.Model.Notifications;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Threading;
namespace Emby.Server.Implementations.News
{
public class NewsEntryPoint : IServerEntryPoint
{
private ITimer _timer;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
private readonly IJsonSerializer _json;
private readonly INotificationManager _notifications;
private readonly IUserManager _userManager;
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
private readonly ITimerFactory _timerFactory;
public NewsEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IJsonSerializer json, INotificationManager notifications, IUserManager userManager, ITimerFactory timerFactory)
{
_httpClient = httpClient;
_appPaths = appPaths;
_fileSystem = fileSystem;
_logger = logger;
_json = json;
_notifications = notifications;
_userManager = userManager;
_timerFactory = timerFactory;
}
public void Run()
{
_timer = _timerFactory.Create(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency);
}
/// <summary>
/// Called when [timer fired].
/// </summary>
/// <param name="state">The state.</param>
private async void OnTimerFired(object state)
{
var path = Path.Combine(_appPaths.CachePath, "news.json");
try
{
await DownloadNews(path).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error downloading news", ex);
}
}
private async Task DownloadNews(string path)
{
DateTime? lastUpdate = null;
if (_fileSystem.FileExists(path))
{
lastUpdate = _fileSystem.GetLastWriteTimeUtc(path);
}
var requestOptions = new HttpRequestOptions
{
Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog",
Progress = new Progress<double>(),
UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36",
BufferContent = false
};
using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false))
{
using (var reader = XmlReader.Create(stream))
{
var news = ParseRssItems(reader).ToList();
_json.SerializeToFile(news, path);
await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false);
}
}
}
private Task CreateNotifications(List<NewsItem> items, DateTime? lastUpdate, CancellationToken cancellationToken)
{
if (lastUpdate.HasValue)
{
items = items.Where(i => i.Date.ToUniversalTime() >= lastUpdate.Value)
.ToList();
}
var tasks = items.Select(i => _notifications.SendNotification(new NotificationRequest
{
Date = i.Date,
Name = i.Title,
Description = i.Description,
Url = i.Link,
UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList()
}, cancellationToken));
return Task.WhenAll(tasks);
}
private IEnumerable<NewsItem> ParseRssItems(XmlReader reader)
{
reader.MoveToContent();
reader.Read();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "channel":
{
using (var subReader = reader.ReadSubtree())
{
return ParseFromChannelNode(subReader);
}
}
default:
{
reader.Skip();
break;
}
}
}
else
{
reader.Read();
}
}
return new List<NewsItem>();
}
private IEnumerable<NewsItem> ParseFromChannelNode(XmlReader reader)
{
var list = new List<NewsItem>();
reader.MoveToContent();
reader.Read();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "item":
{
using (var subReader = reader.ReadSubtree())
{
list.Add(ParseItem(subReader));
}
break;
}
default:
{
reader.Skip();
break;
}
}
}
else
{
reader.Read();
}
}
return list;
}
private NewsItem ParseItem(XmlReader reader)
{
var item = new NewsItem();
reader.MoveToContent();
reader.Read();
while (!reader.EOF)
{
if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{
case "title":
{
item.Title = reader.ReadElementContentAsString();
break;
}
case "link":
{
item.Link = reader.ReadElementContentAsString();
break;
}
case "description":
{
item.DescriptionHtml = reader.ReadElementContentAsString();
item.Description = item.DescriptionHtml.StripHtml();
break;
}
case "pubDate":
{
var date = reader.ReadElementContentAsString();
DateTime parsedDate;
if (DateTime.TryParse(date, out parsedDate))
{
item.Date = parsedDate;
}
break;
}
default:
{
reader.Skip();
break;
}
}
}
else
{
reader.Read();
}
}
return item;
}
public void Dispose()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
}
}
}

View File

@ -1,8 +1,7 @@
{
{
"supports": {},
"dependencies": {
"MediaBrowser.Naming": "1.0.0.59",
"Patterns.Logging": "1.0.0.6"
"MediaBrowser.Naming": "1.0.0.59"
},
"frameworks": {
".NETPortable,Version=v4.5,Profile=Profile7": {}

View File

@ -46,17 +46,13 @@
<HintPath>..\ThirdParty\emby\Emby.Common.Implementations.dll</HintPath>
</Reference>
<Reference Include="Emby.XmlTv, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\Emby.XmlTv.1.0.0.62\lib\portable-net45+win8\Emby.XmlTv.dll</HintPath>
<HintPath>..\packages\Emby.XmlTv.1.0.0.63\lib\portable-net45+win8\Emby.XmlTv.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="INIFileParser, Version=2.3.0.0, Culture=neutral, PublicKeyToken=79af7b307b65cf3c, processorArchitecture=MSIL">
<HintPath>..\packages\ini-parser.2.3.0\lib\net20\INIFileParser.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.6151.30291, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.59\lib\portable-net45+win8\MediaBrowser.Naming.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Microsoft.IO.RecyclableMemoryStream, Version=1.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.IO.RecyclableMemoryStream.1.1.0.0\lib\net45\Microsoft.IO.RecyclableMemoryStream.dll</HintPath>
<Private>True</Private>
@ -120,17 +116,8 @@
<Compile Include="Connect\Validator.cs" />
<Compile Include="Devices\DeviceRepository.cs" />
<Compile Include="Devices\CameraUploadsFolder.cs" />
<Compile Include="EntryPoints\AutomaticRestartEntryPoint.cs" />
<Compile Include="EntryPoints\ExternalPortForwarding.cs" />
<Compile Include="EntryPoints\LibraryChangedNotifier.cs" />
<Compile Include="EntryPoints\LoadRegistrations.cs" />
<Compile Include="EntryPoints\RecordingNotifier.cs" />
<Compile Include="EntryPoints\RefreshUsersMetadata.cs" />
<Compile Include="EntryPoints\UsageEntryPoint.cs" />
<Compile Include="EntryPoints\UsageReporter.cs" />
<Compile Include="EntryPoints\UdpServerEntryPoint.cs" />
<Compile Include="EntryPoints\ServerEventNotifier.cs" />
<Compile Include="EntryPoints\UserDataChangeNotifier.cs" />
<Compile Include="HttpServer\IHttpListener.cs" />
<Compile Include="HttpServer\Security\AuthorizationContext.cs" />
<Compile Include="HttpServer\ContainerAdapter.cs" />
@ -211,8 +198,6 @@
<Compile Include="LiveTv\TunerHosts\SatIp\Utils.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="Logging\PatternsLogger.cs" />
<Compile Include="MediaEncoder\EncodingManager.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
<Compile Include="Persistence\BaseSqliteRepository.cs" />
<Compile Include="Persistence\DataExtensions.cs" />
<Compile Include="Persistence\IDbConnector.cs" />
@ -286,23 +271,6 @@
<Name>MediaBrowser.Providers</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\Ratings\us.txt" />
<EmbeddedResource Include="Localization\Ratings\au.txt" />
<EmbeddedResource Include="Localization\Ratings\gb.txt" />
<EmbeddedResource Include="Localization\Ratings\nl.txt" />
<EmbeddedResource Include="Localization\Ratings\br.txt" />
<EmbeddedResource Include="Localization\Ratings\dk.txt" />
<EmbeddedResource Include="Localization\Ratings\de.txt" />
<EmbeddedResource Include="Localization\Ratings\mx.txt" />
<EmbeddedResource Include="Localization\Ratings\co.txt" />
<EmbeddedResource Include="Localization\Ratings\fr.txt" />
<EmbeddedResource Include="Localization\Ratings\ie.txt" />
<EmbeddedResource Include="Localization\Ratings\jp.txt" />
<EmbeddedResource Include="Localization\Ratings\kz.txt" />
<EmbeddedResource Include="Localization\Ratings\nz.txt" />
<EmbeddedResource Include="Localization\Ratings\ru.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="..\ThirdParty\ServiceStack\swagger-ui\lib\backbone-min.js">
<Link>swagger-ui\lib\backbone-min.js</Link>
@ -368,7 +336,6 @@
<Link>swagger-ui\swagger-ui.min.js</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Localization\countries.json" />
<Content Include="..\ThirdParty\ServiceStack\swagger-ui\fonts\droid-sans-v6-latin-700.eot">
<Link>swagger-ui\fonts\droid-sans-v6-latin-700.eot</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
@ -401,46 +368,25 @@
<Link>swagger-ui\fonts\droid-sans-v6-latin-regular.woff2</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Localization\Ratings\us.txt" />
<EmbeddedResource Include="Localization\Ratings\ru.txt" />
<EmbeddedResource Include="Localization\Ratings\nz.txt" />
<EmbeddedResource Include="Localization\Ratings\nl.txt" />
<EmbeddedResource Include="Localization\Ratings\mx.txt" />
<EmbeddedResource Include="Localization\Ratings\kz.txt" />
<EmbeddedResource Include="Localization\Ratings\jp.txt" />
<EmbeddedResource Include="Localization\Ratings\ie.txt" />
<EmbeddedResource Include="Localization\Ratings\gb.txt" />
<EmbeddedResource Include="Localization\Ratings\fr.txt" />
<EmbeddedResource Include="Localization\Ratings\dk.txt" />
<EmbeddedResource Include="Localization\Ratings\de.txt" />
<EmbeddedResource Include="Localization\Ratings\co.txt" />
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
<EmbeddedResource Include="Localization\Ratings\br.txt" />
<EmbeddedResource Include="Localization\Ratings\be.txt" />
<EmbeddedResource Include="Localization\Ratings\au.txt" />
<EmbeddedResource Include="Localization\iso6392.txt" />
<None Include="app.config" />
<EmbeddedResource Include="Localization\Core\core.json" />
<EmbeddedResource Include="Localization\Core\ar.json" />
<EmbeddedResource Include="Localization\Core\bg-BG.json" />
<EmbeddedResource Include="Localization\Core\ca.json" />
<EmbeddedResource Include="Localization\Core\cs.json" />
<EmbeddedResource Include="Localization\Core\da.json" />
<EmbeddedResource Include="Localization\Core\de.json" />
<EmbeddedResource Include="Localization\Core\el.json" />
<EmbeddedResource Include="Localization\Core\en-GB.json" />
<EmbeddedResource Include="Localization\Core\en-US.json" />
<EmbeddedResource Include="Localization\Core\es-AR.json" />
<EmbeddedResource Include="Localization\Core\es-MX.json" />
<EmbeddedResource Include="Localization\Core\es.json" />
<EmbeddedResource Include="Localization\Core\fi.json" />
<EmbeddedResource Include="Localization\Core\fr.json" />
<EmbeddedResource Include="Localization\Core\gsw.json" />
<EmbeddedResource Include="Localization\Core\he.json" />
<EmbeddedResource Include="Localization\Core\hr.json" />
<EmbeddedResource Include="Localization\Core\it.json" />
<EmbeddedResource Include="Localization\Core\kk.json" />
<EmbeddedResource Include="Localization\Core\ko.json" />
<EmbeddedResource Include="Localization\Core\ms.json" />
<EmbeddedResource Include="Localization\Core\nb.json" />
<EmbeddedResource Include="Localization\Core\nl.json" />
<EmbeddedResource Include="Localization\Core\pl.json" />
<EmbeddedResource Include="Localization\Core\pt-BR.json" />
<EmbeddedResource Include="Localization\Core\pt-PT.json" />
<EmbeddedResource Include="Localization\Core\ro.json" />
<EmbeddedResource Include="Localization\Core\ru.json" />
<EmbeddedResource Include="Localization\Core\sl-SI.json" />
<EmbeddedResource Include="Localization\Core\sv.json" />
<EmbeddedResource Include="Localization\Core\tr.json" />
<EmbeddedResource Include="Localization\Core\uk.json" />
<EmbeddedResource Include="Localization\Core\vi.json" />
<EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-TW.json" />
<EmbeddedResource Include="Localization\Core\zh-HK.json" />
<EmbeddedResource Include="Localization\Core\hu.json" />
<EmbeddedResource Include="Localization\Core\id.json" />
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0030.ini" />
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0049.ini" />
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\0070.ini" />
@ -610,12 +556,49 @@
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3560.ini" />
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3592.ini" />
<EmbeddedResource Include="LiveTv\TunerHosts\SatIp\ini\satellite\3594.ini" />
<EmbeddedResource Include="Localization\Core\ar.json" />
<EmbeddedResource Include="Localization\Core\bg-BG.json" />
<EmbeddedResource Include="Localization\Core\ca.json" />
<EmbeddedResource Include="Localization\Core\core.json" />
<EmbeddedResource Include="Localization\Core\cs.json" />
<EmbeddedResource Include="Localization\Core\da.json" />
<EmbeddedResource Include="Localization\Core\de.json" />
<EmbeddedResource Include="Localization\Core\el.json" />
<EmbeddedResource Include="Localization\Core\en-GB.json" />
<EmbeddedResource Include="Localization\Core\en-US.json" />
<EmbeddedResource Include="Localization\Core\es-AR.json" />
<EmbeddedResource Include="Localization\Core\es-MX.json" />
<EmbeddedResource Include="Localization\Core\es.json" />
<EmbeddedResource Include="Localization\Core\fi.json" />
<EmbeddedResource Include="Localization\Core\fr-CA.json" />
<EmbeddedResource Include="Localization\Core\fr.json" />
<EmbeddedResource Include="Localization\Core\gsw.json" />
<EmbeddedResource Include="Localization\Core\he.json" />
<EmbeddedResource Include="Localization\Core\hr.json" />
<EmbeddedResource Include="Localization\Core\hu.json" />
<EmbeddedResource Include="Localization\Core\id.json" />
<EmbeddedResource Include="Localization\Core\it.json" />
<EmbeddedResource Include="Localization\Core\kk.json" />
<EmbeddedResource Include="Localization\Core\ko.json" />
<EmbeddedResource Include="Localization\Core\ms.json" />
<EmbeddedResource Include="Localization\Core\nb.json" />
<EmbeddedResource Include="Localization\Core\nl.json" />
<EmbeddedResource Include="Localization\Core\pl.json" />
<EmbeddedResource Include="Localization\Core\pt-BR.json" />
<EmbeddedResource Include="Localization\Core\pt-PT.json" />
<EmbeddedResource Include="Localization\Core\ro.json" />
<EmbeddedResource Include="Localization\Core\ru.json" />
<EmbeddedResource Include="Localization\Core\sl-SI.json" />
<EmbeddedResource Include="Localization\Core\sv.json" />
<EmbeddedResource Include="Localization\Core\tr.json" />
<EmbeddedResource Include="Localization\Core\uk.json" />
<EmbeddedResource Include="Localization\Core\vi.json" />
<EmbeddedResource Include="Localization\Core\zh-CN.json" />
<EmbeddedResource Include="Localization\Core\zh-HK.json" />
<EmbeddedResource Include="Localization\Core\zh-TW.json" />
<EmbeddedResource Include="Localization\countries.json" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="Localization\Ratings\ca.txt" />
</ItemGroup>
<ItemGroup>
<Content Include="..\ThirdParty\ServiceStack\swagger-ui\css\reset.css">
<Link>swagger-ui\css\reset.css</Link>
@ -665,8 +648,6 @@
<Link>swagger-ui\lib\shred\content.js</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<EmbeddedResource Include="Localization\iso6392.txt" />
<EmbeddedResource Include="Localization\Ratings\be.txt" />
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

View File

@ -1,170 +0,0 @@
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Plugins;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.News;
using MediaBrowser.Model.Notifications;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.IO;
using MediaBrowser.Model.IO;
using MediaBrowser.Server.Implementations.Threading;
namespace MediaBrowser.Server.Implementations.News
{
public class NewsEntryPoint : IServerEntryPoint
{
private PeriodicTimer _timer;
private readonly IHttpClient _httpClient;
private readonly IApplicationPaths _appPaths;
private readonly IFileSystem _fileSystem;
private readonly ILogger _logger;
private readonly IJsonSerializer _json;
private readonly INotificationManager _notifications;
private readonly IUserManager _userManager;
private readonly TimeSpan _frequency = TimeSpan.FromHours(24);
public NewsEntryPoint(IHttpClient httpClient, IApplicationPaths appPaths, IFileSystem fileSystem, ILogger logger, IJsonSerializer json, INotificationManager notifications, IUserManager userManager)
{
_httpClient = httpClient;
_appPaths = appPaths;
_fileSystem = fileSystem;
_logger = logger;
_json = json;
_notifications = notifications;
_userManager = userManager;
}
public void Run()
{
_timer = new PeriodicTimer(OnTimerFired, null, TimeSpan.FromMilliseconds(500), _frequency);
}
/// <summary>
/// Called when [timer fired].
/// </summary>
/// <param name="state">The state.</param>
private async void OnTimerFired(object state)
{
var path = Path.Combine(_appPaths.CachePath, "news.json");
try
{
await DownloadNews(path).ConfigureAwait(false);
}
catch (Exception ex)
{
_logger.ErrorException("Error downloading news", ex);
}
}
private async Task DownloadNews(string path)
{
DateTime? lastUpdate = null;
if (_fileSystem.FileExists(path))
{
lastUpdate = _fileSystem.GetLastWriteTimeUtc(path);
}
var requestOptions = new HttpRequestOptions
{
Url = "http://emby.media/community/index.php?/blog/rss/1-media-browser-developers-blog",
Progress = new Progress<double>(),
UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.42 Safari/537.36",
BufferContent = false
};
using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false))
{
var doc = new XmlDocument();
doc.Load(stream);
var news = ParseRssItems(doc).ToList();
_json.SerializeToFile(news, path);
await CreateNotifications(news, lastUpdate, CancellationToken.None).ConfigureAwait(false);
}
}
private Task CreateNotifications(List<NewsItem> items, DateTime? lastUpdate, CancellationToken cancellationToken)
{
if (lastUpdate.HasValue)
{
items = items.Where(i => i.Date.ToUniversalTime() >= lastUpdate.Value)
.ToList();
}
var tasks = items.Select(i => _notifications.SendNotification(new NotificationRequest
{
Date = i.Date,
Name = i.Title,
Description = i.Description,
Url = i.Link,
UserIds = _userManager.Users.Select(u => u.Id.ToString("N")).ToList()
}, cancellationToken));
return Task.WhenAll(tasks);
}
private IEnumerable<NewsItem> ParseRssItems(XmlDocument xmlDoc)
{
var nodes = xmlDoc.SelectNodes("rss/channel/item");
if (nodes != null)
{
foreach (XmlNode node in nodes)
{
var newsItem = new NewsItem();
newsItem.Title = ParseDocElements(node, "title");
newsItem.DescriptionHtml = ParseDocElements(node, "description");
newsItem.Description = newsItem.DescriptionHtml.StripHtml();
newsItem.Link = ParseDocElements(node, "link");
var date = ParseDocElements(node, "pubDate");
DateTime parsedDate;
if (DateTime.TryParse(date, out parsedDate))
{
newsItem.Date = parsedDate;
}
yield return newsItem;
}
}
}
private string ParseDocElements(XmlNode parent, string xPath)
{
var node = parent.SelectSingleNode(xPath);
return node != null ? node.InnerText : string.Empty;
}
public void Dispose()
{
if (_timer != null)
{
_timer.Dispose();
_timer = null;
}
}
}
}

View File

@ -1,8 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Emby.XmlTv" version="1.0.0.62" targetFramework="net46" />
<package id="Emby.XmlTv" version="1.0.0.63" targetFramework="net46" />
<package id="ini-parser" version="2.3.0" targetFramework="net45" />
<package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" />
<package id="Microsoft.IO.RecyclableMemoryStream" version="1.1.0.0" targetFramework="net46" />
<package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" />
<package id="SocketHttpListener" version="1.0.0.40" targetFramework="net45" />

View File

@ -59,7 +59,6 @@ using MediaBrowser.Server.Implementations.HttpServer.Security;
using MediaBrowser.Server.Implementations.IO;
using MediaBrowser.Server.Implementations.LiveTv;
using MediaBrowser.Server.Implementations.Localization;
using MediaBrowser.Server.Implementations.MediaEncoder;
using MediaBrowser.Server.Implementations.Notifications;
using MediaBrowser.Server.Implementations.Persistence;
using MediaBrowser.Server.Implementations.Security;
@ -107,6 +106,7 @@ using Emby.Server.Implementations.Devices;
using Emby.Server.Implementations.Dto;
using Emby.Server.Implementations.FileOrganization;
using Emby.Server.Implementations.Library;
using Emby.Server.Implementations.MediaEncoder;
using Emby.Server.Implementations.Notifications;
using Emby.Server.Implementations.Persistence;
using Emby.Server.Implementations.Playlists;

View File

@ -38,6 +38,10 @@
<Reference Include="Emby.Dlna">
<HintPath>..\ThirdParty\emby\Emby.Dlna.dll</HintPath>
</Reference>
<Reference Include="MediaBrowser.Naming, Version=1.0.6151.30291, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MediaBrowser.Naming.1.0.0.59\lib\portable-net45+win8\MediaBrowser.Naming.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="Mono.Posix, Version=4.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Mono.Posix.4.0.0.0\lib\net40\Mono.Posix.dll</HintPath>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MediaBrowser.Naming" version="1.0.0.59" targetFramework="net46" />
<package id="Mono.Posix" version="4.0.0.0" targetFramework="net45" />
<package id="Patterns.Logging" version="1.0.0.6" targetFramework="net46" />
<package id="SimpleInjector" version="3.2.4" targetFramework="net46" />

View File

@ -32,11 +32,6 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Patterns.Logging">
<HintPath>..\packages\Patterns.Logging.1.0.0.2\lib\portable-net45+sl4+wp71+win8+wpa81\Patterns.Logging.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="..\SharedVersion.cs">
<Link>Properties\SharedVersion.cs</Link>

View File

@ -1,4 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Patterns.Logging" version="1.0.0.2" targetFramework="net45" />
</packages>