diff --git a/MangaReader.Core/Account/CookieClient.cs b/MangaReader.Core/Account/CookieClient.cs index b6135e52..80b6bad9 100644 --- a/MangaReader.Core/Account/CookieClient.cs +++ b/MangaReader.Core/Account/CookieClient.cs @@ -1,6 +1,7 @@ using System; using System.Net; using System.Text; +using MangaReader.Core.Services; namespace MangaReader.Core.Account { @@ -33,16 +34,10 @@ protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult r return baseResponce; } - public CookieClient() : this(new CookieContainer()) - { - - } - - public CookieClient(CookieContainer cookie) + protected CookieClient() { + this.Cookie = new CookieContainer(); this.Encoding = Encoding.UTF8; - this.Proxy = SystemProxySetting.SystemProxy.Value; - this.Cookie = cookie; Headers[HttpRequestHeader.UserAgent] = "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0) Gecko/20100101 Firefox/57.0"; } } diff --git a/MangaReader.Core/Account/IProxySetting.cs b/MangaReader.Core/Account/IProxySetting.cs deleted file mode 100644 index d90bf38d..00000000 --- a/MangaReader.Core/Account/IProxySetting.cs +++ /dev/null @@ -1,9 +0,0 @@ -using System.Net; - -namespace MangaReader.Core.Account -{ - public interface IProxySetting - { - IWebProxy GetProxy(); - } -} diff --git a/MangaReader.Core/Account/Login.cs b/MangaReader.Core/Account/Login.cs index 97d97af3..60771462 100644 --- a/MangaReader.Core/Account/Login.cs +++ b/MangaReader.Core/Account/Login.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using MangaReader.Core.Manga; using MangaReader.Core.Services; +using MangaReader.Core.Services.Config; namespace MangaReader.Core.Account { @@ -39,10 +40,7 @@ public bool IsLogined /// protected internal CookieContainer ClientCookie { get; set; } - protected internal CookieClient GetClient() - { - return new CookieClient(this.ClientCookie) { BaseAddress = MainUri.ToString() }; - } + protected internal abstract CookieClient GetClient(); private bool isLogined; diff --git a/MangaReader.Core/Account/ProxySetting.cs b/MangaReader.Core/Account/ProxySetting.cs index eefa6956..6d81078a 100644 --- a/MangaReader.Core/Account/ProxySetting.cs +++ b/MangaReader.Core/Account/ProxySetting.cs @@ -3,8 +3,15 @@ namespace MangaReader.Core.Account { - public class ProxySetting : Entity.Entity, IProxySetting + public class ProxySetting : Entity.Entity { + internal static readonly Lazy SystemProxy = new Lazy(() => + { + var proxy = WebRequest.GetSystemWebProxy(); + proxy.Credentials = CredentialCache.DefaultCredentials; + return proxy; + }); + public string Name { get; set; } public Uri Address { get; set; } @@ -13,10 +20,38 @@ public class ProxySetting : Entity.Entity, IProxySetting public string Password { get; set; } + public ProxySettingType SettingType { get; set; } + public virtual IWebProxy GetProxy() { - var proxy = new WebProxy(Address, true, null, new NetworkCredential(UserName, Password)); - return proxy; + switch (SettingType) + { + case ProxySettingType.NoProxy: + return null; + case ProxySettingType.System: + return SystemProxy.Value; + case ProxySettingType.Manual: + return new WebProxy(Address, true, null, new NetworkCredential(UserName, Password)); + default: + throw new ArgumentOutOfRangeException(); + } + } + + protected ProxySetting() + { + this.SettingType = ProxySettingType.NoProxy; + } + + public ProxySetting(ProxySettingType settingType) + { + this.SettingType = settingType; } } + + public enum ProxySettingType + { + NoProxy, + System, + Manual + } } diff --git a/MangaReader.Core/Account/SystemProxySetting.cs b/MangaReader.Core/Account/SystemProxySetting.cs deleted file mode 100644 index a713b6ba..00000000 --- a/MangaReader.Core/Account/SystemProxySetting.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System; -using System.Net; - -namespace MangaReader.Core.Account -{ - public class SystemProxySetting : IProxySetting - { - internal static readonly Lazy SystemProxy = new Lazy(() => - { - var proxy = WebRequest.GetSystemWebProxy(); - proxy.Credentials = CredentialCache.DefaultCredentials; - return proxy; - }); - - public IWebProxy GetProxy() - { - return SystemProxy.Value; - } - } -} \ No newline at end of file diff --git a/MangaReader.Core/BaseSiteParser.cs b/MangaReader.Core/BaseSiteParser.cs index 57adac0f..f4cf1539 100644 --- a/MangaReader.Core/BaseSiteParser.cs +++ b/MangaReader.Core/BaseSiteParser.cs @@ -110,17 +110,18 @@ protected void FillMangaPages(IManga manga, ICollection pages) public virtual IAsyncEnumerable Search(string name) { - var client = new CookieClient(); var hosts = ConfigStorage.Plugins .Where(p => p.GetParser().GetType() == this.GetType()) .Select(p => p.GetSettings().MainUri); - return hosts.SelectAsync(async host => await GetMangaNodes(name, host, client).ConfigureAwait(false)) - .Where(nc => nc != null && nc.Item1 != null) - .SelectMany(n => n.Item1.SelectAsync(node => GetMangaFromNode(n.Item2, client, node))) + return hosts.SelectAsync(async host => await GetMangaNodes(name, host).ConfigureAwait(false)) + .Where(nc => nc.Nodes != null) + .SelectMany(n => n.Nodes.SelectAsync(node => GetMangaFromNode(n.Uri, n.CookieClient, node))) .Where(m => m != null); } - protected abstract Task> GetMangaNodes(string name, Uri host, CookieClient client); + public abstract CookieClient GetClient(); + + protected abstract Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host); protected abstract Task GetMangaFromNode(Uri host, CookieClient client, HtmlNode manga); @@ -142,4 +143,4 @@ public virtual IMapper GetMapper() }); } } -} \ No newline at end of file +} diff --git a/MangaReader.Core/Convertation/Config/From47To48.cs b/MangaReader.Core/Convertation/Config/From47To48.cs new file mode 100644 index 00000000..089fa71f --- /dev/null +++ b/MangaReader.Core/Convertation/Config/From47To48.cs @@ -0,0 +1,37 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using MangaReader.Core.Account; +using MangaReader.Core.Convertation.Primitives; +using MangaReader.Core.NHibernate; +using MangaReader.Core.Services; + +namespace MangaReader.Core.Convertation.Config +{ + public class From47To48 : ConfigConverter + { + protected override async Task ProtectedConvert(IProcess process) + { + using (var context = Repository.GetEntityContext()) + { + var proxySetting = await context + .Get() + .Where(s => s.SettingType == ProxySettingType.System) + .SingleAsync().ConfigureAwait(false); + var settings = await context.Get().Where(s => s.ProxySetting == null).ToListAsync().ConfigureAwait(false); + foreach (var setting in settings) + { + setting.ProxySetting = proxySetting; + } + + await settings.SaveAll(context).ConfigureAwait(false); + } + } + + public From47To48() + { + this.Name = "Поддержка прокси"; + this.Version = new Version(1, 48, 0); + } + } +} diff --git a/MangaReader.Core/Convertation/Primitives/BaseConverter.cs b/MangaReader.Core/Convertation/Primitives/BaseConverter.cs index 7e516207..3bf30718 100644 --- a/MangaReader.Core/Convertation/Primitives/BaseConverter.cs +++ b/MangaReader.Core/Convertation/Primitives/BaseConverter.cs @@ -25,9 +25,9 @@ public async Task Convert(IProcess process) { if (this.CanConvert(process)) { - Log.AddFormat("Converter '{0}{1}' started", this.Name, this.Version); + Log.AddFormat("Converter '{0} {1}' started", this.Name, this.Version); await this.ProtectedConvert(process).ConfigureAwait(false); - Log.AddFormat("Converter '{0}{1}' completed", this.Name, this.Version); + Log.AddFormat("Converter '{0} {1}' completed", this.Name, this.Version); } } diff --git a/MangaReader.Core/ISiteParser.cs b/MangaReader.Core/ISiteParser.cs index 4229f18d..35e74155 100644 --- a/MangaReader.Core/ISiteParser.cs +++ b/MangaReader.Core/ISiteParser.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using System.Threading.Tasks; +using MangaReader.Core.Account; using MangaReader.Core.Manga; namespace MangaReader.Core @@ -50,6 +51,12 @@ public interface ISiteParser /// Название манги. /// Найденная манга. IAsyncEnumerable Search(string name); + + /// + /// Клиент для работы с сайтом. + /// + /// + CookieClient GetClient(); } public class UriParseResult @@ -75,4 +82,4 @@ public enum UriParseKind Chapter = 2, Page = 3 } -} \ No newline at end of file +} diff --git a/MangaReader.Core/Manga/Mangas.cs b/MangaReader.Core/Manga/Mangas.cs index a3e47b2a..bf16da0c 100644 --- a/MangaReader.Core/Manga/Mangas.cs +++ b/MangaReader.Core/Manga/Mangas.cs @@ -490,7 +490,7 @@ public override async Task BeforeSave(ChangeTrackerArgs args) debugMessage += $" uri changed from '{uriState.OldValue}' to '{uriState.Value}'"; using (Repository.GetEntityContext("Manga uri changed")) { - var settings = ConfigStorage.Plugins.Where(p => p.GetParser().GetType() == Parser.GetType()).Select(p => p.GetSettings()); + var settings = ConfigStorage.Plugins.Where(p => p.LoginType == this.Setting.Login.GetType()).Select(p => p.GetSettings()); var allowedUris = settings.Select(s => s.MainUri).ToList(); if (allowedUris.Any(s => s.Host == uriState.OldValue.Host) && allowedUris.All(s => s.Host != uriState.Value.Host)) diff --git a/MangaReader.Core/NHibernate/MangaSettingMap.cs b/MangaReader.Core/NHibernate/MangaSettingMap.cs index bffc8e67..031d5570 100644 --- a/MangaReader.Core/NHibernate/MangaSettingMap.cs +++ b/MangaReader.Core/NHibernate/MangaSettingMap.cs @@ -18,6 +18,7 @@ public MangaSettingMap() Map(x => x.MainUri); Map(x => x.FolderNamingStrategy); References(x => x.Login).Cascade.All().NotFound.Ignore(); + References(x => x.ProxySetting); } } } diff --git a/MangaReader.Core/NHibernate/ProxySettingMap.cs b/MangaReader.Core/NHibernate/ProxySettingMap.cs new file mode 100644 index 00000000..0279c4a4 --- /dev/null +++ b/MangaReader.Core/NHibernate/ProxySettingMap.cs @@ -0,0 +1,19 @@ +using FluentNHibernate.Mapping; +using MangaReader.Core.Account; + +namespace MangaReader.Core.NHibernate +{ + public class ProxySettingMap : ClassMap + { + public ProxySettingMap() + { + Not.LazyLoad(); + Id(x => x.Id); + Map(x => x.Name); + Map(x => x.UserName); + Map(x => x.Password); + Map(x => x.SettingType); + Map(x => x.Address); + } + } +} diff --git a/MangaReader.Core/Services/CallContext.cs b/MangaReader.Core/Services/CallContext.cs new file mode 100644 index 00000000..c1dba3ee --- /dev/null +++ b/MangaReader.Core/Services/CallContext.cs @@ -0,0 +1,25 @@ +using System.Collections.Concurrent; +using System.Threading; + +namespace MangaReader.Core.Services +{ + public static class CallContext + { + private static readonly ConcurrentDictionary> State = new ConcurrentDictionary>(); + + public static void SetData(string name, T data) + { + State.AddOrUpdate(name, new AsyncLocal(), (_, __) => new AsyncLocal()).Value = data; + } + + public static T GetData(string name) + { + return State.TryGetValue(name, out AsyncLocal data) ? data.Value : default(T); + } + + public static bool RemoveData(string name) + { + return State.TryRemove(name, out _); + } + } +} diff --git a/MangaReader.Core/Services/Config/DatabaseConfig.cs b/MangaReader.Core/Services/Config/DatabaseConfig.cs index a5b7f653..d9204bf0 100644 --- a/MangaReader.Core/Services/Config/DatabaseConfig.cs +++ b/MangaReader.Core/Services/Config/DatabaseConfig.cs @@ -59,12 +59,32 @@ private static async Task CreateDefaultMangaSettings(RepositoryContext context) Manga = plugin.MangaGuid, MangaName = plugin.Name, DefaultCompression = Compression.CompressionMode.Manga, + ProxySetting = await context.Get().SingleAsync(s => s.SettingType == ProxySettingType.System).ConfigureAwait(false), Login = await Login.Get(plugin.LoginType).ConfigureAwait(false) }; await context.Save(setting).ConfigureAwait(false); settings.Add(setting); } + + foreach (var setting in settings) + { + MangaSettingCache.Set(new MangaSettingCache(setting)); + } + } + + private static async Task CreateDefaultProxySettings(RepositoryContext context) + { + var types = new[] { ProxySettingType.NoProxy, ProxySettingType.System }; + foreach (var settingType in types) + { + if (!await context.Get().AnyAsync(s => s.SettingType == settingType) + .ConfigureAwait(false)) + { + var noProxy = new ProxySetting(settingType); + await context.Save(noProxy).ConfigureAwait(false); + } + } } public DatabaseConfig() @@ -77,7 +97,10 @@ public static async Task Initialize() { await Repository.GetStateless().SingleOrCreate().ConfigureAwait(false); using (var context = Repository.GetEntityContext("Initialize database config")) + { + await CreateDefaultProxySettings(context).ConfigureAwait(false); await CreateDefaultMangaSettings(context).ConfigureAwait(false); + } } } -} \ No newline at end of file +} diff --git a/MangaReader.Core/Services/MangaSetting.cs b/MangaReader.Core/Services/MangaSetting.cs index 4ce9d4c5..92863176 100644 --- a/MangaReader.Core/Services/MangaSetting.cs +++ b/MangaReader.Core/Services/MangaSetting.cs @@ -39,6 +39,11 @@ public class MangaSetting : Entity.Entity /// public Guid FolderNamingStrategy { get; set; } + /// + /// Настройки прокси. + /// + public ProxySetting ProxySetting { get; set; } + public override async Task BeforeSave(ChangeTrackerArgs args) { if (!DirectoryHelpers.ValidateSettingPath(this.Folder)) diff --git a/MangaReader.Core/Services/MangaSettingCache.cs b/MangaReader.Core/Services/MangaSettingCache.cs new file mode 100644 index 00000000..eceb5683 --- /dev/null +++ b/MangaReader.Core/Services/MangaSettingCache.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Concurrent; +using System.Collections.Generic; +using System.Linq; +using MangaReader.Core.Services.Config; + +namespace MangaReader.Core.Services +{ + public class MangaSettingCache + { + public Type Plugin { get; set; } + + public System.Net.IWebProxy Proxy { get; set; } + + private static ConcurrentDictionary caches = new ConcurrentDictionary(); + + public static void Set(MangaSettingCache cache) + { + caches.AddOrUpdate(cache.Plugin, cache, (_, __) => cache); + } + + public static MangaSettingCache Get(Type pluginType) + { + MangaSettingCache cache; + if (caches.TryGetValue(pluginType, out cache)) + return cache; + throw new KeyNotFoundException($"В кеше не найдено ничего с типом {pluginType.Name}"); + } + + public static void Clear() + { + caches.Clear(); + } + + public MangaSettingCache(MangaSetting setting) + { + this.Plugin = ConfigStorage.Plugins.Single(p => p.MangaGuid == setting.Manga).GetType(); + this.Proxy = setting.ProxySetting.GetProxy(); + } + } +} diff --git a/MangaReader.Core/Services/Page.cs b/MangaReader.Core/Services/Page.cs index 0f7473d8..c61628fe 100644 --- a/MangaReader.Core/Services/Page.cs +++ b/MangaReader.Core/Services/Page.cs @@ -35,7 +35,7 @@ public static async Task DelayOnExpectationFailed(WebException ex) /// Клиент, если нужен специфичный. /// Попыток скачивания. /// Исходный код страницы. - public static async Task GetPageAsync(Uri url, CookieClient client = null, int restartCounter = 0) + public static async Task GetPageAsync(Uri url, CookieClient client, int restartCounter = 0) { try { @@ -44,7 +44,7 @@ public static async Task GetPageAsync(Uri url, CookieClient client = null, using (await ThrottleService.WaitAsync().ConfigureAwait(false)) { - var cookieClient = client ?? new CookieClient(); + var cookieClient = client; var task = cookieClient.DownloadStringTaskAsync(url).ConfigureAwait(false); return new Page(await task, cookieClient.ResponseUri); } diff --git a/Sites/Acomics.ru/AcomicsClient.cs b/Sites/Acomics.ru/AcomicsClient.cs new file mode 100644 index 00000000..dcbbabdd --- /dev/null +++ b/Sites/Acomics.ru/AcomicsClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Acomics +{ + public class AcomicsClient : CookieClient + { + public AcomicsClient() + { + Proxy = MangaSettingCache.Get(typeof(AcomicsPlugin)).Proxy; + } + } +} diff --git a/Sites/Acomics.ru/AcomicsLogin.cs b/Sites/Acomics.ru/AcomicsLogin.cs index 6b27246b..ed42a73d 100644 --- a/Sites/Acomics.ru/AcomicsLogin.cs +++ b/Sites/Acomics.ru/AcomicsLogin.cs @@ -20,6 +20,11 @@ public class AcomicsLogin : Login public override Uri LogoutUri { get { return new Uri(this.MainUri, "auth/logout"); } } public override Uri BookmarksUri { get { return new Uri(this.MainUri, "settings/subscribes"); } } + protected override CookieClient GetClient() + { + return new AcomicsClient() { BaseAddress = MainUri.ToString(), Cookie = this.ClientCookie }; + } + public override async Task DoLogin() { if (IsLogined || !this.CanLogin) @@ -89,4 +94,4 @@ public AcomicsLogin() this.MainUri = new Uri("https://acomics.ru/"); } } -} \ No newline at end of file +} diff --git a/Sites/Acomics.ru/Parser.cs b/Sites/Acomics.ru/Parser.cs index 8affb76a..567c16e5 100644 --- a/Sites/Acomics.ru/Parser.cs +++ b/Sites/Acomics.ru/Parser.cs @@ -22,10 +22,10 @@ public class Parser : BaseSiteParser private static readonly string VolumeXPath = string.Format("//*[@class=\"{0}\"]", VolumeClassName); private static readonly string ChapterXPath = "//div[@class=\"chapters\"]//a"; - public CookieClient GetAdultClient() + public override CookieClient GetClient() { var host = Generic.GetLoginMainUri().Host; - var client = new CookieClient(); + var client = new AcomicsClient(); client.Cookie.Add(new Cookie("ageRestrict", "40", "/", host)); return client; } @@ -39,7 +39,7 @@ public override async Task UpdateNameAndStatus(IManga manga) try { var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/about"), this.GetAdultClient()).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/about"), this.GetClient()).ConfigureAwait(false)).Content); var nameNode = document.DocumentNode.SelectSingleNode("//head//meta[@property=\"og:title\"]"); if (nameNode != null && nameNode.Attributes.Any(a => Equals(a.Name, "content"))) { @@ -77,7 +77,7 @@ public override async Task UpdateContentType(IManga manga) try { var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/content"), this.GetAdultClient()).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/content"), this.GetClient()).ConfigureAwait(false)).Content); manga.HasVolumes = document.DocumentNode.SelectNodes(VolumeXPath) != null; manga.HasChapters = document.DocumentNode.SelectNodes(ChapterXPath) != null; } @@ -96,7 +96,7 @@ public override async Task UpdateContent(IManga manga) try { var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/content"), this.GetAdultClient()).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/content"), this.GetClient()).ConfigureAwait(false)).Content); var volumeNodes = document.DocumentNode.SelectNodes(VolumeXPath); if (volumeNodes != null) @@ -202,7 +202,7 @@ public override async Task> GetPreviews(IManga manga) try { var document = new HtmlDocument(); - var client = this.GetAdultClient(); + var client = this.GetClient(); document.LoadHtml((await Page.GetPageAsync(new Uri(manga.Uri.OriginalString + @"/banner"), client).ConfigureAwait(false)).Content); var banners = document.DocumentNode.SelectSingleNode("//div[@class='serial-content']"); var image = banners.ChildNodes.SkipWhile(n => n.InnerText != "160x90").Skip(1).FirstOrDefault(); @@ -218,18 +218,19 @@ public override async Task> GetPreviews(IManga manga) return new[] { result }; } - protected override async Task> GetMangaNodes(string name, Uri host, CookieClient client) + protected override async Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host) { var searchHost = new Uri(host, "search?keyword=" + WebUtility.UrlEncode(name)); + var client = GetClient(); var page = await Page.GetPageAsync(searchHost, client).ConfigureAwait(false); if (!page.HasContent) - return null; + return (null, null, null); return await Task.Run(() => { var document = new HtmlDocument(); document.LoadHtml(page.Content); - return new Tuple(document.DocumentNode.SelectNodes("//table[@class='catalog-elem list-loadable']"), host); + return (document.DocumentNode.SelectNodes("//table[@class='catalog-elem list-loadable']"), host, client); }).ConfigureAwait(false); } @@ -261,7 +262,7 @@ private async Task> GetMangaPages(Uri uri) var images = new List(); try { - var adultClient = this.GetAdultClient(); + var adultClient = this.GetClient(); var document = new HtmlDocument(); document.LoadHtml((await Page.GetPageAsync(uri, adultClient).ConfigureAwait(false)).Content); var last = document.DocumentNode.SelectSingleNode("//nav[@class='serial']//a[@class='read2']").Attributes[1].Value; diff --git a/Sites/Grouple.ru/GroupleLogin.cs b/Sites/Grouple.ru/GroupleLogin.cs index 3c6990cc..70ba2859 100644 --- a/Sites/Grouple.ru/GroupleLogin.cs +++ b/Sites/Grouple.ru/GroupleLogin.cs @@ -20,6 +20,12 @@ public class GroupleLogin : Login public override Uri LogoutUri { get { return new Uri(this.MainUri, "login/logout"); } } public override Uri BookmarksUri { get { return new Uri(this.MainUri, "private/bookmarks"); } } + protected override CookieClient GetClient() + { +#warning В итоге конкретный клиент тут забит, а логин на совсем другом хосте. + return new MintmangaClient() { BaseAddress = MainUri.ToString(), Cookie = this.ClientCookie }; + } + public override async Task DoLogin() { if (IsLogined || !this.CanLogin) @@ -66,7 +72,8 @@ protected override async Task> DownloadBookmarks() return bookmarks; } - var parser = new Parser(); +#warning Тоже завязка на конкретный тип + var parser = new MintmangaParser(); using (var context = Repository.GetEntityContext("Loading bookmarks")) { var loadedBookmarks = Regex @@ -92,4 +99,4 @@ public GroupleLogin() this.MainUri = new Uri(@"https://grouple.co/"); } } -} \ No newline at end of file +} diff --git a/Sites/Grouple.ru/GroupleManga.cs b/Sites/Grouple.ru/GroupleManga.cs index 668cf821..b1932e56 100644 --- a/Sites/Grouple.ru/GroupleManga.cs +++ b/Sites/Grouple.ru/GroupleManga.cs @@ -55,7 +55,7 @@ public override List AllowedCompressionModes /// public override async Task Refresh() { - var page = await Page.GetPageAsync(this.Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(this.Uri, Parser.GetClient()).ConfigureAwait(false); if (!page.HasContent) return; @@ -68,9 +68,9 @@ public override async Task Refresh() } // Если на странице редирект - выполняем его и получаем новую ссылку на мангу. - if (page.Content.ToLowerInvariant().Contains(Grouple.Parser.CookieKey)) + if (page.Content.ToLowerInvariant().Contains(Grouple.GroupleParser.CookieKey)) { - var newUri = await Grouple.Parser.GetRedirectUri(page).ConfigureAwait(false); + var newUri = await (Parser as Grouple.GroupleParser).GetRedirectUri(page).ConfigureAwait(false); if (!this.Uri.Equals(newUri)) { this.Uri = newUri; diff --git a/Sites/Grouple.ru/Parser.cs b/Sites/Grouple.ru/GroupleParser.cs similarity index 86% rename from Sites/Grouple.ru/Parser.cs rename to Sites/Grouple.ru/GroupleParser.cs index 9235c659..f68c4f4b 100644 --- a/Sites/Grouple.ru/Parser.cs +++ b/Sites/Grouple.ru/GroupleParser.cs @@ -19,7 +19,7 @@ namespace Grouple { - public class Parser : BaseSiteParser + public abstract class GroupleParser : BaseSiteParser { /// /// Ключ с куками для редиректа. @@ -36,19 +36,19 @@ public class Parser : BaseSiteParser /// /// Содержимое страницы по ссылке. /// Новая ссылка. - public static Task GetRedirectUri(Page page) + public Task GetRedirectUri(Page page) { return GetRedirectUriInternal(page, 0); } - private static async Task GetRedirectUriInternal(Page page, int restartCount) + private async Task GetRedirectUriInternal(Page page, int restartCount) { var fullUri = page.ResponseUri.OriginalString; CookieClient client = null; try { - client = new CookieClient(); + client = this.GetClient(); var cookie = new Cookie { Name = CookieKey, @@ -93,7 +93,7 @@ public override async Task UpdatePages(Chapter groupleChapter) { groupleChapter.Container.Clear(); var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(groupleChapter.Uri).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(groupleChapter.Uri, GetClient()).ConfigureAwait(false)).Content); var node = document.DocumentNode.SelectNodes("//div[@class=\"pageBlock container reader-bottom\"]").FirstOrDefault(); if (node == null) return; @@ -119,7 +119,7 @@ public override async Task UpdatePages(Chapter groupleChapter) public override async Task UpdateNameAndStatus(IManga manga) { - var page = await Page.GetPageAsync(manga.Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(manga.Uri, GetClient()).ConfigureAwait(false); var localizedName = new MangaName(); try { @@ -170,7 +170,7 @@ public override async Task UpdateContent(IManga manga) var dic = new Dictionary(); var links = new List { }; var description = new List { }; - var page = await Page.GetPageAsync(manga.Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(manga.Uri, GetClient()).ConfigureAwait(false); var hasCopyrightNotice = false; try { @@ -230,7 +230,7 @@ public override UriParseResult ParseUri(Uri uri) // Page : - var hosts = ConfigStorage.Plugins - .Where(p => p.GetParser().GetType() == typeof(Parser)) + .Where(p => p.GetParser() is GroupleParser) .Select(p => p.GetSettings().MainUri); foreach (var host in hosts) @@ -257,18 +257,19 @@ public override Task> GetPreviews(IManga manga) return GetPreviewsImpl(manga); } - protected override async Task> GetMangaNodes(string name, Uri host, CookieClient client) + protected override async Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host) { var searchHost = new Uri(host, "search"); + var client = GetClient(); var page = await client.UploadValuesTaskAsync(searchHost, new NameValueCollection() { { "q", WebUtility.UrlEncode(name) } }).ConfigureAwait(false); if (page == null) - return null; + return (null, null, null); return await Task.Run(() => { var document = new HtmlDocument(); document.LoadHtml(Encoding.UTF8.GetString(page)); - return new Tuple(document.DocumentNode.SelectNodes("//div[contains(@class, 'col-sm-6')]"), host); + return (document.DocumentNode.SelectNodes("//div[contains(@class, 'col-sm-6')]"), host, client); }).ConfigureAwait(false); } @@ -298,7 +299,7 @@ protected override async Task GetMangaFromNode(Uri host, CookieClient cl private async Task> GetPreviewsImpl(IManga manga) { var document = new HtmlDocument(); - var client = new CookieClient(); + var client = this.GetClient(); document.LoadHtml((await Page.GetPageAsync(manga.Uri, client).ConfigureAwait(false)).Content); var banners = document.DocumentNode.SelectSingleNode("//div[@class='picture-fotorama']"); var images = new List(); @@ -336,28 +337,5 @@ private async Task> GetPreviewsImpl(IManga manga) return images; } - - public override IMapper GetMapper() - { - return Mappers.GetOrAdd(typeof(Parser), type => - { - var config = new MapperConfiguration(cfg => - { - cfg.AddCollectionMappers(); - cfg.CreateMap() - .EqualityComparison((src, dest) => src.Number == dest.Number); - cfg.CreateMap() - .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) - .EqualityComparison((src, dest) => src.Number == dest.Number); - cfg.CreateMap() - .IncludeBase() - .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) - .EqualityComparison((src, dest) => src.Number == dest.Number); - cfg.CreateMap() - .EqualityComparison((src, dest) => src.ImageLink == dest.ImageLink); - }); - return config.CreateMapper(); - }); - } } } diff --git a/Sites/Grouple.ru/MintmangaClient.cs b/Sites/Grouple.ru/MintmangaClient.cs new file mode 100644 index 00000000..e83febfd --- /dev/null +++ b/Sites/Grouple.ru/MintmangaClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Grouple +{ + public class MintmangaClient : CookieClient + { + public MintmangaClient() + { + this.Proxy = MangaSettingCache.Get(typeof(MintmangaPlugin)).Proxy; + } + } +} \ No newline at end of file diff --git a/Sites/Grouple.ru/MintmangaParser.cs b/Sites/Grouple.ru/MintmangaParser.cs new file mode 100644 index 00000000..1672cc3c --- /dev/null +++ b/Sites/Grouple.ru/MintmangaParser.cs @@ -0,0 +1,39 @@ +using AutoMapper; +using AutoMapper.EquivalencyExpression; +using MangaReader.Core.Account; +using MangaReader.Core.DataTrasferObject; +using MangaReader.Core.Manga; + +namespace Grouple +{ + public class MintmangaParser : GroupleParser + { + public override CookieClient GetClient() + { + return new MintmangaClient(); + } + + public override IMapper GetMapper() + { + return Mappers.GetOrAdd(typeof(MintmangaParser), type => + { + var config = new MapperConfiguration(cfg => + { + cfg.AddCollectionMappers(); + cfg.CreateMap() + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .IncludeBase() + .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .EqualityComparison((src, dest) => src.ImageLink == dest.ImageLink); + }); + return config.CreateMapper(); + }); + } + } +} diff --git a/Sites/Grouple.ru/MintmangaPlugin.cs b/Sites/Grouple.ru/MintmangaPlugin.cs index 3b95e74d..8e5de70f 100644 --- a/Sites/Grouple.ru/MintmangaPlugin.cs +++ b/Sites/Grouple.ru/MintmangaPlugin.cs @@ -18,7 +18,7 @@ public class MintmangaPlugin : BasePlugin public override HistoryType HistoryType { get { return HistoryType.Chapter; } } public override ISiteParser GetParser() { - return new Parser(); + return new MintmangaParser(); } } -} \ No newline at end of file +} diff --git a/Sites/Grouple.ru/ReadmangaClient.cs b/Sites/Grouple.ru/ReadmangaClient.cs new file mode 100644 index 00000000..592d69a1 --- /dev/null +++ b/Sites/Grouple.ru/ReadmangaClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Grouple +{ + public class ReadmangaClient : CookieClient + { + public ReadmangaClient() + { + this.Proxy = MangaSettingCache.Get(typeof(ReadmangaPlugin)).Proxy; + } + } +} diff --git a/Sites/Grouple.ru/ReadmangaParser.cs b/Sites/Grouple.ru/ReadmangaParser.cs new file mode 100644 index 00000000..2fcf50ec --- /dev/null +++ b/Sites/Grouple.ru/ReadmangaParser.cs @@ -0,0 +1,39 @@ +using AutoMapper; +using AutoMapper.EquivalencyExpression; +using MangaReader.Core.Account; +using MangaReader.Core.DataTrasferObject; +using MangaReader.Core.Manga; + +namespace Grouple +{ + public class ReadmangaParser : GroupleParser + { + public override CookieClient GetClient() + { + return new ReadmangaClient(); + } + + public override IMapper GetMapper() + { + return Mappers.GetOrAdd(typeof(ReadmangaParser), type => + { + var config = new MapperConfiguration(cfg => + { + cfg.AddCollectionMappers(); + cfg.CreateMap() + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .IncludeBase() + .ConstructUsing(dto => new GroupleChapter(dto.Uri, dto.Name)) + .EqualityComparison((src, dest) => src.Number == dest.Number); + cfg.CreateMap() + .EqualityComparison((src, dest) => src.ImageLink == dest.ImageLink); + }); + return config.CreateMapper(); + }); + } + } +} diff --git a/Sites/Grouple.ru/ReadmangaPlugin.cs b/Sites/Grouple.ru/ReadmangaPlugin.cs index 8fc85b26..e144925e 100644 --- a/Sites/Grouple.ru/ReadmangaPlugin.cs +++ b/Sites/Grouple.ru/ReadmangaPlugin.cs @@ -18,7 +18,7 @@ public class ReadmangaPlugin : BasePlugin public override HistoryType HistoryType { get { return HistoryType.Chapter; } } public override ISiteParser GetParser() { - return new Parser(); + return new ReadmangaParser(); } } -} \ No newline at end of file +} diff --git a/Sites/Hentai2Read.com/Hentai2ReadClient.cs b/Sites/Hentai2Read.com/Hentai2ReadClient.cs new file mode 100644 index 00000000..d59a5d47 --- /dev/null +++ b/Sites/Hentai2Read.com/Hentai2ReadClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Hentai2Read.com +{ + public class Hentai2ReadClient : CookieClient + { + public Hentai2ReadClient() + { + Proxy = MangaSettingCache.Get(typeof(Hentai2ReadPlugin)).Proxy; + } + } +} diff --git a/Sites/Hentai2Read.com/Hentai2ReadLogin.cs b/Sites/Hentai2Read.com/Hentai2ReadLogin.cs index 03148544..9874e39b 100644 --- a/Sites/Hentai2Read.com/Hentai2ReadLogin.cs +++ b/Sites/Hentai2Read.com/Hentai2ReadLogin.cs @@ -21,6 +21,11 @@ public class Hentai2ReadLogin : Login internal string LogoutNonce { get; set; } + protected override CookieClient GetClient() + { + return new Hentai2ReadClient() { BaseAddress = MainUri.ToString(), Cookie = this.ClientCookie }; + } + public override async Task DoLogin() { if (IsLogined || !this.CanLogin) @@ -99,4 +104,4 @@ public Hentai2ReadLogin() this.MainUri = new Uri("https://hentai2read.com/"); } } -} \ No newline at end of file +} diff --git a/Sites/Hentai2Read.com/Hentai2ReadParser.cs b/Sites/Hentai2Read.com/Hentai2ReadParser.cs index e6265010..5ad6a024 100644 --- a/Sites/Hentai2Read.com/Hentai2ReadParser.cs +++ b/Sites/Hentai2Read.com/Hentai2ReadParser.cs @@ -22,6 +22,11 @@ namespace Hentai2Read.com { public class Hentai2ReadParser : BaseSiteParser { + public override CookieClient GetClient() + { + return new Hentai2ReadClient(); + } + /// /// Обновить название и статус манги. /// @@ -31,7 +36,7 @@ public override async Task UpdateNameAndStatus(IManga manga) try { var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(manga.Uri).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(manga.Uri, GetClient()).ConfigureAwait(false)).Content); var nameNode = document.DocumentNode.SelectSingleNode("//span[@itemprop=\"name\"]"); if (nameNode != null) { @@ -82,7 +87,7 @@ public override async Task UpdateContent(IManga manga) try { var document = new HtmlDocument(); - document.LoadHtml((await Page.GetPageAsync(manga.Uri).ConfigureAwait(false)).Content); + document.LoadHtml((await Page.GetPageAsync(manga.Uri, GetClient()).ConfigureAwait(false)).Content); var chapterNodes = document.DocumentNode.SelectNodes("//a[@class=\"pull-left font-w600\"]").Reverse(); foreach (var chapterNode in chapterNodes) @@ -106,7 +111,7 @@ public override async Task UpdatePages(Chapter chapter) try { var document = new HtmlDocument(); - var page = await Page.GetPageAsync(chapter.Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(chapter.Uri, GetClient()).ConfigureAwait(false); document.LoadHtml(page.Content); var imgs = Regex.Match(document.DocumentNode.OuterHtml, @"\'images\'\s*:\s*(\[.+\])", RegexOptions.IgnoreCase).Groups[1].Value; @@ -158,7 +163,7 @@ public override async Task> GetPreviews(IManga manga) try { var document = new HtmlDocument(); - var client = new CookieClient(); + var client = GetClient(); document.LoadHtml((await Page.GetPageAsync(manga.Uri, client).ConfigureAwait(false)).Content); var imageBlock = document.DocumentNode.SelectSingleNode("//img[@class=\"img-responsive border-black-op\"]"); var src = imageBlock.Attributes.Single(a => a.Name == "src").Value; @@ -168,19 +173,20 @@ public override async Task> GetPreviews(IManga manga) return new[] { result }; } - protected override async Task> GetMangaNodes(string name, Uri host, CookieClient client) + protected override async Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host) { var searchHost = new Uri(host, "hentai-list/search/"); + var client = GetClient(); var page = await client.UploadValuesTaskAsync(searchHost, new NameValueCollection() { { "cmd_wpm_wgt_mng_sch_sbm", "Search" }, {"txt_wpm_wgt_mng_sch_nme", WebUtility.UrlEncode(name)}}).ConfigureAwait(false); if (page == null) - return null; + return (null, null, null); return await Task.Run(() => { var document = new HtmlDocument(); document.LoadHtml(Encoding.UTF8.GetString(page)); - return new Tuple(document.DocumentNode.SelectNodes("//div[@class=\"col-xs-6 col-sm-4 col-md-3 col-lg-2b col-xl-2\"]"), host); + return (document.DocumentNode.SelectNodes("//div[@class=\"col-xs-6 col-sm-4 col-md-3 col-lg-2b col-xl-2\"]"), host, client); }).ConfigureAwait(false); } diff --git a/Sites/Hentaichan.me/HentaichanClient.cs b/Sites/Hentaichan.me/HentaichanClient.cs new file mode 100644 index 00000000..3e3a933b --- /dev/null +++ b/Sites/Hentaichan.me/HentaichanClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Hentaichan +{ + public class HentaichanClient : CookieClient + { + public HentaichanClient() + { + Proxy = MangaSettingCache.Get(typeof(HentaichanPlugin)).Proxy; + } + } +} diff --git a/Sites/Hentaichan.me/HentaichanLogin.cs b/Sites/Hentaichan.me/HentaichanLogin.cs index 38f9277c..56f88b1a 100644 --- a/Sites/Hentaichan.me/HentaichanLogin.cs +++ b/Sites/Hentaichan.me/HentaichanLogin.cs @@ -16,6 +16,11 @@ namespace Hentaichan { public class HentaichanLogin : BaseLogin { + protected override CookieClient GetClient() + { + return new HentaichanClient() { BaseAddress = MainUri.ToString(), Cookie = this.ClientCookie }; + } + protected override async Task> DownloadBookmarks() { var bookmarks = new List(); @@ -84,4 +89,4 @@ public HentaichanLogin() this.MainUri = new Uri(@"http://henchan.me/"); } } -} \ No newline at end of file +} diff --git a/Sites/Hentaichan.me/Mangachan/Mangachan.cs b/Sites/Hentaichan.me/Mangachan/Mangachan.cs index 0f4610da..b20e9587 100644 --- a/Sites/Hentaichan.me/Mangachan/Mangachan.cs +++ b/Sites/Hentaichan.me/Mangachan/Mangachan.cs @@ -32,7 +32,7 @@ public override async Task Refresh() { if (Parser.ParseUri(Uri).Kind != UriParseKind.Manga) { - var page = await Page.GetPageAsync(Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(Uri, Parser.GetClient()).ConfigureAwait(false); if (page.HasContent) { var match = Regex.Match(page.Content, "content_id\":\"(.*?)\"", RegexOptions.IgnoreCase); diff --git a/Sites/Hentaichan.me/Mangachan/MangachanClient.cs b/Sites/Hentaichan.me/Mangachan/MangachanClient.cs new file mode 100644 index 00000000..7b97ea17 --- /dev/null +++ b/Sites/Hentaichan.me/Mangachan/MangachanClient.cs @@ -0,0 +1,13 @@ +using MangaReader.Core.Account; +using MangaReader.Core.Services; + +namespace Hentaichan.Mangachan +{ + public class MangachanClient : CookieClient + { + public MangachanClient() + { + Proxy = MangaSettingCache.Get(typeof(MangachanPlugin)).Proxy; + } + } +} diff --git a/Sites/Hentaichan.me/Mangachan/MangachanLogin.cs b/Sites/Hentaichan.me/Mangachan/MangachanLogin.cs index 9d9af850..c555cecf 100644 --- a/Sites/Hentaichan.me/Mangachan/MangachanLogin.cs +++ b/Sites/Hentaichan.me/Mangachan/MangachanLogin.cs @@ -6,6 +6,7 @@ using System.Text.RegularExpressions; using System.Threading.Tasks; using HtmlAgilityPack; +using MangaReader.Core.Account; using MangaReader.Core.Manga; using MangaReader.Core.Services; @@ -13,6 +14,10 @@ namespace Hentaichan.Mangachan { public class MangachanLogin : BaseLogin { + protected override CookieClient GetClient() + { + return new MangachanClient() { BaseAddress = MainUri.ToString(), Cookie = this.ClientCookie }; + } /// /// http://mangachan.me/user/RandomUserName/favorites diff --git a/Sites/Hentaichan.me/Mangachan/Parser.cs b/Sites/Hentaichan.me/Mangachan/Parser.cs index 3c8e8c8b..109b67c5 100644 --- a/Sites/Hentaichan.me/Mangachan/Parser.cs +++ b/Sites/Hentaichan.me/Mangachan/Parser.cs @@ -20,10 +20,10 @@ namespace Hentaichan.Mangachan { public class Parser : BaseSiteParser { - private static CookieClient GetClient() + public override CookieClient GetClient() { var setting = ConfigStorage.GetPlugin().GetSettings(); - var client = new CookieClient(); + var client = new MangachanClient(); if (setting != null) { var login = setting.Login as BaseLogin; @@ -160,21 +160,22 @@ public override UriParseResult ParseUri(Uri uri) public override Task> GetPreviews(IManga manga) { - return GetPreviewsImpl(manga); + return GetPreviewsImpl(this, manga); } - protected override async Task> GetMangaNodes(string name, Uri host, CookieClient client) + protected override async Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host) { var searchHost = new Uri(host, "?do=search&subaction=search&story=" + WebUtility.UrlEncode(name)); + var client = GetClient(); var page = await Page.GetPageAsync(searchHost, client).ConfigureAwait(false); if (!page.HasContent) - return null; + return (null, null, null); return await Task.Run(() => { var document = new HtmlDocument(); document.LoadHtml(page.Content); - return new Tuple(document.DocumentNode.SelectNodes("//div[@class='content_row']"), host); + return (document.DocumentNode.SelectNodes("//div[@class='content_row']"), host, client); }).ConfigureAwait(false); } @@ -194,10 +195,10 @@ protected override async Task GetMangaFromNode(Uri host, CookieClient cl return result; } - internal static async Task> GetPreviewsImpl(IManga manga) + internal static async Task> GetPreviewsImpl(ISiteParser parser, IManga manga) { var links = new List(); - var client = GetClient(); + var client = parser.GetClient(); try { var document = new HtmlDocument(); diff --git a/Sites/Hentaichan.me/Parser.cs b/Sites/Hentaichan.me/Parser.cs index c48c6b10..2d1703b3 100644 --- a/Sites/Hentaichan.me/Parser.cs +++ b/Sites/Hentaichan.me/Parser.cs @@ -24,10 +24,10 @@ public class Parser : BaseSiteParser private const string NeedRegister = "Контент запрещен на территории РФ"; private const string IsDevelopment = "?development_access=true"; - public static CookieClient GetClient() + public override CookieClient GetClient() { var setting = ConfigStorage.GetPlugin().GetSettings(); - var client = new CookieClient(); + var client = new HentaichanClient(); if (setting != null) { var login = setting.Login as HentaichanLogin; @@ -53,7 +53,7 @@ public static CookieClient GetClient() public override async Task UpdateNameAndStatus(IManga manga) { - var page = await Page.GetPageAsync(manga.Uri).ConfigureAwait(false); + var page = await Page.GetPageAsync(manga.Uri, GetClient()).ConfigureAwait(false); var name = string.Empty; try { @@ -154,7 +154,7 @@ public override async Task UpdateContent(IManga manga) FillMangaChapters(manga, chapters); } - private static async Task> GetPageWithRedirect(Uri uri) + private async Task> GetPageWithRedirect(Uri uri) { uri = new Uri(uri.OriginalString.Replace(@"/manga/", @"/online/")); var page = await Page.GetPageAsync(uri, GetClient()).ConfigureAwait(false); @@ -201,21 +201,23 @@ public override UriParseResult ParseUri(Uri uri) public override Task> GetPreviews(IManga manga) { - return Mangachan.Parser.GetPreviewsImpl(manga); + + return Mangachan.Parser.GetPreviewsImpl(this, manga); } - protected override async Task> GetMangaNodes(string name, Uri host, CookieClient client) + protected override async Task<(HtmlNodeCollection Nodes, Uri Uri, CookieClient CookieClient)> GetMangaNodes(string name, Uri host) { var searchHost = new Uri(host, "?do=search&subaction=search&story=" + WebUtility.UrlEncode(name)); + var client = GetClient(); var page = await Page.GetPageAsync(searchHost, client).ConfigureAwait(false); if (!page.HasContent) - return null; + return (null, null, null); return await Task.Run(() => { var document = new HtmlDocument(); document.LoadHtml(page.Content); - return new Tuple(document.DocumentNode.SelectNodes("//div[@class='content_row']"), host); + return (document.DocumentNode.SelectNodes("//div[@class='content_row']"), host, client); }).ConfigureAwait(false); } diff --git a/Tests/Tests.Entities/Manga/ReadmangaMoved.cs b/Tests/Tests.Entities/Manga/MangaMove.cs similarity index 70% rename from Tests/Tests.Entities/Manga/ReadmangaMoved.cs rename to Tests/Tests.Entities/Manga/MangaMove.cs index 4592d94d..d533333f 100644 --- a/Tests/Tests.Entities/Manga/ReadmangaMoved.cs +++ b/Tests/Tests.Entities/Manga/MangaMove.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Threading.Tasks; using Grouple; +using MangaReader.Core.Exception; using MangaReader.Core.Manga; using MangaReader.Core.NHibernate; using MangaReader.Core.Services; @@ -11,10 +12,10 @@ namespace Tests.Entities.Manga { [TestFixture] - public class ReadmangaMoved : TestClass + public class MangaMove : TestClass { [Test] - public async Task CreateWithHistoryAndMove() + public async Task CreateReadmangaWithHistoryAndMove() { var model = new MangaReader.Core.Services.LibraryViewModel(); using (var context = Repository.GetEntityContext()) @@ -44,5 +45,26 @@ public async Task CreateWithHistoryAndMove() Assert.AreEqual(0, chartersNotInHistory.Count); } } + + [Test] + public async Task AcomicsMoveTo([Values]bool sameSite) + { + using (var context = Repository.GetEntityContext()) + { + var manga = await Builder.CreateAcomics().ConfigureAwait(false); + + async Task SaveManga() + { + await context.Save(manga).ConfigureAwait(false); + } + + manga.Uri = sameSite ? new Uri(MangaInfos.Acomics.SuperScienceFriends.Uri) : new Uri(MangaInfos.Henchan.TwistedIntent.Uri); + + if (sameSite) + Assert.DoesNotThrowAsync(SaveManga); + else + Assert.ThrowsAsync(SaveManga); + } + } } } diff --git a/Tests/Tests.Entities/Manga/MintmangaStructure.cs b/Tests/Tests.Entities/Manga/MintmangaStructure.cs index 614d971a..4bab1b42 100644 --- a/Tests/Tests.Entities/Manga/MintmangaStructure.cs +++ b/Tests/Tests.Entities/Manga/MintmangaStructure.cs @@ -20,8 +20,8 @@ public async Task AddMintmangaWithExtra() private async Task GetCountOfChapters(string url) { var manga = await Mangas.Create(new Uri(url)).ConfigureAwait(false); - await new Parser().UpdateContent(manga).ConfigureAwait(false); + await new MintmangaParser().UpdateContent(manga).ConfigureAwait(false); return manga.Volumes.Sum(v => v.Container.Count()); } } -} \ No newline at end of file +} diff --git a/Tests/Tests.Entities/Manga/ReadmangaCensored.cs b/Tests/Tests.Entities/Manga/ReadmangaCensored.cs index a9e6091b..2d6b35ca 100644 --- a/Tests/Tests.Entities/Manga/ReadmangaCensored.cs +++ b/Tests/Tests.Entities/Manga/ReadmangaCensored.cs @@ -14,7 +14,7 @@ namespace Tests.Entities.Manga [TestFixture] public class ReadmangaCensored : TestClass { - private Parser parser = new Grouple.Parser(); + private ReadmangaParser parser = new Grouple.ReadmangaParser(); // Not censored // http://readmanga.me/black_butler_anthology_comic_rainbow_butler/vol1/6 diff --git a/Tests/Tests.Entities/Manga/ReadmangaStructure.cs b/Tests/Tests.Entities/Manga/ReadmangaStructure.cs index de5df518..59f9d53b 100644 --- a/Tests/Tests.Entities/Manga/ReadmangaStructure.cs +++ b/Tests/Tests.Entities/Manga/ReadmangaStructure.cs @@ -41,8 +41,8 @@ public async Task AddReadmangaWithExtra() private async Task GetCountOfChapters(string url) { var manga = await Mangas.Create(new Uri(url)).ConfigureAwait(false); - await new Parser().UpdateContent(manga).ConfigureAwait(false); + await new ReadmangaParser().UpdateContent(manga).ConfigureAwait(false); return manga.Volumes.Sum(v => v.Container.Count()); } } -} \ No newline at end of file +} diff --git a/Tests/Tests.Entities/Search/Grouple.cs b/Tests/Tests.Entities/Search/Grouple.cs index 527757e9..e1d1b863 100644 --- a/Tests/Tests.Entities/Search/Grouple.cs +++ b/Tests/Tests.Entities/Search/Grouple.cs @@ -18,8 +18,8 @@ public void SearchOnGrouple() private IEnumerable Search(string name) { - return new global::Grouple.Parser().Search(name).ToEnumerable(); + return new global::Grouple.MintmangaParser().Search(name).ToEnumerable(); } } -} \ No newline at end of file +} diff --git a/Tests/Tests.Entities/Tests.Entities.csproj b/Tests/Tests.Entities/Tests.Entities.csproj index a34a3906..e0ade789 100644 --- a/Tests/Tests.Entities/Tests.Entities.csproj +++ b/Tests/Tests.Entities/Tests.Entities.csproj @@ -113,7 +113,7 @@ - +