History VIew Added.

Fixed Relationships between History and Episode/Indexer.
Indexer now uses int as ID, string caused issues.
Get single Indexer by ID.
This commit is contained in:
Mark McDowall 2011-03-22 22:19:23 -07:00
parent 4f2f5a3d71
commit 33b09567ce
14 changed files with 1704 additions and 48 deletions

View File

@ -20,7 +20,7 @@ namespace NzbDrone.Core.Test
public void AllItems()
{
//Setup
var indexer = new Indexer { Enabled = true, IndexerName = "NzbMatrix", Order = 1, RssUrl = "http://www.nzbmatrix.com" };
var indexer = new Indexer { Enabled = true, IndexerId = 0, IndexerName = "NzbMatrix", Order = 1, RssUrl = "http://www.nzbmatrix.com" };
var series = new Series
{
SeriesId = 5656,
@ -52,7 +52,7 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerName = indexer.IndexerName,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});
@ -105,7 +105,7 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerName = indexer.IndexerName,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});
@ -161,7 +161,7 @@ namespace NzbDrone.Core.Test
Date = DateTime.Now,
IsProper = false,
Quality = QualityTypes.TV,
IndexerName = indexer.IndexerName,
IndexerId = indexer.IndexerId,
EpisodeId = episode.EpisodeId
});

View File

@ -24,6 +24,7 @@ namespace NzbDrone.Core
private static IKernel _kernel;
private static readonly Object kernelLock = new object();
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private static string _startupPath;
public static void BindKernel()
{
@ -86,6 +87,9 @@ namespace NzbDrone.Core
SetupIndexers(_kernel.Get<IRepository>()); //Setup the default set of indexers on start-up
SetupDefaultQualityProfiles(_kernel.Get<IRepository>()); //Setup the default QualityProfiles on start-up
//Store the startup path
_startupPath = AppPath;
//Get the Timers going
var config = _kernel.Get<IConfigProvider>();
var timer = _kernel.Get<ITimerProvider>();
@ -116,6 +120,11 @@ namespace NzbDrone.Core
}
}
public static string StartupPath
{
get { return _startupPath; }
}
public static IKernel NinjectKernel
{
get
@ -134,6 +143,8 @@ namespace NzbDrone.Core
repository.GetPaged<EpisodeFile>(0, 1);
repository.GetPaged<Episode>(0, 1);
repository.GetPaged<Season>(0, 1);
repository.GetPaged<History>(0, 1);
repository.GetPaged<Indexer>(0, 1);
}
/// <summary>
@ -182,6 +193,7 @@ namespace NzbDrone.Core
var nzbMatrixIndexer = new Indexer
{
IndexerId = 1,
IndexerName = "NzbMatrix",
RssUrl = nzbMatrixRss,
ApiUrl = nzbMatrixApi,
@ -190,6 +202,7 @@ namespace NzbDrone.Core
var nzbsOrgIndexer = new Indexer
{
IndexerId = 2,
IndexerName = "NzbsOrg",
RssUrl = nzbsOrgRss,
ApiUrl = nzbsOrgApi,
@ -198,6 +211,7 @@ namespace NzbDrone.Core
var nzbsrusIndexer = new Indexer
{
IndexerId = 3,
IndexerName = "Nzbsrus",
RssUrl = nzbsrusRss,
ApiUrl = nzbsrusApi,
@ -206,7 +220,7 @@ namespace NzbDrone.Core
//NzbMatrix
Logger.Debug("Checking for NzbMatrix Indexer");
var nzbMatix = repository.Single<Indexer>("NzbMatrix");
var nzbMatix = repository.Single<Indexer>(1);
if (nzbMatix == null)
{
Logger.Debug("Adding new Indexer: NzbMatrix");
@ -223,7 +237,7 @@ namespace NzbDrone.Core
//Nzbs.org
Logger.Debug("Checking for Nzbs.org");
var nzbsOrg = repository.Single<Indexer>("NzbsOrg");
var nzbsOrg = repository.Single<Indexer>(2);
if (nzbsOrg == null)
{
Logger.Debug("Adding new Indexer: Nzbs.org");
@ -240,7 +254,7 @@ namespace NzbDrone.Core
//Nzbsrus
Logger.Debug("Checking for Nzbsrus");
var nzbsrus = repository.Single<Indexer>("Nzbsrus");
var nzbsrus = repository.Single<Indexer>(3);
if (nzbsrus == null)
{
Logger.Debug("Adding new Indexer: Nzbsrus");

View File

@ -44,7 +44,7 @@ namespace NzbDrone.Core.Providers
public void Insert(History item)
{
_sonicRepo.Add(item);
Logger.Info("Item added to history: {0} - {1}x{2:00}", item.Episode.Series.Title, item.Episode.SeasonNumber, item.Episode.EpisodeNumber);
//Logger.Info("Item added to history: {0} - {1}x{2:00}", item.Episode.Series.Title, item.Episode.SeasonNumber, item.Episode.EpisodeNumber);
}
public bool Exists(int episodeId, QualityTypes quality, bool proper)

View File

@ -12,5 +12,6 @@ namespace NzbDrone.Core.Providers
List<Indexer> AllIndexers();
List<Indexer> EnabledIndexers();
void Update(Indexer indexer);
Indexer Single(int indexerId);
}
}

View File

@ -39,6 +39,11 @@ namespace NzbDrone.Core.Providers
_sonicRepo.Update(indexer);
}
public Indexer Single(int indexerId)
{
return _sonicRepo.Single<Indexer>(indexerId);
}
#endregion
}
}

View File

@ -53,7 +53,7 @@ namespace NzbDrone.Core.Providers
var episodeParseResults = Parser.ParseEpisodeInfo(nzb.Title);
if (episodeParseResults.Count() > 1)
if (episodeParseResults.Count() > 0)
{
ProcessStandardItem(nzb, indexer, episodeParseResults);
return false;
@ -70,6 +70,7 @@ namespace NzbDrone.Core.Providers
catch (Exception ex)
{
Logger.Error("Unsupported Title: {0}", nzb.Title);
Logger.ErrorException("Error Parsing NZB: " + ex.Message, ex);
}
return false;
@ -89,8 +90,10 @@ namespace NzbDrone.Core.Providers
if (episodeInDb == null)
{
Logger.Debug("Episode Not found in Database");
return String.Format("{0} - {1:00}x{2}", series.Title, episode.SeasonNumber, episode.SeriesTitle);
//Todo: Handle this some other way?
Logger.Debug("Episode Not found in Database, Fake it...");
//return String.Format("{0} - {1:00}x{2}", series.Title, episode.SeasonNumber, episode.EpisodeNumber);
episodeInDb = new Episode { EpisodeNumber = episode.EpisodeNumber, Title = "TBA" };
}
seasonNumber = episodeInDb.SeasonNumber;
@ -149,7 +152,7 @@ namespace NzbDrone.Core.Providers
var titleFix = GetTitleFix(new List<EpisodeParseResult> { episode }, episodeModel.SeriesId);
titleFix = String.Format("{0} [{1}]", titleFix, nzb.Quality); //Add Quality to the titleFix
if (Convert.ToBoolean(_configProvider.GetValue("UseBlackhole", true, true)))
if (!Convert.ToBoolean(_configProvider.GetValue("UseBlackhole", true, true)))
if (_sabProvider.IsInQueue(titleFix))
return;
}
@ -165,11 +168,17 @@ namespace NzbDrone.Core.Providers
if (String.IsNullOrEmpty(path))
{
//Use the NZBDrone root Directory + /NZBs
path = CentralDispatch.AppPath + Path.DirectorySeparatorChar + "NZBs";
//path = CentralDispatch.StartupPath + "NZBs";
path = @"C:\Test\NZBs";
}
if (_diskProvider.FolderExists(path))
_httpProvider.DownloadFile(nzb.Link.ToString(), path);
{
var filename = path + Path.DirectorySeparatorChar + nzb.TitleFix;
if (_httpProvider.DownloadFile(nzb.Link.ToString(), filename))
AddToHistory(episodeParseResults, series, nzb, indexer);
}
else
Logger.Error("Blackhole Directory doesn't exist, not saving NZB: '{0}'", path);
@ -185,7 +194,13 @@ namespace NzbDrone.Core.Providers
}
if (indexer.IndexerName != "Newzbin")
AddByUrl(episodeParseResults, series, nzb, indexer);
{
if (AddByUrl(nzb))
{
AddToHistory(episodeParseResults, series, nzb, indexer);
}
}
else
{
@ -195,35 +210,37 @@ namespace NzbDrone.Core.Providers
}
private void AddByUrl(List<EpisodeParseResult> episodeParseResults, Series series, NzbInfoModel nzb, Indexer indexer)
private bool AddByUrl(NzbInfoModel nzb)
{
if (_sabProvider.AddByUrl(nzb.Link.ToString(), nzb.TitleFix))
return _sabProvider.AddByUrl(nzb.Link.ToString(), nzb.TitleFix);
}
private void AddToHistory(List<EpisodeParseResult> episodeParseResults, Series series, NzbInfoModel nzb, Indexer indexer)
{
//We need to loop through the episodeParseResults so each episode in the NZB is properly handled
foreach (var epr in episodeParseResults)
{
//We need to loop through the episodeParseResults so each episode in the NZB is properly handled
foreach (var epr in episodeParseResults)
var episode = _episodeProvider.GetEpisode(series.SeriesId, epr.SeasonNumber, epr.EpisodeNumber);
if (episode == null)
{
var episode = _episodeProvider.GetEpisode(series.SeriesId, epr.SeasonNumber, epr.EpisodeNumber);
if (episode == null)
{
//Not sure how we got this far, so lets throw an exception
throw new ArgumentOutOfRangeException();
}
//Set episode status to grabbed
episode.Status = EpisodeStatusType.Grabbed;
//Add to History
var history = new History();
history.Date = DateTime.Now;
history.EpisodeId = episode.EpisodeId;
history.IndexerName = indexer.IndexerName;
history.IsProper = nzb.Proper;
history.Quality = nzb.Quality;
history.NzbTitle = nzb.Title;
_historyProvider.Insert(history);
//Not sure how we got this far, so lets throw an exception
throw new ArgumentOutOfRangeException();
}
//Set episode status to grabbed
episode.Status = EpisodeStatusType.Grabbed;
//Add to History
var history = new History();
history.Date = DateTime.Now;
history.EpisodeId = episode.EpisodeId;
history.IndexerId = indexer.IndexerId;
history.IsProper = nzb.Proper;
history.Quality = nzb.Quality;
history.NzbTitle = nzb.Title;
_historyProvider.Insert(history);
}
}
}

View File

@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;
using NzbDrone.Core.Model;
using SubSonic.SqlGeneration.Schema;

View File

@ -1,7 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NzbDrone.Core.Repository.Quality;
using SubSonic.SqlGeneration.Schema;
@ -9,9 +6,10 @@ namespace NzbDrone.Core.Repository
{
public class History
{
public int HistoryId { get; set; }
[SubSonicPrimaryKey(true)]
public virtual int HistoryId { get; set; }
public virtual int EpisodeId { get; set; }
public virtual string IndexerName { get; set; }
public virtual int IndexerId { get; set; }
public string NzbTitle { get; set; }
public QualityTypes Quality { get; set; }
public DateTime Date { get; set; }

View File

@ -10,7 +10,9 @@ namespace NzbDrone.Core.Repository
{
public class Indexer
{
[SubSonicPrimaryKey(true)]
[SubSonicPrimaryKey(false)]
public virtual int IndexerId { get; set; }
public string IndexerName { get; set; }
public string RssUrl { get; set; }

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NzbDrone.Core.Providers;
using NzbDrone.Core.Repository.Quality;
using NzbDrone.Web.Models;
using Telerik.Web.Mvc;
namespace NzbDrone.Web.Controllers
{
public class HistoryController : Controller
{
private IHistoryProvider _historyProvider;
public HistoryController(IHistoryProvider historyProvider)
{
_historyProvider = historyProvider;
}
//
// GET: /History/
public ActionResult Index()
{
return View();
}
public ActionResult Trim()
{
_historyProvider.Trim();
return RedirectToAction("Index");
}
public ActionResult Purge()
{
_historyProvider.Purge();
return RedirectToAction("Index");
}
[GridAction]
public ActionResult _AjaxBinding()
{
var history = _historyProvider.AllItems().Select(h => new HistoryModel
{
HistoryId = h.HistoryId,
SeasonNumber = h.Episode.SeasonNumber,
EpisodeNumber = h.Episode.EpisodeNumber,
EpisodeTitle = h.Episode.Title,
EpisodeOverview = h.Episode.Overview,
SeriesTitle = h.Episode.Series.Title,
NzbTitle = h.NzbTitle,
Quality = h.Quality.ToString("G"),
IsProper = h.IsProper,
Date = h.Date
});
return View(new GridModel(history));
}
}
}

View File

@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using NzbDrone.Core.Repository;
using NzbDrone.Core.Repository.Quality;
namespace NzbDrone.Web.Models
{
public class HistoryModel
{
public int HistoryId { get; set; }
public string SeriesTitle { get; set; }
public int SeasonNumber { get; set; }
public int EpisodeNumber { get; set; }
public string EpisodeTitle { get; set; }
public string EpisodeOverview { get; set; }
public string NzbTitle { get; set; }
public string Quality { get; set; }
public DateTime Date { get; set; }
public bool IsProper { get; set; }
}
}

View File

@ -96,6 +96,7 @@
<Compile Include="Models\AddNewSeriesModel.cs" />
<Compile Include="Models\DownloadSettingsModel.cs" />
<Compile Include="Models\EpisodeSortingModel.cs" />
<Compile Include="Models\HistoryModel.cs" />
<Compile Include="Models\IndexerSettingsModel.cs" />
<Compile Include="Models\MappingModel.cs" />
<Compile Include="Models\EpisodeModel.cs" />

View File

@ -0,0 +1,62 @@
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<List<NzbDrone.Web.Models.HistoryModel>>" %>
<%@ Import Namespace="Telerik.Web.Mvc.UI" %>
<%@ Import Namespace="NzbDrone.Web.Models" %>
<asp:Content ID="Content1" ContentPlaceHolderID="Scripts" runat="server">
<script type="text/javascript">
function onRowDataBound(e) {
e.row.style.boarder = "";
if (e.dataItem.Level == 3) {
e.row.style.backgroundColor = "#FFD700";
}
else if (e.dataItem.Level == 4) {
e.row.style.backgroundColor = "#FF7500";
}
else if (e.dataItem.Level == 5) {
e.row.style.backgroundColor = "black";
e.row.style.color = "red";
}
//e.row.style.color = 'blue';
}
</script>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="TitleContent" runat="server">
History
</asp:Content>
<asp:Content ID="Menu" ContentPlaceHolderID="ActionMenu" runat="server">
<%
Html.Telerik().Menu().Name("historyMenu").Items(items =>
{
items.Add().Text("Trim History").Action("Trim", "History");
items.Add().Text("Purge History").Action("Purge", "History");
}).Render();
%>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="MainContent" runat="server">
<%Html.Telerik().Grid<HistoryModel>().Name("history")
.Columns(columns =>
{
columns.Bound(c => c.SeriesTitle).Title("Series Name").Width(120);
columns.Bound(c => c.SeasonNumber).Title("Season #").Width(10);
columns.Bound(c => c.EpisodeNumber).Title("Episode #").Width(10);
columns.Bound(c => c.EpisodeTitle).Title("Episode Title").Width(140);
columns.Bound(c => c.Quality).Title("Quality").Width(30);
columns.Bound(c => c.Date).Title("Date Grabbed").Width(60);
})
.DetailView(detailView => detailView.ClientTemplate(
"<div><b>Overview: </b><#= EpisodeOverview #></div>" +
"<div><b>NZB Title: </b><#= NzbTitle #></div>" +
"<div><b>Proper: </b><#= IsProper #></div>"
))
.DataBinding(data => data.Ajax().Select("_AjaxBinding", "History"))
.Sortable(rows => rows.OrderBy(epSort => epSort.Add(c => c.Date).Descending()).Enabled(true))
.Pageable(c => c.PageSize(20).Position(GridPagerPosition.Both).Style(GridPagerStyles.PageInput | GridPagerStyles.NextPreviousAndNumeric))
//.Filterable()
//.ClientEvents(c => c.OnRowDataBound("onRowDataBound"))
.Render();
%>
</asp:Content>