fixed build and added logging

pull/1959/head
TidusJar 7 years ago
parent 1ab8112c68
commit b223306ee8

@ -1,388 +1,388 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Ombi.Api.DogNzb;
using Ombi.Api.DogNzb.Models;
using Ombi.Api.SickRage;
using Ombi.Api.SickRage.Models;
using Ombi.Api.Sonarr;
using Ombi.Api.Sonarr.Models;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities.Requests;
namespace Ombi.Core.Senders
{
public class TvSender : ITvSender
{
public TvSender(ISonarrApi sonarrApi, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
ISettingsService<DogNzbSettings> dog, IDogNzbApi dogApi, ISettingsService<SickRageSettings> srSettings,
ISickRageApi srApi)
{
SonarrApi = sonarrApi;
Logger = log;
SonarrSettings = sonarrSettings;
DogNzbSettings = dog;
DogNzbApi = dogApi;
SickRageSettings = srSettings;
SickRageApi = srApi;
}
private ISonarrApi SonarrApi { get; }
private IDogNzbApi DogNzbApi { get; }
private ISickRageApi SickRageApi { get; }
private ILogger<TvSender> Logger { get; }
private ISettingsService<SonarrSettings> SonarrSettings { get; }
private ISettingsService<DogNzbSettings> DogNzbSettings { get; }
private ISettingsService<SickRageSettings> SickRageSettings { get; }
public async Task<SenderResult> Send(ChildRequests model)
{
var sonarr = await SonarrSettings.GetSettingsAsync();
if (sonarr.Enabled)
{
var result = await SendToSonarr(model);
if (result != null)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
}
var dog = await DogNzbSettings.GetSettingsAsync();
if (dog.Enabled)
{
var result = await SendToDogNzb(model, dog);
if (!result.Failure)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
return new SenderResult
{
Message = result.ErrorMessage
};
}
var sr = await SickRageSettings.GetSettingsAsync();
if (sr.Enabled)
{
var result = await SendToSickRage(model, sr);
if (result)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
return new SenderResult
{
Message = "Could not send to SickRage!"
};
}
return new SenderResult
{
Success = true
};
}
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
{
var id = model.ParentRequest.TvDbId;
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
}
/// <summary>
/// Send the request to Sonarr to process
/// </summary>
/// <param name="s"></param>
/// <param name="model"></param>
/// <param name="qualityId">This is for any qualities overriden from the UI</param>
/// <returns></returns>
public async Task<NewSeries> SendToSonarr(ChildRequests model, string qualityId = null)
{
var s = await SonarrSettings.GetSettingsAsync();
if (!s.Enabled)
{
return null;
}
if (string.IsNullOrEmpty(s.ApiKey))
{
return null;
}
var qualityProfile = 0;
if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
{
int.TryParse(qualityId, out qualityProfile);
}
if (qualityProfile <= 0)
{
int.TryParse(s.QualityProfile, out qualityProfile);
}
// Get the root path from the rootfolder selected.
// For some reason, if we haven't got one use the first root folder in Sonarr
// TODO make this overrideable via the UI
var rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPath), s);
try
{
// Does the series actually exist?
var allSeries = await SonarrApi.GetSeries(s.ApiKey, s.FullUri);
var existingSeries = allSeries.FirstOrDefault(x => x.tvdbId == model.ParentRequest.TvDbId);
if (existingSeries == null)
{
// Time to add a new one
var newSeries = new NewSeries
{
title = model.ParentRequest.Title,
imdbId = model.ParentRequest.ImdbId,
tvdbId = model.ParentRequest.TvDbId,
cleanTitle = model.ParentRequest.Title,
monitored = true,
seasonFolder = s.SeasonFolders,
rootFolderPath = rootFolderPath,
qualityProfileId = qualityProfile,
titleSlug = model.ParentRequest.Title,
addOptions = new AddOptions
{
ignoreEpisodesWithFiles = true, // There shouldn't be any episodes with files, this is a new season
ignoreEpisodesWithoutFiles = true, // We want all missing
searchForMissingEpisodes = false // we want dont want to search yet. We want to make sure everything is unmonitored/monitored correctly.
}
};
// Montitor the correct seasons,
// If we have that season in the model then it's monitored!
var seasonsToAdd = new List<Season>();
for (var i = 1; i < model.ParentRequest.TotalSeasons + 1; i++)
{
var index = i;
var season = new Season
{
seasonNumber = i,
monitored = model.SeasonRequests.Any(x => x.SeasonNumber == index)
};
seasonsToAdd.Add(season);
}
newSeries.seasons = seasonsToAdd;
var result = await SonarrApi.AddSeries(newSeries, s.ApiKey, s.FullUri);
existingSeries = await SonarrApi.GetSeriesById(result.id, s.ApiKey, s.FullUri);
await SendToSonarr(model, existingSeries, s);
}
else
{
await SendToSonarr(model, existingSeries, s);
}
return new NewSeries
{
id = existingSeries.id,
seasons = existingSeries.seasons.ToList(),
cleanTitle = existingSeries.cleanTitle,
title = existingSeries.title,
tvdbId = existingSeries.tvdbId
};
}
catch (Exception e)
{
Logger.LogError(LoggingEvents.SonarrSender, e, "Exception thrown when attempting to send series over to Sonarr");
throw;
}
}
private async Task SendToSonarr(ChildRequests model, SonarrSeries result, SonarrSettings s)
{
var episodesToUpdate = new List<Episode>();
// Ok, now let's sort out the episodes.
if (model.SeriesType == SeriesType.Anime)
{
result.seriesType = "anime";
await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
}
var sonarrEpisodes = await SonarrApi.GetEpisodes(result.id, s.ApiKey, s.FullUri);
var sonarrEpList = sonarrEpisodes.ToList() ?? new List<Episode>();
while (!sonarrEpList.Any())
{
// It could be that the series metadata is not ready yet. So wait
sonarrEpList = (await SonarrApi.GetEpisodes(result.id, s.ApiKey, s.FullUri)).ToList();
await Task.Delay(500);
}
foreach (var req in model.SeasonRequests)
{
foreach (var ep in req.Episodes)
{
var sonarrEp = sonarrEpList.FirstOrDefault(x =>
x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == req.SeasonNumber);
if (sonarrEp != null)
{
sonarrEp.monitored = true;
episodesToUpdate.Add(sonarrEp);
}
}
}
var seriesChanges = false;
foreach (var season in model.SeasonRequests)
{
var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber);
var sonarrEpCount = sonarrSeason.Count();
var ourRequestCount = season.Episodes.Count;
if (sonarrEpCount == ourRequestCount)
{
// We have the same amount of requests as all of the episodes in the season.
var existingSeason =
result.seasons.First(x => x.seasonNumber == season.SeasonNumber);
existingSeason.monitored = true;
seriesChanges = true;
}
else
{
// Now update the episodes that need updating
foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber))
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
}
}
if (seriesChanges)
{
await SonarrApi.SeasonPass(s.ApiKey, s.FullUri, result);
}
if (!s.AddOnly)
{
await SearchForRequest(model, sonarrEpList, result, s, episodesToUpdate);
}
}
private async Task<bool> SendToSickRage(ChildRequests model, SickRageSettings settings, string qualityId = null)
{
var tvdbid = model.ParentRequest.TvDbId;
if (qualityId.HasValue())
{
var id = qualityId;
if (settings.Qualities.All(x => x.Value != id))
{
qualityId = settings.QualityProfile;
}
}
else
{
qualityId = settings.QualityProfile;
}
// Check if the show exists
var existingShow = await SickRageApi.GetShow(tvdbid, settings.ApiKey, settings.FullUri);
if (existingShow.message.Equals("Show not found", StringComparison.CurrentCultureIgnoreCase))
{
var addResult = await SickRageApi.AddSeries(model.ParentRequest.TvDbId, qualityId, SickRageStatus.Ignored,
settings.ApiKey, settings.FullUri);
Logger.LogDebug("Added the show (tvdbid) {0}. The result is '{2}' : '{3}'", tvdbid, addResult.result, addResult.message);
if (addResult.result.Equals("failure") || addResult.result.Equals("fatal"))
{
// Do something
return false;
}
}
foreach (var seasonRequests in model.SeasonRequests)
{
var srEpisodes = await SickRageApi.GetEpisodesForSeason(tvdbid, seasonRequests.SeasonNumber, settings.ApiKey, settings.FullUri);
while (srEpisodes.message.Equals("Show not found", StringComparison.CurrentCultureIgnoreCase) && srEpisodes.data.Count <= 0)
{
await Task.Delay(TimeSpan.FromSeconds(1));
srEpisodes = await SickRageApi.GetEpisodesForSeason(tvdbid, seasonRequests.SeasonNumber, settings.ApiKey, settings.FullUri);
}
var totalSrEpisodes = srEpisodes.data.Count;
if (totalSrEpisodes == seasonRequests.Episodes.Count)
{
// This is a request for the whole season
var wholeSeasonResult = await SickRageApi.SetEpisodeStatus(settings.ApiKey, settings.FullUri, tvdbid, SickRageStatus.Wanted,
seasonRequests.SeasonNumber);
Logger.LogDebug("Set the status to Wanted for season {0}. The result is '{1}' : '{2}'", seasonRequests.SeasonNumber, wholeSeasonResult.result, wholeSeasonResult.message);
continue;
}
foreach (var srEp in srEpisodes.data)
{
var epNumber = srEp.Key;
var epData = srEp.Value;
var epRequest = seasonRequests.Episodes.FirstOrDefault(x => x.EpisodeNumber == epNumber);
if (epRequest != null)
{
// We want to monior this episode since we have a request for it
// Let's check to see if it's wanted first, save an api call
if (epData.status.Equals(SickRageStatus.Wanted, StringComparison.CurrentCultureIgnoreCase))
{
continue;
}
var epResult = await SickRageApi.SetEpisodeStatus(settings.ApiKey, settings.FullUri, tvdbid,
SickRageStatus.Wanted, seasonRequests.SeasonNumber, epNumber);
Logger.LogDebug("Set the status to Wanted for Episode {0} in season {1}. The result is '{2}' : '{3}'", seasonRequests.SeasonNumber, epNumber, epResult.result, epResult.message);
}
}
}
return true;
}
private async Task SearchForRequest(ChildRequests model, IEnumerable<Episode> sonarrEpList, SonarrSeries existingSeries, SonarrSettings s,
IReadOnlyCollection<Episode> episodesToUpdate)
{
foreach (var season in model.SeasonRequests)
{
var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber);
var sonarrEpCount = sonarrSeason.Count();
var ourRequestCount = season.Episodes.Count;
if (sonarrEpCount == ourRequestCount)
{
// We have the same amount of requests as all of the episodes in the season.
// Do a season search
await SonarrApi.SeasonSearch(existingSeries.id, season.SeasonNumber, s.ApiKey, s.FullUri);
}
else
{
// There is a miss-match, let's search the episodes indiviaully
await SonarrApi.EpisodeSearch(episodesToUpdate.Select(x => x.id).ToArray(), s.ApiKey, s.FullUri);
}
}
}
private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings)
{
var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri);
if (pathId == 0)
{
return rootFoldersResult.FirstOrDefault().path;
}
foreach (var r in rootFoldersResult.Where(r => r.id == pathId))
{
return r.path;
}
return string.Empty;
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Ombi.Api.DogNzb;
using Ombi.Api.DogNzb.Models;
using Ombi.Api.SickRage;
using Ombi.Api.SickRage.Models;
using Ombi.Api.Sonarr;
using Ombi.Api.Sonarr.Models;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Settings.Settings.Models.External;
using Ombi.Store.Entities.Requests;
namespace Ombi.Core.Senders
{
public class TvSender : ITvSender
{
public TvSender(ISonarrApi sonarrApi, ILogger<TvSender> log, ISettingsService<SonarrSettings> sonarrSettings,
ISettingsService<DogNzbSettings> dog, IDogNzbApi dogApi, ISettingsService<SickRageSettings> srSettings,
ISickRageApi srApi)
{
SonarrApi = sonarrApi;
Logger = log;
SonarrSettings = sonarrSettings;
DogNzbSettings = dog;
DogNzbApi = dogApi;
SickRageSettings = srSettings;
SickRageApi = srApi;
}
private ISonarrApi SonarrApi { get; }
private IDogNzbApi DogNzbApi { get; }
private ISickRageApi SickRageApi { get; }
private ILogger<TvSender> Logger { get; }
private ISettingsService<SonarrSettings> SonarrSettings { get; }
private ISettingsService<DogNzbSettings> DogNzbSettings { get; }
private ISettingsService<SickRageSettings> SickRageSettings { get; }
public async Task<SenderResult> Send(ChildRequests model)
{
var sonarr = await SonarrSettings.GetSettingsAsync();
if (sonarr.Enabled)
{
var result = await SendToSonarr(model);
if (result != null)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
}
var dog = await DogNzbSettings.GetSettingsAsync();
if (dog.Enabled)
{
var result = await SendToDogNzb(model, dog);
if (!result.Failure)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
return new SenderResult
{
Message = result.ErrorMessage
};
}
var sr = await SickRageSettings.GetSettingsAsync();
if (sr.Enabled)
{
var result = await SendToSickRage(model, sr);
if (result)
{
return new SenderResult
{
Sent = true,
Success = true
};
}
return new SenderResult
{
Message = "Could not send to SickRage!"
};
}
return new SenderResult
{
Success = true
};
}
private async Task<DogNzbAddResult> SendToDogNzb(ChildRequests model, DogNzbSettings settings)
{
var id = model.ParentRequest.TvDbId;
return await DogNzbApi.AddTvShow(settings.ApiKey, id.ToString());
}
/// <summary>
/// Send the request to Sonarr to process
/// </summary>
/// <param name="s"></param>
/// <param name="model"></param>
/// <param name="qualityId">This is for any qualities overriden from the UI</param>
/// <returns></returns>
public async Task<NewSeries> SendToSonarr(ChildRequests model, string qualityId = null)
{
var s = await SonarrSettings.GetSettingsAsync();
if (!s.Enabled)
{
return null;
}
if (string.IsNullOrEmpty(s.ApiKey))
{
return null;
}
var qualityProfile = 0;
if (!string.IsNullOrEmpty(qualityId)) // try to parse the passed in quality, otherwise use the settings default quality
{
int.TryParse(qualityId, out qualityProfile);
}
if (qualityProfile <= 0)
{
int.TryParse(s.QualityProfile, out qualityProfile);
}
// Get the root path from the rootfolder selected.
// For some reason, if we haven't got one use the first root folder in Sonarr
// TODO make this overrideable via the UI
var rootFolderPath = await GetSonarrRootPath(model.ParentRequest.RootFolder ?? int.Parse(s.RootPath), s);
try
{
// Does the series actually exist?
var allSeries = await SonarrApi.GetSeries(s.ApiKey, s.FullUri);
var existingSeries = allSeries.FirstOrDefault(x => x.tvdbId == model.ParentRequest.TvDbId);
if (existingSeries == null)
{
// Time to add a new one
var newSeries = new NewSeries
{
title = model.ParentRequest.Title,
imdbId = model.ParentRequest.ImdbId,
tvdbId = model.ParentRequest.TvDbId,
cleanTitle = model.ParentRequest.Title,
monitored = true,
seasonFolder = s.SeasonFolders,
rootFolderPath = rootFolderPath,
qualityProfileId = qualityProfile,
titleSlug = model.ParentRequest.Title,
addOptions = new AddOptions
{
ignoreEpisodesWithFiles = true, // There shouldn't be any episodes with files, this is a new season
ignoreEpisodesWithoutFiles = true, // We want all missing
searchForMissingEpisodes = false // we want dont want to search yet. We want to make sure everything is unmonitored/monitored correctly.
}
};
// Montitor the correct seasons,
// If we have that season in the model then it's monitored!
var seasonsToAdd = new List<Season>();
for (var i = 1; i < model.ParentRequest.TotalSeasons + 1; i++)
{
var index = i;
var season = new Season
{
seasonNumber = i,
monitored = model.SeasonRequests.Any(x => x.SeasonNumber == index)
};
seasonsToAdd.Add(season);
}
newSeries.seasons = seasonsToAdd;
var result = await SonarrApi.AddSeries(newSeries, s.ApiKey, s.FullUri);
existingSeries = await SonarrApi.GetSeriesById(result.id, s.ApiKey, s.FullUri);
await SendToSonarr(model, existingSeries, s);
}
else
{
await SendToSonarr(model, existingSeries, s);
}
return new NewSeries
{
id = existingSeries.id,
seasons = existingSeries.seasons.ToList(),
cleanTitle = existingSeries.cleanTitle,
title = existingSeries.title,
tvdbId = existingSeries.tvdbId
};
}
catch (Exception e)
{
Logger.LogError(LoggingEvents.SonarrSender, e, "Exception thrown when attempting to send series over to Sonarr");
throw;
}
}
private async Task SendToSonarr(ChildRequests model, SonarrSeries result, SonarrSettings s)
{
var episodesToUpdate = new List<Episode>();
// Ok, now let's sort out the episodes.
if (model.SeriesType == SeriesType.Anime)
{
result.seriesType = "anime";
await SonarrApi.UpdateSeries(result, s.ApiKey, s.FullUri);
}
var sonarrEpisodes = await SonarrApi.GetEpisodes(result.id, s.ApiKey, s.FullUri);
var sonarrEpList = sonarrEpisodes.ToList() ?? new List<Episode>();
while (!sonarrEpList.Any())
{
// It could be that the series metadata is not ready yet. So wait
sonarrEpList = (await SonarrApi.GetEpisodes(result.id, s.ApiKey, s.FullUri)).ToList();
await Task.Delay(500);
}
foreach (var req in model.SeasonRequests)
{
foreach (var ep in req.Episodes)
{
var sonarrEp = sonarrEpList.FirstOrDefault(x =>
x.episodeNumber == ep.EpisodeNumber && x.seasonNumber == req.SeasonNumber);
if (sonarrEp != null)
{
sonarrEp.monitored = true;
episodesToUpdate.Add(sonarrEp);
}
}
}
var seriesChanges = false;
foreach (var season in model.SeasonRequests)
{
var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber);
var sonarrEpCount = sonarrSeason.Count();
var ourRequestCount = season.Episodes.Count;
if (sonarrEpCount == ourRequestCount)
{
// We have the same amount of requests as all of the episodes in the season.
var existingSeason =
result.seasons.First(x => x.seasonNumber == season.SeasonNumber);
existingSeason.monitored = true;
seriesChanges = true;
}
else
{
// Now update the episodes that need updating
foreach (var epToUpdate in episodesToUpdate.Where(x => x.seasonNumber == season.SeasonNumber))
{
await SonarrApi.UpdateEpisode(epToUpdate, s.ApiKey, s.FullUri);
}
}
}
if (seriesChanges)
{
await SonarrApi.SeasonPass(s.ApiKey, s.FullUri, result);
}
if (!s.AddOnly)
{
await SearchForRequest(model, sonarrEpList, result, s, episodesToUpdate);
}
}
private async Task<bool> SendToSickRage(ChildRequests model, SickRageSettings settings, string qualityId = null)
{
var tvdbid = model.ParentRequest.TvDbId;
if (qualityId.HasValue())
{
var id = qualityId;
if (settings.Qualities.All(x => x.Value != id))
{
qualityId = settings.QualityProfile;
}
}
else
{
qualityId = settings.QualityProfile;
}
// Check if the show exists
var existingShow = await SickRageApi.GetShow(tvdbid, settings.ApiKey, settings.FullUri);
if (existingShow.message.Equals("Show not found", StringComparison.CurrentCultureIgnoreCase))
{
var addResult = await SickRageApi.AddSeries(model.ParentRequest.TvDbId, qualityId, SickRageStatus.Ignored,
settings.ApiKey, settings.FullUri);
Logger.LogDebug("Added the show (tvdbid) {0}. The result is '{2}' : '{3}'", tvdbid, addResult.result, addResult.message);
if (addResult.result.Equals("failure") || addResult.result.Equals("fatal"))
{
// Do something
return false;
}
}
foreach (var seasonRequests in model.SeasonRequests)
{
var srEpisodes = await SickRageApi.GetEpisodesForSeason(tvdbid, seasonRequests.SeasonNumber, settings.ApiKey, settings.FullUri);
while (srEpisodes.message.Equals("Show not found", StringComparison.CurrentCultureIgnoreCase) && srEpisodes.data.Count <= 0)
{
await Task.Delay(TimeSpan.FromSeconds(1));
srEpisodes = await SickRageApi.GetEpisodesForSeason(tvdbid, seasonRequests.SeasonNumber, settings.ApiKey, settings.FullUri);
}
var totalSrEpisodes = srEpisodes.data.Count;
if (totalSrEpisodes == seasonRequests.Episodes.Count)
{
// This is a request for the whole season
var wholeSeasonResult = await SickRageApi.SetEpisodeStatus(settings.ApiKey, settings.FullUri, tvdbid, SickRageStatus.Wanted,
seasonRequests.SeasonNumber);
Logger.LogDebug("Set the status to Wanted for season {0}. The result is '{1}' : '{2}'", seasonRequests.SeasonNumber, wholeSeasonResult.result, wholeSeasonResult.message);
continue;
}
foreach (var srEp in srEpisodes.data)
{
var epNumber = srEp.Key;
var epData = srEp.Value;
var epRequest = seasonRequests.Episodes.FirstOrDefault(x => x.EpisodeNumber == epNumber);
if (epRequest != null)
{
// We want to monior this episode since we have a request for it
// Let's check to see if it's wanted first, save an api call
if (epData.status.Equals(SickRageStatus.Wanted, StringComparison.CurrentCultureIgnoreCase))
{
continue;
}
var epResult = await SickRageApi.SetEpisodeStatus(settings.ApiKey, settings.FullUri, tvdbid,
SickRageStatus.Wanted, seasonRequests.SeasonNumber, epNumber);
Logger.LogDebug("Set the status to Wanted for Episode {0} in season {1}. The result is '{2}' : '{3}'", seasonRequests.SeasonNumber, epNumber, epResult.result, epResult.message);
}
}
}
return true;
}
private async Task SearchForRequest(ChildRequests model, IEnumerable<Episode> sonarrEpList, SonarrSeries existingSeries, SonarrSettings s,
IReadOnlyCollection<Episode> episodesToUpdate)
{
foreach (var season in model.SeasonRequests)
{
var sonarrSeason = sonarrEpList.Where(x => x.seasonNumber == season.SeasonNumber);
var sonarrEpCount = sonarrSeason.Count();
var ourRequestCount = season.Episodes.Count;
if (sonarrEpCount == ourRequestCount)
{
// We have the same amount of requests as all of the episodes in the season.
// Do a season search
await SonarrApi.SeasonSearch(existingSeries.id, season.SeasonNumber, s.ApiKey, s.FullUri);
}
else
{
// There is a miss-match, let's search the episodes indiviaully
await SonarrApi.EpisodeSearch(episodesToUpdate.Select(x => x.id).ToArray(), s.ApiKey, s.FullUri);
}
}
}
private async Task<string> GetSonarrRootPath(int pathId, SonarrSettings sonarrSettings)
{
var rootFoldersResult = await SonarrApi.GetRootFolders(sonarrSettings.ApiKey, sonarrSettings.FullUri);
if (pathId == 0)
{
return rootFoldersResult.FirstOrDefault().path;
}
foreach (var r in rootFoldersResult.Where(r => r.id == pathId))
{
return r.path;
}
return string.Empty;
}
}
}

@ -18,7 +18,10 @@ namespace Ombi.Notifications.Agents
{
public class DiscordNotification : BaseNotification<DiscordNotificationSettings>, IDiscordNotification
{
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn, ILogger<DiscordNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s)
public DiscordNotification(IDiscordApi api, ISettingsService<DiscordNotificationSettings> sn,
ILogger<DiscordNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s)
: base(sn, r, m, t,s,log)
{
Api = api;
Logger = log;

@ -19,7 +19,7 @@ namespace Ombi.Notifications.Agents
public class EmailNotification : BaseNotification<EmailNotificationSettings>, IEmailNotification
{
public EmailNotification(ISettingsService<EmailNotificationSettings> settings, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, IEmailProvider prov, ISettingsService<CustomizationSettings> c,
ILogger<EmailNotification> log) : base(settings, r, m, t, c)
ILogger<EmailNotification> log) : base(settings, r, m, t, c,log)
{
EmailProvider = prov;
Logger = log;

@ -21,7 +21,7 @@ namespace Ombi.Notifications.Agents
public class MattermostNotification : BaseNotification<MattermostNotificationSettings>, IMattermostNotification
{
public MattermostNotification(IMattermostApi api, ISettingsService<MattermostNotificationSettings> sn, ILogger<MattermostNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s)
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
{
Api = api;
Logger = log;

@ -22,7 +22,7 @@ namespace Ombi.Notifications.Agents
{
public MobileNotification(IOneSignalApi api, ISettingsService<MobileNotificationSettings> sn, ILogger<MobileNotification> log, INotificationTemplatesRepository r,
IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s, IRepository<NotificationUserId> notification,
UserManager<OmbiUser> um) : base(sn, r, m, t, s)
UserManager<OmbiUser> um) : base(sn, r, m, t, s,log)
{
_api = api;
_logger = log;

@ -17,7 +17,7 @@ namespace Ombi.Notifications.Agents
public class PushbulletNotification : BaseNotification<PushbulletSettings>, IPushbulletNotification
{
public PushbulletNotification(IPushbulletApi api, ISettingsService<PushbulletSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s)
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
{
Api = api;
Logger = log;

@ -17,8 +17,8 @@ namespace Ombi.Notifications.Agents
{
public class PushoverNotification : BaseNotification<PushoverSettings>, IPushoverNotification
{
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushbulletNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s)
public PushoverNotification(IPushoverApi api, ISettingsService<PushoverSettings> sn, ILogger<PushoverNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s, log)
{
Api = api;
Logger = log;
@ -27,7 +27,7 @@ namespace Ombi.Notifications.Agents
public override string NotificationName => "PushoverNotification";
private IPushoverApi Api { get; }
private ILogger<PushbulletNotification> Logger { get; }
private ILogger<PushoverNotification> Logger { get; }
protected override bool ValidateConfiguration(PushoverSettings settings)
{

@ -18,7 +18,7 @@ namespace Ombi.Notifications.Agents
public class SlackNotification : BaseNotification<SlackNotificationSettings>, ISlackNotification
{
public SlackNotification(ISlackApi api, ISettingsService<SlackNotificationSettings> sn, ILogger<SlackNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t,
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s)
ISettingsService<CustomizationSettings> s) : base(sn, r, m, t, s, log)
{
Api = api;
Logger = log;

@ -16,7 +16,9 @@ namespace Ombi.Notifications.Agents
{
public class TelegramNotification : BaseNotification<TelegramSettings>, ITelegramNotification
{
public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log, INotificationTemplatesRepository r, IMovieRequestRepository m, ITvRequestRepository t, ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s)
public TelegramNotification(ITelegramApi api, ISettingsService<TelegramSettings> sn, ILogger<TelegramNotification> log,
INotificationTemplatesRepository r, IMovieRequestRepository m,
ITvRequestRepository t, ISettingsService<CustomizationSettings> s) : base(sn, r, m, t,s,log)
{
Api = api;
Logger = log;

@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Ombi.Core.Settings;
using Ombi.Helpers;
using Ombi.Notifications.Exceptions;
@ -16,7 +17,7 @@ namespace Ombi.Notifications.Interfaces
public abstract class BaseNotification<T> : INotification where T : Settings.Settings.Models.Settings, new()
{
protected BaseNotification(ISettingsService<T> settings, INotificationTemplatesRepository templateRepo, IMovieRequestRepository movie, ITvRequestRepository tv,
ISettingsService<CustomizationSettings> customization)
ISettingsService<CustomizationSettings> customization, ILogger<BaseNotification<T>> log)
{
Settings = settings;
TemplateRepository = templateRepo;
@ -25,6 +26,7 @@ namespace Ombi.Notifications.Interfaces
CustomizationSettings = customization;
Settings.ClearCache();
CustomizationSettings.ClearCache();
_log = log;
}
protected ISettingsService<T> Settings { get; }
@ -33,6 +35,7 @@ namespace Ombi.Notifications.Interfaces
protected ITvRequestRepository TvRepository { get; }
protected CustomizationSettings Customization { get; set; }
private ISettingsService<CustomizationSettings> CustomizationSettings { get; }
private readonly ILogger<BaseNotification<T>> _log;
protected ChildRequests TvRequest { get; set; }
@ -159,10 +162,13 @@ namespace Ombi.Notifications.Interfaces
var curlys = new NotificationMessageCurlys();
if (model.RequestType == RequestType.Movie)
{
_log.LogDebug("Notification options: {@model}, Req: {@MovieRequest}, Settings: {@Customization}", model, MovieRequest, Customization);
curlys.Setup(model, MovieRequest, Customization);
}
else
{
_log.LogDebug("Notification options: {@model}, Req: {@TvRequest}, Settings: {@Customization}", model, TvRequest, Customization);
curlys.Setup(model, TvRequest, Customization);
}
var parsed = resolver.ParseMessage(template, curlys);

@ -11,16 +11,8 @@ namespace Ombi.Notifications
{
public class NotificationMessageCurlys
{
public NotificationMessageCurlys(ILogger<NotificationMessageCurlys> log)
{
_log = log;
}
private readonly ILogger<NotificationMessageCurlys> _log;
public void Setup(NotificationOptions opts, FullBaseRequest req, CustomizationSettings s)
{
_log.LogDebug("Notification options: {@Opts}, Req: {@Req}, Settings: {@S}", opts, req, s);
ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty;
ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName;
RequestedUser = string.IsNullOrEmpty(req.RequestedUser.Alias)
@ -39,8 +31,7 @@ namespace Ombi.Notifications
public void Setup(NotificationOptions opts, ChildRequests req, CustomizationSettings s)
{
_log.LogDebug("Notification options: {@Opts}, Req: {@Req}, Settings: {@S}", opts, req, s);
ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty;
ApplicationUrl = (s?.ApplicationUrl.HasValue() ?? false) ? s.ApplicationUrl : string.Empty;
ApplicationName = string.IsNullOrEmpty(s?.ApplicationName) ? "Ombi" : s?.ApplicationName;
RequestedUser = string.IsNullOrEmpty(req.RequestedUser.Alias)
? req.RequestedUser.UserName

@ -1,167 +1,167 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Notifications;
using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
namespace Ombi.Schedule.Jobs.Plex
{
public class PlexAvailabilityChecker : IPlexAvailabilityChecker
{
public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies,
INotificationService notification, IBackgroundJobClient background)
{
_tvRepo = tvRequest;
_repo = repo;
_movieRepo = movies;
_notificationService = notification;
_backgroundJobClient = background;
}
private readonly ITvRequestRepository _tvRepo;
private readonly IMovieRequestRepository _movieRepo;
private readonly IPlexContentRepository _repo;
private readonly INotificationService _notificationService;
private readonly IBackgroundJobClient _backgroundJobClient;
public async Task Start()
{
await ProcessMovies();
await ProcessTv();
}
private async Task ProcessTv()
{
var tv = _tvRepo.GetChild().Where(x => !x.Available);
var plexEpisodes = _repo.GetAllEpisodes().Include(x => x.Series);
foreach (var child in tv)
{
var useImdb = false;
var useTvDb = false;
if (child.ParentRequest.ImdbId.HasValue())
{
useImdb = true;
}
if (child.ParentRequest.TvDbId.ToString().HasValue())
{
useTvDb = true;
}
var tvDbId = child.ParentRequest.TvDbId;
var imdbId = child.ParentRequest.ImdbId;
IQueryable<PlexEpisode> seriesEpisodes = null;
if (useImdb)
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
}
if (useTvDb)
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString());
}
foreach (var season in child.SeasonRequests)
{
foreach (var episode in season.Episodes)
{
var foundEp = await seriesEpisodes.FirstOrDefaultAsync(
x => x.EpisodeNumber == episode.EpisodeNumber &&
x.SeasonNumber == episode.Season.SeasonNumber);
if (foundEp != null)
{
episode.Available = true;
}
}
}
// Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
if (allAvailable)
{
// We have fulfulled this request!
child.Available = true;
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = child.ParentRequestId,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email
}));
}
}
await _tvRepo.Save();
}
private async Task ProcessMovies()
{
// Get all non available
var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available);
foreach (var movie in movies)
{
PlexServerContent item = null;
if (movie.ImdbId.HasValue())
{
item = await _repo.Get(movie.ImdbId);
}
if (item == null)
{
if (movie.TheMovieDbId.ToString().HasValue())
{
item = await _repo.Get(movie.TheMovieDbId.ToString());
}
}
if (item == null)
{
// We don't yet have this
continue;
}
movie.Available = true;
if (movie.Available)
{
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = movie.Id,
RequestType = RequestType.Movie,
Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty
}));
}
}
await _movieRepo.Save();
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_movieRepo?.Dispose();
_repo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Hangfire;
using Microsoft.EntityFrameworkCore;
using Ombi.Core.Notifications;
using Ombi.Helpers;
using Ombi.Notifications.Models;
using Ombi.Store.Entities;
using Ombi.Store.Repository;
using Ombi.Store.Repository.Requests;
namespace Ombi.Schedule.Jobs.Plex
{
public class PlexAvailabilityChecker : IPlexAvailabilityChecker
{
public PlexAvailabilityChecker(IPlexContentRepository repo, ITvRequestRepository tvRequest, IMovieRequestRepository movies,
INotificationService notification, IBackgroundJobClient background)
{
_tvRepo = tvRequest;
_repo = repo;
_movieRepo = movies;
_notificationService = notification;
_backgroundJobClient = background;
}
private readonly ITvRequestRepository _tvRepo;
private readonly IMovieRequestRepository _movieRepo;
private readonly IPlexContentRepository _repo;
private readonly INotificationService _notificationService;
private readonly IBackgroundJobClient _backgroundJobClient;
public async Task Start()
{
await ProcessMovies();
await ProcessTv();
}
private async Task ProcessTv()
{
var tv = _tvRepo.GetChild().Where(x => !x.Available);
var plexEpisodes = _repo.GetAllEpisodes().Include(x => x.Series);
foreach (var child in tv)
{
var useImdb = false;
var useTvDb = false;
if (child.ParentRequest.ImdbId.HasValue())
{
useImdb = true;
}
if (child.ParentRequest.TvDbId.ToString().HasValue())
{
useTvDb = true;
}
var tvDbId = child.ParentRequest.TvDbId;
var imdbId = child.ParentRequest.ImdbId;
IQueryable<PlexEpisode> seriesEpisodes = null;
if (useImdb)
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.ImdbId == imdbId.ToString());
}
if (useTvDb)
{
seriesEpisodes = plexEpisodes.Where(x => x.Series.TvDbId == tvDbId.ToString());
}
foreach (var season in child.SeasonRequests)
{
foreach (var episode in season.Episodes)
{
var foundEp = await seriesEpisodes.FirstOrDefaultAsync(
x => x.EpisodeNumber == episode.EpisodeNumber &&
x.SeasonNumber == episode.Season.SeasonNumber);
if (foundEp != null)
{
episode.Available = true;
}
}
}
// Check to see if all of the episodes in all seasons are available for this request
var allAvailable = child.SeasonRequests.All(x => x.Episodes.All(c => c.Available));
if (allAvailable)
{
// We have fulfulled this request!
child.Available = true;
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = child.ParentRequestId,
RequestType = RequestType.TvShow,
Recipient = child.RequestedUser.Email
}));
}
}
await _tvRepo.Save();
}
private async Task ProcessMovies()
{
// Get all non available
var movies = _movieRepo.GetAll().Include(x => x.RequestedUser).Where(x => !x.Available);
foreach (var movie in movies)
{
PlexServerContent item = null;
if (movie.ImdbId.HasValue())
{
item = await _repo.Get(movie.ImdbId);
}
if (item == null)
{
if (movie.TheMovieDbId.ToString().HasValue())
{
item = await _repo.Get(movie.TheMovieDbId.ToString());
}
}
if (item == null)
{
// We don't yet have this
continue;
}
movie.Available = true;
if (movie.Available)
{
_backgroundJobClient.Enqueue(() => _notificationService.Publish(new NotificationOptions
{
DateTime = DateTime.Now,
NotificationType = NotificationType.RequestAvailable,
RequestId = movie.Id,
RequestType = RequestType.Movie,
Recipient = movie.RequestedUser != null ? movie.RequestedUser.Email : string.Empty
}));
}
}
await _movieRepo.Save();
}
private bool _disposed;
protected virtual void Dispose(bool disposing)
{
if (_disposed)
return;
if (disposing)
{
_movieRepo?.Dispose();
_repo?.Dispose();
}
_disposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
}
Loading…
Cancel
Save