diff --git a/CustomMetadataDB.Tests/UtilsTests.cs b/CustomMetadataDB.Tests/UtilsTests.cs index 0907c36..60be854 100644 --- a/CustomMetadataDB.Tests/UtilsTests.cs +++ b/CustomMetadataDB.Tests/UtilsTests.cs @@ -66,5 +66,33 @@ public void Test_get_series_id_from_json(string dir, string expected) Assert.Equal(expected, result); } + + [Fact] + public void Test_file_to_info() + { + var path = "/home/media/test/201012 foobar ep24 - ahmed [foo].mkv"; + var item = Utils.FileToInfo(path, new DateTime(2021, 1, 1, 01, 02, 03, DateTimeKind.Utc)); + Assert.Equal(110120203, item.IndexNumber); + Assert.Equal(202010, item.ParentIndexNumber); + Assert.Equal(2020, item.Year); + Assert.Equal("ep24 - ahmed", item.Name); + Assert.Equal($"{item.IndexNumber}", item.ProviderIds[Constants.PLUGIN_EXTERNAL_ID]); + } + + [Fact] + public void Test_ToEpisode() + { + var path = "/home/media/test/201012 foobar ep24 - ahmed [foo].mkv"; + var result = Utils.ToEpisode(Utils.FileToInfo(path, new DateTime(2021, 1, 1, 01, 02, 03, DateTimeKind.Utc))); + + Assert.True(result.HasMetadata); + + var item = result.Item; + + Assert.Equal(110120203, item.IndexNumber); + Assert.Equal(202010, item.ParentIndexNumber); + Assert.Equal("ep24 - ahmed", item.Name); + Assert.Equal($"{item.IndexNumber}", item.ProviderIds[Constants.PLUGIN_EXTERNAL_ID]); + } } } diff --git a/CustomMetadataDB/CustomMetadataDB.csproj b/CustomMetadataDB/CustomMetadataDB.csproj index e947d50..54a609a 100644 --- a/CustomMetadataDB/CustomMetadataDB.csproj +++ b/CustomMetadataDB/CustomMetadataDB.csproj @@ -2,7 +2,7 @@ net6.0 CustomMetadataDB - 0.0.0.2 + 1.0.0.0 $(Version) $(Version) true diff --git a/CustomMetadataDB/ExternalId.cs b/CustomMetadataDB/ExternalId.cs index 9462e86..48342b2 100644 --- a/CustomMetadataDB/ExternalId.cs +++ b/CustomMetadataDB/ExternalId.cs @@ -4,18 +4,30 @@ using CustomMetadataDB.Helpers; using MediaBrowser.Controller.Configuration; -namespace CustomMetadataDB +namespace CustomMetadataDB; + +public class SeriesExternalId : IExternalId { - public class SeriesExternalId : IExternalId + public bool Supports(IHasProviderIds item) => item is Series; + public string Name => Constants.PLUGIN_NAME; + public string Key => Constants.PLUGIN_EXTERNAL_ID; + public string UrlFormatString { get; set; } + + public SeriesExternalId(IServerConfigurationManager config) { - public bool Supports(IHasProviderIds item) => item is Series; - public string Name => Constants.PLUGIN_NAME; - public string Key => Constants.PLUGIN_EXTERNAL_ID; - public string UrlFormatString { get; set; } + UrlFormatString = Utils.GetConfiguration(config).ApiRefUrl; + } +} - public SeriesExternalId(IServerConfigurationManager config) - { - UrlFormatString = Utils.GetConfiguration(config).ApiRefUrl; - } +public class EpisodeExternalId : IExternalId +{ + public bool Supports(IHasProviderIds item) => item is Episode; + public string Name => Constants.PLUGIN_NAME; + public string Key => Constants.PLUGIN_EXTERNAL_ID; + public string UrlFormatString { get; set; } + + public EpisodeExternalId(IServerConfigurationManager config) + { + UrlFormatString = Utils.GetConfiguration(config).ApiRefUrl; } } diff --git a/CustomMetadataDB/Helpers/Constants.cs b/CustomMetadataDB/Helpers/Constants.cs index de2b927..506ec91 100644 --- a/CustomMetadataDB/Helpers/Constants.cs +++ b/CustomMetadataDB/Helpers/Constants.cs @@ -1,4 +1,6 @@ -namespace CustomMetadataDB.Helpers +using System.Text.RegularExpressions; + +namespace CustomMetadataDB.Helpers { public class Constants { @@ -6,5 +8,15 @@ public class Constants public const string PLUGIN_EXTERNAL_ID = "cmdb"; public const string PLUGIN_DESCRIPTION = "Custom metadata agent db."; public const string PLUGIN_GUID = "83b77e24-9fce-4ee0-a794-73fdfa972e66"; + public static readonly Regex[] EPISODE_MATCHERS = { + // YY?YY(-._)MM(-._)DD -? series -? epNumber -? title + new(@"^(?\d{2,4})(\-|\.|_)?(?\d{2})(\-|\.|_)?(?\d{2})\s-?(?.+?)(?\#(\d+)|ep(\d+)|DVD[0-9.-]+|DISC[0-9.-]+|SP[0-9.-]+|Episode\s(\d+)) -?(?.+)", RegexOptions.Compiled | RegexOptions.IgnoreCase), + // YY?YY(-._)MM(-._)DD -? title + new(@"^(?<year>\d{2,4})(\-|\.|_)?(?<month>\d{2})(\-|\.|_)?(?<day>\d{2})\s?-?(?<title>.+)", RegexOptions.Compiled | RegexOptions.IgnoreCase), + // title YY?YY(-._)MM(-._)DD at end of filename. + new(@"(?<title>.+?)(?<year>\d{2,4})(\-|\.|_)?(?<month>\d{2})(\-|\.|_)?(?<day>\d{2})$", RegexOptions.Compiled | RegexOptions.IgnoreCase), + // series - YY?YY(-._)MM(-._)DD -? title + new(@"(?<series>.+?)(?<year>\d{2,4})(\-|\.|_)?(?<month>\d{2})(\-|\.|_)?(?<day>\d{2})\s?-?(?<title>.+)?", RegexOptions.Compiled | RegexOptions.IgnoreCase) + }; } } diff --git a/CustomMetadataDB/Helpers/Utils.cs b/CustomMetadataDB/Helpers/Utils.cs index 1a9a269..6656ed7 100644 --- a/CustomMetadataDB/Helpers/Utils.cs +++ b/CustomMetadataDB/Helpers/Utils.cs @@ -10,6 +10,7 @@ using System.Text.Json.Serialization; using System; using CustomMetadataDB.Helpers.Configuration; +using System.Text.RegularExpressions; namespace CustomMetadataDB.Helpers { @@ -36,6 +37,7 @@ public static PersonInfo CreatePerson(string name, string provider_id) ProviderIds = new ProviderIdDictionary(new Dictionary<string, string> { { Constants.PLUGIN_EXTERNAL_ID, provider_id } }), }; } + public static MetadataResult<Series> ToSeries(DTO data) { Logger?.Info($"Processing {data}."); @@ -90,13 +92,143 @@ public static MetadataResult<Series> ToSeries(DTO data) Item = item }; } - private static MetadataResult<Series> ErrorOut() + + public static EpisodeInfo FileToInfo(string file, DateTime? file_date = null) { - return new MetadataResult<Series> + + //-- get only the file stem + string filename = System.IO.Path.GetFileNameWithoutExtension(file); + + Match matcher = null; + + for (int i = 0; i < Constants.EPISODE_MATCHERS.Length; i++) { - HasMetadata = true, - Item = new Series() + matcher = Constants.EPISODE_MATCHERS[i].Match(filename); + if (!matcher.Success) + { + continue; + } + break; + } + + if (!matcher.Success) + { + Logger?.Info($"No match found for {file}."); + return new EpisodeInfo(); + } + + string series = matcher.Groups["series"].Success ? matcher.Groups["series"].Value : ""; + string year = matcher.Groups["year"].Success ? matcher.Groups["year"].Value : ""; + year = (year.Length == 2) ? "20" + year : year; + string month = matcher.Groups["month"].Success ? matcher.Groups["month"].Value : ""; + string day = matcher.Groups["day"].Success ? matcher.Groups["day"].Value : ""; + string episode = matcher.Groups["episode"].Success ? matcher.Groups["episode"].Value : ""; + + string season = matcher.Groups["season"].Success ? matcher.Groups["season"].Value : ""; + season = season == "" ? year + month : season; + + string broadcastDate = (year != "" && month != "" && day != "") ? year + "-" + month + "-" + day : ""; + if (broadcastDate == "" && file_date != null) + { + broadcastDate = file_date?.ToString("yyyy-MM-dd") ?? ""; + } + + string title = matcher.Groups["title"].Success ? matcher.Groups["title"].Value : ""; + if (title != "") + { + if (!string.IsNullOrEmpty(series) && title != series && title.ToLower().Contains(series.ToLower())) + { + title = title.Replace(series, "", StringComparison.OrdinalIgnoreCase).Trim(); + } + + if (title == "" && title == series && broadcastDate != "") + { + title = broadcastDate; + } + + // -- replace double spaces with single space + title = Regex.Replace(title, @"\[.+?\]", " ").Trim('-').Trim(); + title = Regex.Replace(title, @"\s+", " "); + title = title.Trim().Trim('-').Trim(); + + if (matcher.Groups["epNumber"].Success) + { + title = matcher.Groups["epNumber"].Value + " - " + title; + } + else if (title != "" && broadcastDate != "" && broadcastDate != title) + { + title = $"{broadcastDate.Replace("-", "")} ~ {title}"; + } + } + + if (episode == "") + { + episode = "1" + month + day; + + // get the modified date of the file + if (System.IO.File.Exists(file) || file_date != null) + { + episode += (file_date ?? System.IO.File.GetLastWriteTimeUtc(file)).ToString("mmss"); + } + } + + episode = (episode == "") ? int.Parse('1' + month + day).ToString() : episode; + + EpisodeInfo item = new() + { + IndexNumber = int.Parse(episode), + Name = title, + Year = int.Parse(year), + ParentIndexNumber = int.Parse(season) + }; + + item.SetProviderId(Constants.PLUGIN_EXTERNAL_ID, item.IndexNumber.ToString()); + + // -- Set the PremiereDate if we have a year, month and day + if (year != "" && month != "" && day != "") + { + item.PremiereDate = new DateTime(int.Parse(year), int.Parse(month), int.Parse(day)); + } + + return item; + } + + public static MetadataResult<Episode> ToEpisode(EpisodeInfo data) + { + if (data.Name == "") + { + Logger?.Warn($"No metadata found for '{data}'."); + return ErrorOutEpisode(); + } + + Logger?.Debug($"Processing {data}."); + + Episode item = new() + { + Name = data.Name, + IndexNumber = data.IndexNumber, + ParentIndexNumber = data.ParentIndexNumber, }; + + if (data.PremiereDate is DateTimeOffset time) + { + item.PremiereDate = time; + item.ProductionYear = time.Year; + } + + item.SetProviderId(Constants.PLUGIN_EXTERNAL_ID, data.ProviderIds[Constants.PLUGIN_EXTERNAL_ID]); + + return new MetadataResult<Episode> { HasMetadata = true, Item = item }; + } + + private static MetadataResult<Series> ErrorOut() + { + return new MetadataResult<Series> { HasMetadata = false, Item = new Series() }; + } + + private static MetadataResult<Episode> ErrorOutEpisode() + { + return new MetadataResult<Episode> { HasMetadata = false, Item = new Episode() }; } } } diff --git a/CustomMetadataDB/Provider/AbstractProvider.cs b/CustomMetadataDB/Provider/AbstractProvider.cs deleted file mode 100644 index df0b2fa..0000000 --- a/CustomMetadataDB/Provider/AbstractProvider.cs +++ /dev/null @@ -1,113 +0,0 @@ -using CustomMetadataDB.Helpers; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.IO; -using MediaBrowser.Model.Providers; -using System; -using System.Collections.Generic; -using System.Threading; -using System.Threading.Tasks; -using System.Web; -using MediaBrowser.Model.Logging; -using MediaBrowser.Common.Net; -using System.Net; -using System.Text.Json; -using MediaBrowser.Model.Entities; -using System.Net.Http; - -namespace CustomMetadataDB -{ - public abstract class AbstractProvider<B, T, E> : IRemoteMetadataProvider<T, E> - where T : BaseItem, IHasLookupInfo<E> - where E : ItemLookupInfo, new() - { - protected readonly IServerConfigurationManager _config; - protected readonly IHttpClient _httpClient; - protected readonly ILogger _logger; - protected readonly IFileSystem _fileSystem; - - public AbstractProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, ILogger logger) - { - _config = config; - _logger = logger; - Utils.Logger = logger; - _fileSystem = fileSystem; - _httpClient = httpClient; - } - - public virtual string Name { get; } = Constants.PLUGIN_NAME; - - public virtual Task<MetadataResult<T>> GetMetadata(E info, CancellationToken cancellationToken) - { - _logger.Debug($"CMD GetMetadata: {info.Name}"); - - return GetMetadataImpl(info, cancellationToken); - } - - internal abstract Task<MetadataResult<T>> GetMetadataImpl(E data, CancellationToken cancellationToken); - - protected Task<HttpResponseInfo> QueryAPI(string type, string name, CancellationToken cancellationToken, int limit = 1) - { - var apiUrl = Utils.GetConfiguration(_config).ApiUrl; - - apiUrl += string.IsNullOrEmpty(new Uri(apiUrl).Query) ? "?" : "&"; - apiUrl += $"type={type}&limit={limit}&&query={HttpUtility.UrlEncode(name)}"; - - return _httpClient.SendAsync(new MediaBrowser.Common.Net.HttpRequestOptions - { - Url = apiUrl, - BufferContent = false, - CancellationToken = cancellationToken, - }, "GET"); - } - public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(E searchInfo, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - _logger.Debug($"CMD Series GetMetadata: {searchInfo.Name}"); - - var result = new List<RemoteSearchResult>(); - - try - { - using var httpResponse = await QueryAPI("series", searchInfo.Name, cancellationToken, limit: 20).ConfigureAwait(false); - - if (httpResponse.StatusCode != HttpStatusCode.OK) - { - _logger.Info($"CMD Series GetMetadata: {searchInfo.Name} - Status Code: {httpResponse.StatusCode}"); - return result; - } - - DTO[] seriesRootObject = await JsonSerializer.DeserializeAsync<DTO[]>( - utf8Json: httpResponse.Content, - options: Utils.JSON_OPTS, - cancellationToken: cancellationToken - ).ConfigureAwait(false); - - - foreach (var series in seriesRootObject) - { - result.Add(new RemoteSearchResult - { - Name = series.Title, - ProviderIds = new ProviderIdDictionary(new Dictionary<string, string> { { Constants.PLUGIN_EXTERNAL_ID, series.Id } }), - }); - } - - _logger.Debug($"CMD Series GetMetadata Result: {result}"); - return result; - } - catch (HttpRequestException exception) - { - if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) - { - return result; - } - - throw; - } - } - public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) => throw new NotImplementedException(); - } -} diff --git a/CustomMetadataDB/Provider/EpisodeProvider.cs b/CustomMetadataDB/Provider/EpisodeProvider.cs new file mode 100644 index 0000000..fc64368 --- /dev/null +++ b/CustomMetadataDB/Provider/EpisodeProvider.cs @@ -0,0 +1,56 @@ +using System; +using System.Threading; +using System.Threading.Tasks; +using CustomMetadataDB.Helpers; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.Configuration; +using MediaBrowser.Model.Logging; +using MediaBrowser.Model.IO; + +namespace CustomMetadataDB; + +public class EpisodeProvider : ILocalMetadataProvider<Episode>, IHasItemChangeMonitor +{ + protected readonly ILogger _logger; + + public string Name => Constants.PLUGIN_NAME; + + public EpisodeProvider(ILogger logger) + { + _logger = logger; + } + + public Task<MetadataResult<Episode>> GetMetadata(ItemInfo info, LibraryOptions libraryOptions, IDirectoryService directoryService, CancellationToken cancellationToken) + { + var result = new MetadataResult<Episode>(); + + cancellationToken.ThrowIfCancellationRequested(); + + _logger.Debug($"CMD Episode GetMetadata Lookup: '{info.Name}' '({info.Path})'"); + + var item = Utils.FileToInfo(info.Path); + + if (string.IsNullOrEmpty(item.Name)) + { + _logger.Warn($"CMD Episode GetMetadata: No metadata found for '{info.Path}'."); + return Task.FromResult(result); + } + + return Task.FromResult(Utils.ToEpisode(item)); + } + + public bool HasChanged(BaseItem item, LibraryOptions libraryOptions, IDirectoryService directoryService) + { + _logger.Debug($"CMD HasChanged: Checking {item.Path}"); + + FileSystemMetadata fileInfo = directoryService.GetFile(item.Path); + bool result = fileInfo.Exists && fileInfo.LastWriteTimeUtc.ToUniversalTime() > item.DateLastSaved.ToUniversalTime(); + string status = result ? "Has Changed" : "Has Not Changed"; + + _logger.Debug($"CMD HasChanged Result: {status}"); + + return result; + } +} diff --git a/CustomMetadataDB/Provider/SeriesProvider.cs b/CustomMetadataDB/Provider/SeriesProvider.cs deleted file mode 100644 index 8f9f8d5..0000000 --- a/CustomMetadataDB/Provider/SeriesProvider.cs +++ /dev/null @@ -1,57 +0,0 @@ -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Providers; -using MediaBrowser.Model.IO; -using CustomMetadataDB.Helpers; -using MediaBrowser.Controller.Configuration; -using System.Net; -using System.Net.Http; -using System.Threading; -using System.Threading.Tasks; -using System.Text.Json; -using MediaBrowser.Model.Logging; -using MediaBrowser.Common.Net; - -namespace CustomMetadataDB -{ - public class SeriesProvider : AbstractProvider<SeriesProvider, Series, SeriesInfo> - { - public SeriesProvider(IServerConfigurationManager config, IHttpClient httpClient, IFileSystem fileSystem, ILogger logger) : - base(config, httpClient, fileSystem, logger) - { } - internal override async Task<MetadataResult<Series>> GetMetadataImpl(SeriesInfo info, CancellationToken cancellationToken) - { - cancellationToken.ThrowIfCancellationRequested(); - - MetadataResult<Series> result = new(); - _logger.Debug($"CMD Series GetMetadata: {info.Name}"); - - try - { - using var httpResponse = await QueryAPI("series", info.Name, cancellationToken).ConfigureAwait(false); - - if (httpResponse.StatusCode != HttpStatusCode.OK) - { - _logger.Info($"CMD Series GetMetadata: {info.Name} - Status Code: {httpResponse.StatusCode}"); - return result; - } - - DTO[] seriesRootObject = await JsonSerializer.DeserializeAsync<DTO[]>( - utf8Json: httpResponse.Content, - options: Utils.JSON_OPTS, - cancellationToken: cancellationToken - ).ConfigureAwait(false); - - _logger.Debug($"CMD Series GetMetadata Result: {seriesRootObject}"); - return Utils.ToSeries(seriesRootObject[0]); - } - catch (HttpRequestException exception) - { - if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) - { - return result; - } - throw; - } - } - } -} diff --git a/CustomMetadataDB/Provider/SeriesProviders.cs b/CustomMetadataDB/Provider/SeriesProviders.cs new file mode 100644 index 0000000..3f87317 --- /dev/null +++ b/CustomMetadataDB/Provider/SeriesProviders.cs @@ -0,0 +1,143 @@ +using CustomMetadataDB.Helpers; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Providers; +using MediaBrowser.Model.IO; +using MediaBrowser.Model.Providers; +using System; +using System.Collections.Generic; +using System.Threading; +using System.Threading.Tasks; +using System.Web; +using MediaBrowser.Model.Logging; +using MediaBrowser.Common.Net; +using System.Net; +using System.Text.Json; +using MediaBrowser.Model.Entities; +using System.Net.Http; + +namespace CustomMetadataDB; + +public class SeriesProvider : IRemoteMetadataProvider<Series, SeriesInfo> +{ + protected readonly IServerConfigurationManager _config; + protected readonly IHttpClient _httpClient; + protected readonly ILogger _logger; + + public SeriesProvider(IServerConfigurationManager config, IHttpClient httpClient, ILogger logger) + { + _config = config; + _logger = logger; + Utils.Logger = logger; + _httpClient = httpClient; + } + + public string Name => Constants.PLUGIN_NAME; + + public virtual Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken) + { + _logger.Debug($"CMD GetMetadata: {info.Name}"); + + return GetMetadataImpl(info, cancellationToken); + } + + internal async Task<MetadataResult<Series>> GetMetadataImpl(SeriesInfo info, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + MetadataResult<Series> result = new(); + _logger.Debug($"CMD Series GetMetadata: {info.Name}"); + + try + { + using var httpResponse = await QueryAPI("series", info.Name, cancellationToken).ConfigureAwait(false); + + if (httpResponse.StatusCode != HttpStatusCode.OK) + { + _logger.Info($"CMD Series GetMetadata: {info.Name} - Status Code: {httpResponse.StatusCode}"); + return result; + } + + DTO[] seriesRootObject = await JsonSerializer.DeserializeAsync<DTO[]>( + utf8Json: httpResponse.Content, + options: Utils.JSON_OPTS, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + _logger.Debug($"CMD Series GetMetadata Result: {seriesRootObject}"); + return Utils.ToSeries(seriesRootObject[0]); + } + catch (HttpRequestException exception) + { + if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) + { + return result; + } + throw; + } + } + + protected Task<HttpResponseInfo> QueryAPI(string type, string name, CancellationToken cancellationToken, int limit = 1) + { + var apiUrl = Utils.GetConfiguration(_config).ApiUrl; + + apiUrl += string.IsNullOrEmpty(new Uri(apiUrl).Query) ? "?" : "&"; + apiUrl += $"type={type}&limit={limit}&&query={HttpUtility.UrlEncode(name)}"; + + return _httpClient.SendAsync(new MediaBrowser.Common.Net.HttpRequestOptions + { + Url = apiUrl, + BufferContent = false, + CancellationToken = cancellationToken, + }, "GET"); + } + + public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken) + { + cancellationToken.ThrowIfCancellationRequested(); + + _logger.Debug($"CMD Series GetMetadata: {searchInfo.Name}"); + + var result = new List<RemoteSearchResult>(); + + try + { + using var httpResponse = await QueryAPI("series", searchInfo.Name, cancellationToken, limit: 20).ConfigureAwait(false); + + if (httpResponse.StatusCode != HttpStatusCode.OK) + { + _logger.Info($"CMD Series GetMetadata: {searchInfo.Name} - Status Code: {httpResponse.StatusCode}"); + return result; + } + + DTO[] seriesRootObject = await JsonSerializer.DeserializeAsync<DTO[]>( + utf8Json: httpResponse.Content, + options: Utils.JSON_OPTS, + cancellationToken: cancellationToken + ).ConfigureAwait(false); + + + foreach (var series in seriesRootObject) + { + result.Add(new RemoteSearchResult + { + Name = series.Title, + ProviderIds = new ProviderIdDictionary(new Dictionary<string, string> { { Constants.PLUGIN_EXTERNAL_ID, series.Id } }), + }); + } + + _logger.Debug($"CMD Series GetMetadata Result: {result}"); + return result; + } + catch (HttpRequestException exception) + { + if (exception.StatusCode.HasValue && exception.StatusCode.Value == HttpStatusCode.NotFound) + { + return result; + } + + throw; + } + } + public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken) => throw new NotImplementedException(); +} diff --git a/build.yaml b/build.yaml index 156eac6..869c4aa 100644 --- a/build.yaml +++ b/build.yaml @@ -1,7 +1,7 @@ --- name: "Custom metadata agent db" guid: "83b77e24-9fce-4ee0-a794-73fdfa972e66" -version: "0.0.0.2" +version: "1.0.0.0" targetAbi: "10.7.0.0" owner: "arabcoders" overview: "A Custom metadata agent."