aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2014-01-18 16:52:01 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2014-01-18 16:52:01 -0500
commit7f51148130a95b73c1d2cfac10aa04b3817944b5 (patch)
tree6cf65c3e33504eae9827dfaf5e990d49a26cd904
parent5ca7d6355684b1599a0ceb952b93e25e74e6c098 (diff)
display news on dashboard home page
-rw-r--r--MediaBrowser.Api/MediaBrowser.Api.csproj1
-rw-r--r--MediaBrowser.Api/NewsService.cs48
-rw-r--r--MediaBrowser.Controller/MediaBrowser.Controller.csproj1
-rw-r--r--MediaBrowser.Controller/News/INewsService.cs19
-rw-r--r--MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj3
-rw-r--r--MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj3
-rw-r--r--MediaBrowser.Model/MediaBrowser.Model.csproj1
-rw-r--r--MediaBrowser.Model/News/NewsItem.cs29
-rw-r--r--MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj1
-rw-r--r--MediaBrowser.Server.Implementations/News/NewsService.cs132
-rw-r--r--MediaBrowser.ServerApplication/ApplicationHost.cs5
-rw-r--r--MediaBrowser.WebDashboard/ApiClient.js13
-rw-r--r--MediaBrowser.WebDashboard/packages.config2
13 files changed, 257 insertions, 1 deletions
diff --git a/MediaBrowser.Api/MediaBrowser.Api.csproj b/MediaBrowser.Api/MediaBrowser.Api.csproj
index a04aca2a0..a46f82ae0 100644
--- a/MediaBrowser.Api/MediaBrowser.Api.csproj
+++ b/MediaBrowser.Api/MediaBrowser.Api.csproj
@@ -93,6 +93,7 @@
<Compile Include="LiveTv\LiveTvService.cs" />
<Compile Include="LocalizationService.cs" />
<Compile Include="MoviesService.cs" />
+ <Compile Include="NewsService.cs" />
<Compile Include="NotificationsService.cs" />
<Compile Include="PackageReviewService.cs" />
<Compile Include="PackageService.cs" />
diff --git a/MediaBrowser.Api/NewsService.cs b/MediaBrowser.Api/NewsService.cs
new file mode 100644
index 000000000..1875db64a
--- /dev/null
+++ b/MediaBrowser.Api/NewsService.cs
@@ -0,0 +1,48 @@
+using MediaBrowser.Controller.News;
+using MediaBrowser.Model.News;
+using MediaBrowser.Model.Querying;
+using ServiceStack;
+
+namespace MediaBrowser.Api
+{
+ [Route("/News/Product", "GET")]
+ [Api(Description = "Gets search hints based on a search term")]
+ public class GetProductNews : IReturn<QueryResult<NewsItem>>
+ {
+ /// <summary>
+ /// Skips over a given number of items within the results. Use for paging.
+ /// </summary>
+ /// <value>The start index.</value>
+ [ApiMember(Name = "StartIndex", Description = "Optional. The record index to start at. All items with a lower index will be dropped from the results.", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? StartIndex { get; set; }
+
+ /// <summary>
+ /// The maximum number of items to return
+ /// </summary>
+ /// <value>The limit.</value>
+ [ApiMember(Name = "Limit", Description = "Optional. The maximum number of records to return", IsRequired = false, DataType = "int", ParameterType = "query", Verb = "GET")]
+ public int? Limit { get; set; }
+ }
+
+ public class NewsService : BaseApiService
+ {
+ private readonly INewsService _newsService;
+
+ public NewsService(INewsService newsService)
+ {
+ _newsService = newsService;
+ }
+
+ public object Get(GetProductNews request)
+ {
+ var result = _newsService.GetProductNews(new NewsQuery
+ {
+ StartIndex = request.StartIndex,
+ Limit = request.Limit
+
+ }).Result;
+
+ return ToOptimizedResult(result);
+ }
+ }
+}
diff --git a/MediaBrowser.Controller/MediaBrowser.Controller.csproj b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
index 353e92444..53632a51c 100644
--- a/MediaBrowser.Controller/MediaBrowser.Controller.csproj
+++ b/MediaBrowser.Controller/MediaBrowser.Controller.csproj
@@ -136,6 +136,7 @@
<Compile Include="Net\IHttpResultFactory.cs" />
<Compile Include="Net\IHttpServer.cs" />
<Compile Include="Net\IRestfulService.cs" />
+ <Compile Include="News\INewsService.cs" />
<Compile Include="Notifications\INotificationsRepository.cs" />
<Compile Include="Notifications\NotificationUpdateEventArgs.cs" />
<Compile Include="Persistence\MediaStreamQuery.cs" />
diff --git a/MediaBrowser.Controller/News/INewsService.cs b/MediaBrowser.Controller/News/INewsService.cs
new file mode 100644
index 000000000..e3d238cc6
--- /dev/null
+++ b/MediaBrowser.Controller/News/INewsService.cs
@@ -0,0 +1,19 @@
+using MediaBrowser.Model.News;
+using MediaBrowser.Model.Querying;
+using System.Threading.Tasks;
+
+namespace MediaBrowser.Controller.News
+{
+ /// <summary>
+ /// Interface INewsFeed
+ /// </summary>
+ public interface INewsService
+ {
+ /// <summary>
+ /// Gets the product news.
+ /// </summary>
+ /// <param name="query">The query.</param>
+ /// <returns>IEnumerable{NewsItem}.</returns>
+ Task<QueryResult<NewsItem>> GetProductNews(NewsQuery query);
+ }
+}
diff --git a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
index 40c71ec3c..708573e8f 100644
--- a/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
+++ b/MediaBrowser.Model.Portable/MediaBrowser.Model.Portable.csproj
@@ -290,6 +290,9 @@
<Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs">
<Link>Net\WebSocketState.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsItem.cs">
+ <Link>News\NewsItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\Notification.cs">
<Link>Notifications\Notification.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
index c03b87243..5fe9c4e5c 100644
--- a/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
+++ b/MediaBrowser.Model.net35/MediaBrowser.Model.net35.csproj
@@ -277,6 +277,9 @@
<Compile Include="..\MediaBrowser.Model\Net\WebSocketState.cs">
<Link>Net\WebSocketState.cs</Link>
</Compile>
+ <Compile Include="..\MediaBrowser.Model\News\NewsItem.cs">
+ <Link>News\NewsItem.cs</Link>
+ </Compile>
<Compile Include="..\MediaBrowser.Model\Notifications\Notification.cs">
<Link>Notifications\Notification.cs</Link>
</Compile>
diff --git a/MediaBrowser.Model/MediaBrowser.Model.csproj b/MediaBrowser.Model/MediaBrowser.Model.csproj
index fff999172..0eddcd7e7 100644
--- a/MediaBrowser.Model/MediaBrowser.Model.csproj
+++ b/MediaBrowser.Model/MediaBrowser.Model.csproj
@@ -80,6 +80,7 @@
<Compile Include="LiveTv\RecordingStatus.cs" />
<Compile Include="LiveTv\SeriesTimerInfoDto.cs" />
<Compile Include="LiveTv\TimerInfoDto.cs" />
+ <Compile Include="News\NewsItem.cs" />
<Compile Include="Providers\ImageProviderInfo.cs" />
<Compile Include="Providers\RemoteImageInfo.cs" />
<Compile Include="Dto\StudioDto.cs" />
diff --git a/MediaBrowser.Model/News/NewsItem.cs b/MediaBrowser.Model/News/NewsItem.cs
new file mode 100644
index 000000000..6dbe5a79e
--- /dev/null
+++ b/MediaBrowser.Model/News/NewsItem.cs
@@ -0,0 +1,29 @@
+using System;
+using System.Collections.Generic;
+
+namespace MediaBrowser.Model.News
+{
+ public class NewsChannel
+ {
+ public string Title { get; set; }
+ public string Link { get; set; }
+ public string Description { get; set; }
+ public List<NewsItem> Items { get; set; }
+ }
+
+ public class NewsItem
+ {
+ public string Title { get; set; }
+ public string Link { get; set; }
+ public string Description { get; set; }
+ public string Guid { get; set; }
+ public DateTime Date { get; set; }
+ }
+
+ public class NewsQuery
+ {
+ public int? StartIndex { get; set; }
+
+ public int? Limit { get; set; }
+ }
+}
diff --git a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
index e530eca46..907301699 100644
--- a/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
+++ b/MediaBrowser.Server.Implementations/MediaBrowser.Server.Implementations.csproj
@@ -173,6 +173,7 @@
<Compile Include="LiveTv\RefreshChannelsScheduledTask.cs" />
<Compile Include="Localization\LocalizationManager.cs" />
<Compile Include="MediaEncoder\MediaEncoder.cs" />
+ <Compile Include="News\NewsService.cs" />
<Compile Include="Persistence\SqliteChapterRepository.cs" />
<Compile Include="Persistence\SqliteExtensions.cs" />
<Compile Include="Persistence\SqliteMediaStreamsRepository.cs" />
diff --git a/MediaBrowser.Server.Implementations/News/NewsService.cs b/MediaBrowser.Server.Implementations/News/NewsService.cs
new file mode 100644
index 000000000..b01470d31
--- /dev/null
+++ b/MediaBrowser.Server.Implementations/News/NewsService.cs
@@ -0,0 +1,132 @@
+using MediaBrowser.Common.Configuration;
+using MediaBrowser.Common.IO;
+using MediaBrowser.Common.Net;
+using MediaBrowser.Controller.News;
+using MediaBrowser.Model.News;
+using MediaBrowser.Model.Querying;
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Threading.Tasks;
+using System.Xml;
+
+namespace MediaBrowser.Server.Implementations.News
+{
+ public class NewsService : INewsService
+ {
+ private readonly IApplicationPaths _appPaths;
+ private readonly IFileSystem _fileSystem;
+ private readonly IHttpClient _httpClient;
+
+ public NewsService(IApplicationPaths appPaths, IFileSystem fileSystem, IHttpClient httpClient)
+ {
+ _appPaths = appPaths;
+ _fileSystem = fileSystem;
+ _httpClient = httpClient;
+ }
+
+ public async Task<QueryResult<NewsItem>> GetProductNews(NewsQuery query)
+ {
+ var path = Path.Combine(_appPaths.CachePath, "news.xml");
+
+ await EnsureNewsFile(path).ConfigureAwait(false);
+
+ var items = GetNewsItems(path);
+
+ var itemsArray = items.ToArray();
+ var count = itemsArray.Length;
+
+ if (query.StartIndex.HasValue)
+ {
+ itemsArray = itemsArray.Skip(query.StartIndex.Value).ToArray();
+ }
+
+ if (query.Limit.HasValue)
+ {
+ itemsArray = itemsArray.Take(query.Limit.Value).ToArray();
+ }
+
+ return new QueryResult<NewsItem>
+ {
+ Items = itemsArray,
+ TotalRecordCount = count
+ };
+ }
+
+ private IEnumerable<NewsItem> GetNewsItems(string path)
+ {
+ var xmlDoc = new XmlDocument();
+
+ xmlDoc.Load(path);
+
+ return ParseRssItems(xmlDoc);
+ }
+
+ private IEnumerable<NewsItem> ParseRssItems(XmlDocument xmlDoc)
+ {
+ var nodes = xmlDoc.SelectNodes("rss/channel/item");
+
+ if (nodes == null)
+ {
+ yield return null;
+ }
+
+ foreach (XmlNode node in nodes)
+ {
+ var newsItem = new NewsItem();
+
+ newsItem.Title = ParseDocElements(node, "title");
+
+ newsItem.Description = ParseDocElements(node, "description");
+
+ 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 : "Unresolvable";
+ }
+
+
+ /// <summary>
+ /// Ensures the news file.
+ /// </summary>
+ /// <param name="path">The path.</param>
+ /// <returns>Task.</returns>
+ private async Task EnsureNewsFile(string path)
+ {
+ var info = _fileSystem.GetFileSystemInfo(path);
+
+ if (!info.Exists || (DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(info)).TotalHours > 24)
+ {
+ var requestOptions = new HttpRequestOptions
+ {
+ Url = "http://mediabrowser3.com/community/index.php?/blog/rss/1-media-browser-developers-blog",
+ Progress = new Progress<double>()
+ };
+
+ using (var stream = await _httpClient.Get(requestOptions).ConfigureAwait(false))
+ {
+ using (var fileStream = _fileSystem.GetFileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read, true))
+ {
+ await stream.CopyToAsync(fileStream).ConfigureAwait(false);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/MediaBrowser.ServerApplication/ApplicationHost.cs b/MediaBrowser.ServerApplication/ApplicationHost.cs
index 84adffecb..13e33c7a3 100644
--- a/MediaBrowser.ServerApplication/ApplicationHost.cs
+++ b/MediaBrowser.ServerApplication/ApplicationHost.cs
@@ -19,6 +19,7 @@ using MediaBrowser.Controller.LiveTv;
using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.MediaInfo;
using MediaBrowser.Controller.Net;
+using MediaBrowser.Controller.News;
using MediaBrowser.Controller.Notifications;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Plugins;
@@ -283,6 +284,10 @@ namespace MediaBrowser.ServerApplication
DtoService = new DtoService(Logger, LibraryManager, UserManager, UserDataManager, ItemRepository, ImageProcessor);
RegisterSingleInstance(DtoService);
+
+ var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, FileSystemManager, HttpClient);
+ RegisterSingleInstance<INewsService>(newsService);
+
progress.Report(15);
var innerProgress = new ActionableProgress<double>();
diff --git a/MediaBrowser.WebDashboard/ApiClient.js b/MediaBrowser.WebDashboard/ApiClient.js
index d8a1c45ce..2b282e5e4 100644
--- a/MediaBrowser.WebDashboard/ApiClient.js
+++ b/MediaBrowser.WebDashboard/ApiClient.js
@@ -197,6 +197,19 @@ MediaBrowser.ApiClient = function ($, navigator, JSON, WebSocket, setTimeout, wi
return webSocket && (webSocket.readyState === WebSocket.OPEN || webSocket.readyState === WebSocket.CONNECTING);
};
+ self.getProductNews = function (options) {
+
+ options = options || {};
+
+ var url = self.getUrl("News/Product", options);
+
+ return self.ajax({
+ type: "GET",
+ url: url,
+ dataType: "json"
+ });
+ };
+
/**
* Gets an item from the server
* Omit itemId to get the root folder.
diff --git a/MediaBrowser.WebDashboard/packages.config b/MediaBrowser.WebDashboard/packages.config
index 321ffd45c..70c1bd6e2 100644
--- a/MediaBrowser.WebDashboard/packages.config
+++ b/MediaBrowser.WebDashboard/packages.config
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
- <package id="MediaBrowser.ApiClient.Javascript" version="3.0.237" targetFramework="net45" />
+ <package id="MediaBrowser.ApiClient.Javascript" version="3.0.238" targetFramework="net45" />
</packages> \ No newline at end of file