2011-06-16 19:48:24 -07:00
|
|
|
using System;
|
2010-10-20 18:49:23 -07:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.IO;
|
|
|
|
using System.Linq;
|
2011-06-13 18:23:04 -07:00
|
|
|
using Ninject;
|
2010-10-20 18:49:23 -07:00
|
|
|
using NLog;
|
2011-06-06 23:29:07 -07:00
|
|
|
using NzbDrone.Core.Helpers;
|
2011-04-03 20:50:12 -07:00
|
|
|
using NzbDrone.Core.Providers.Core;
|
2010-10-20 18:49:23 -07:00
|
|
|
using NzbDrone.Core.Repository;
|
2011-06-06 23:29:07 -07:00
|
|
|
using NzbDrone.Core.Repository.Quality;
|
2011-06-16 20:29:39 -07:00
|
|
|
using PetaPoco;
|
2011-11-20 16:35:29 -08:00
|
|
|
using NzbDrone.Common;
|
2010-10-20 18:49:23 -07:00
|
|
|
|
|
|
|
namespace NzbDrone.Core.Providers
|
|
|
|
{
|
2011-04-09 18:34:36 -07:00
|
|
|
public class MediaFileProvider
|
2010-10-20 18:49:23 -07:00
|
|
|
{
|
|
|
|
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
|
2011-06-06 23:29:07 -07:00
|
|
|
private readonly ConfigProvider _configProvider;
|
2011-06-16 20:29:39 -07:00
|
|
|
private readonly IDatabase _database;
|
2011-06-19 20:25:04 -07:00
|
|
|
private readonly EpisodeProvider _episodeProvider;
|
2010-10-20 18:49:23 -07:00
|
|
|
|
2011-06-13 18:23:04 -07:00
|
|
|
[Inject]
|
2011-06-19 20:04:08 -07:00
|
|
|
public MediaFileProvider(EpisodeProvider episodeProvider, ConfigProvider configProvider, IDatabase database)
|
2010-10-20 18:49:23 -07:00
|
|
|
{
|
|
|
|
_episodeProvider = episodeProvider;
|
2011-06-06 23:29:07 -07:00
|
|
|
_configProvider = configProvider;
|
2011-06-16 20:29:39 -07:00
|
|
|
_database = database;
|
2010-10-20 18:49:23 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 20:25:04 -07:00
|
|
|
public MediaFileProvider()
|
|
|
|
{
|
|
|
|
}
|
2010-10-24 00:46:58 -07:00
|
|
|
|
2011-06-21 18:12:20 -07:00
|
|
|
public virtual int Add(EpisodeFile episodeFile)
|
|
|
|
{
|
|
|
|
return Convert.ToInt32(_database.Insert(episodeFile));
|
|
|
|
}
|
|
|
|
|
2011-05-17 22:32:23 -07:00
|
|
|
public virtual void Update(EpisodeFile episodeFile)
|
2011-02-17 22:49:23 -08:00
|
|
|
{
|
2011-06-16 20:29:39 -07:00
|
|
|
_database.Update(episodeFile);
|
2011-06-19 18:59:31 -07:00
|
|
|
}
|
2011-02-17 22:49:23 -08:00
|
|
|
|
2011-06-21 18:12:20 -07:00
|
|
|
public virtual void Delete(int episodeFileId)
|
|
|
|
{
|
2011-06-22 00:26:36 -07:00
|
|
|
_database.Delete<EpisodeFile>(episodeFileId);
|
2011-06-21 18:12:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
public virtual bool Exists(string path)
|
|
|
|
{
|
2011-11-20 16:35:29 -08:00
|
|
|
return _database.Exists<EpisodeFile>("WHERE Path =@0", path.NormalizePath());
|
2011-06-21 18:12:20 -07:00
|
|
|
}
|
|
|
|
|
2011-05-17 22:32:23 -07:00
|
|
|
public virtual EpisodeFile GetEpisodeFile(int episodeFileId)
|
2011-02-17 22:49:23 -08:00
|
|
|
{
|
2011-06-18 16:03:58 -07:00
|
|
|
return _database.Single<EpisodeFile>(episodeFileId);
|
2011-02-17 22:49:23 -08:00
|
|
|
}
|
|
|
|
|
2011-05-17 22:32:23 -07:00
|
|
|
public virtual List<EpisodeFile> GetEpisodeFiles()
|
2011-02-21 22:22:40 -08:00
|
|
|
{
|
2011-06-16 20:29:39 -07:00
|
|
|
return _database.Fetch<EpisodeFile>();
|
2011-02-21 22:22:40 -08:00
|
|
|
}
|
|
|
|
|
2011-06-19 13:43:33 -07:00
|
|
|
public virtual IList<EpisodeFile> GetSeriesFiles(int seriesId)
|
2011-02-23 16:40:11 -08:00
|
|
|
{
|
2011-08-21 17:48:37 -07:00
|
|
|
return _database.Fetch<EpisodeFile>("WHERE SeriesId= @0", seriesId);
|
|
|
|
}
|
|
|
|
|
|
|
|
public virtual IList<EpisodeFile> GetSeasonFiles(int seriesId, int seasonNumber)
|
|
|
|
{
|
|
|
|
return _database.Fetch<EpisodeFile>("WHERE SeriesId= @0 AND SeasonNumber = @1", seriesId, seasonNumber);
|
2011-02-23 16:40:11 -08:00
|
|
|
}
|
|
|
|
|
2011-06-02 20:04:39 -07:00
|
|
|
public virtual Tuple<int, int> GetEpisodeFilesCount(int seriesId)
|
|
|
|
{
|
2011-06-14 16:39:09 -07:00
|
|
|
var allEpisodes = _episodeProvider.GetEpisodeBySeries(seriesId).ToList();
|
2011-06-02 20:04:39 -07:00
|
|
|
|
2011-06-22 23:56:17 -07:00
|
|
|
var episodeTotal = allEpisodes.Where(e => !e.Ignored && e.AirDate != null && e.AirDate <= DateTime.Today).ToList();
|
2011-06-14 16:39:09 -07:00
|
|
|
var avilableEpisodes = episodeTotal.Where(e => e.EpisodeFileId > 0).ToList();
|
2011-06-02 20:04:39 -07:00
|
|
|
|
2011-06-14 16:39:09 -07:00
|
|
|
return new Tuple<int, int>(avilableEpisodes.Count, episodeTotal.Count);
|
2011-06-02 20:04:39 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 20:04:08 -07:00
|
|
|
public virtual FileInfo CalculateFilePath(Series series, int seasonNumber, string fileName, string extention)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-06-19 20:25:04 -07:00
|
|
|
string path = series.Path;
|
2011-06-19 20:04:08 -07:00
|
|
|
if (series.SeasonFolder)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-07-07 20:36:02 -07:00
|
|
|
var seasonFolder = _configProvider.SortingSeasonFolderFormat
|
2011-06-21 20:40:24 -07:00
|
|
|
.Replace("%0s", seasonNumber.ToString("00"))
|
|
|
|
.Replace("%s", seasonNumber.ToString());
|
|
|
|
|
|
|
|
path = Path.Combine(path, seasonFolder);
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
2011-06-07 14:19:11 -07:00
|
|
|
|
2011-06-19 20:04:08 -07:00
|
|
|
path = Path.Combine(path, fileName + extention);
|
2011-06-07 14:19:11 -07:00
|
|
|
|
2011-06-19 20:04:08 -07:00
|
|
|
return new FileInfo(path);
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
|
|
|
|
2011-06-20 23:34:45 -07:00
|
|
|
public virtual int RepairLinks()
|
2011-06-20 18:49:16 -07:00
|
|
|
{
|
2011-06-21 23:34:33 -07:00
|
|
|
Logger.Trace("Verifying Episode>Episode file relationships.");
|
2011-06-20 23:34:45 -07:00
|
|
|
var updated = _database.Execute(@"UPDATE Episodes SET EpisodeFileId = 0
|
2011-06-20 18:49:16 -07:00
|
|
|
WHERE EpisodeFileId IN
|
|
|
|
(SELECT Episodes.EpisodeFileId FROM Episodes
|
|
|
|
LEFT OUTER JOIN EpisodeFiles
|
|
|
|
ON Episodes.EpisodeFileId = EpisodeFiles.EpisodeFileId
|
|
|
|
WHERE Episodes.EpisodeFileId > 0 AND EpisodeFiles.EpisodeFileId IS null)");
|
2011-06-20 23:34:45 -07:00
|
|
|
|
|
|
|
if (updated > 0)
|
|
|
|
{
|
2011-06-21 23:34:33 -07:00
|
|
|
Logger.Debug("Removed {0} invalid links to episode files.", updated);
|
2011-06-20 23:34:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return updated;
|
2011-06-20 18:49:16 -07:00
|
|
|
}
|
|
|
|
|
2011-06-20 23:34:45 -07:00
|
|
|
public virtual int DeleteOrphaned()
|
2011-06-20 18:49:16 -07:00
|
|
|
{
|
2011-07-06 00:36:49 -07:00
|
|
|
Logger.Trace("Deleting orphan files.");
|
2011-06-20 23:34:45 -07:00
|
|
|
|
|
|
|
var updated = _database.Execute(@"DELETE FROM EpisodeFiles
|
2011-06-20 18:49:16 -07:00
|
|
|
WHERE EpisodeFileId IN
|
|
|
|
(SELECT EpisodeFiles.EpisodeFileId FROM EpisodeFiles
|
|
|
|
LEFT OUTER JOIN Episodes
|
|
|
|
ON EpisodeFiles.EpisodeFileId = Episodes.EpisodeFileId
|
|
|
|
WHERE Episodes.EpisodeFileId IS null)");
|
2011-06-20 23:34:45 -07:00
|
|
|
|
|
|
|
if (updated > 0)
|
|
|
|
{
|
2011-07-06 00:36:49 -07:00
|
|
|
Logger.Debug("Removed {0} orphan file(s) from database.S", updated);
|
2011-06-20 23:34:45 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
return updated;
|
2011-06-20 18:49:16 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 19:33:43 -07:00
|
|
|
public virtual string GetNewFilename(IList<Episode> episodes, string seriesTitle, QualityTypes quality)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-07-07 20:36:02 -07:00
|
|
|
var separatorStyle = EpisodeSortingHelper.GetSeparatorStyle(_configProvider.SortingSeparatorStyle);
|
|
|
|
var numberStyle = EpisodeSortingHelper.GetNumberStyle(_configProvider.SortingNumberStyle);
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-06-19 20:25:04 -07:00
|
|
|
string episodeNames = episodes[0].Title;
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-06-19 20:25:04 -07:00
|
|
|
string result = String.Empty;
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-07-07 20:36:02 -07:00
|
|
|
if (_configProvider.SortingIncludeSeriesName)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-06-19 19:33:43 -07:00
|
|
|
result += seriesTitle + separatorStyle.Pattern;
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
result += numberStyle.Pattern.Replace("%0e", String.Format("{0:00}", episodes[0].EpisodeNumber));
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
if (episodes.Count > 1)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-07-07 20:36:02 -07:00
|
|
|
var multiEpisodeStyle = EpisodeSortingHelper.GetMultiEpisodeStyle(_configProvider.SortingMultiEpisodeStyle);
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
foreach (var episode in episodes.OrderBy(e => e.EpisodeNumber).Skip(1))
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
2011-06-19 18:59:31 -07:00
|
|
|
if (multiEpisodeStyle.Name == "Duplicate")
|
|
|
|
{
|
|
|
|
result += separatorStyle.Pattern + numberStyle.Pattern;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
result += multiEpisodeStyle.Pattern;
|
|
|
|
}
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
result = result.Replace("%0e", String.Format("{0:00}", episode.EpisodeNumber));
|
|
|
|
episodeNames += String.Format(" + {0}", episode.Title);
|
|
|
|
}
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
result = result
|
|
|
|
.Replace("%s", String.Format("{0}", episodes.First().SeasonNumber))
|
|
|
|
.Replace("%0s", String.Format("{0:00}", episodes.First().SeasonNumber))
|
|
|
|
.Replace("%x", numberStyle.EpisodeSeparator)
|
|
|
|
.Replace("%p", separatorStyle.Pattern);
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-07-07 20:57:44 -07:00
|
|
|
if (_configProvider.SortingIncludeEpisodeTitle)
|
2011-06-06 23:29:07 -07:00
|
|
|
{
|
|
|
|
episodeNames = episodeNames.TrimEnd(' ', '+');
|
2011-06-19 18:59:31 -07:00
|
|
|
result += separatorStyle.Pattern + episodeNames;
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
|
|
|
|
2011-07-07 20:36:02 -07:00
|
|
|
if (_configProvider.SortingAppendQuality)
|
2011-06-19 18:59:31 -07:00
|
|
|
result += String.Format(" [{0}]", quality);
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-07-07 20:36:02 -07:00
|
|
|
if (_configProvider.SortingReplaceSpaces)
|
2011-06-19 18:59:31 -07:00
|
|
|
result = result.Replace(' ', '.');
|
2011-06-06 23:29:07 -07:00
|
|
|
|
2011-07-06 00:36:49 -07:00
|
|
|
Logger.Trace("New File Name is: [{0}]", result.Trim());
|
2011-06-20 16:46:54 -07:00
|
|
|
return CleanFilename(result.Trim());
|
|
|
|
}
|
|
|
|
|
|
|
|
public static string CleanFilename(string name)
|
|
|
|
{
|
|
|
|
string result = name;
|
|
|
|
string[] badCharacters = { "\\", "/", "<", ">", "?", "*", ":", "|", "\"" };
|
|
|
|
string[] goodCharacters = { "+", "+", "{", "}", "!", "@", "-", "#", "`" };
|
|
|
|
|
|
|
|
for (int i = 0; i < badCharacters.Length; i++)
|
|
|
|
result = result.Replace(badCharacters[i], goodCharacters[i]);
|
|
|
|
|
2011-06-19 18:59:31 -07:00
|
|
|
return result.Trim();
|
2011-06-06 23:29:07 -07:00
|
|
|
}
|
2010-10-20 18:49:23 -07:00
|
|
|
}
|
2011-04-09 19:44:01 -07:00
|
|
|
}
|