diff --git a/src/Jackett.Common/Indexers/Abnormal.cs b/src/Jackett.Common/Indexers/Abnormal.cs index ae8f0da93..0b985aa21 100644 --- a/src/Jackett.Common/Indexers/Abnormal.cs +++ b/src/Jackett.Common/Indexers/Abnormal.cs @@ -548,7 +548,7 @@ namespace Jackett.Common.Indexers /// Results from query private async Task queryTracker(string request) { - BaseWebResult results = null; + WebClientStringResult results = null; // Cache mode not enabled or cached file didn't exist for our query output("\nQuerying tracker for results...."); diff --git a/src/Jackett.Common/Indexers/AniDUB.cs b/src/Jackett.Common/Indexers/AniDUB.cs index 36f069dce..fe6615363 100644 --- a/src/Jackett.Common/Indexers/AniDUB.cs +++ b/src/Jackett.Common/Indexers/AniDUB.cs @@ -509,7 +509,7 @@ namespace Jackett.Common.Indexers return domDate.NodeValue.Trim(); } - private bool IsAuthorized(BaseWebResult result) => + private bool IsAuthorized(WebClientStringResult result) => result.ContentString.Contains("index.php?action=logout"); private IEnumerable ParseCategories(Uri showUri) diff --git a/src/Jackett.Common/Indexers/BJShare.cs b/src/Jackett.Common/Indexers/BJShare.cs index 12c106cac..c0204b071 100644 --- a/src/Jackett.Common/Indexers/BJShare.cs +++ b/src/Jackett.Common/Indexers/BJShare.cs @@ -219,7 +219,7 @@ namespace Jackett.Common.Indexers return title; } - private bool IsSessionIsClosed(BaseWebResult result) + private bool IsSessionIsClosed(WebClientStringResult result) { return result.IsRedirect && result.RedirectingTo.Contains("login.php"); } diff --git a/src/Jackett.Common/Indexers/BaseIndexer.cs b/src/Jackett.Common/Indexers/BaseIndexer.cs index 9fad0e186..1883e2eb2 100644 --- a/src/Jackett.Common/Indexers/BaseIndexer.cs +++ b/src/Jackett.Common/Indexers/BaseIndexer.cs @@ -412,7 +412,7 @@ namespace Jackett.Common.Indexers return response.ContentBytes; } - protected async Task RequestBytesWithCookiesAndRetry(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null) + protected async Task RequestBytesWithCookiesAndRetry(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null) { Exception lastException = null; for (var i = 0; i < 3; i++) @@ -432,7 +432,7 @@ namespace Jackett.Common.Indexers throw lastException; } - protected async Task RequestStringWithCookies(string url, string cookieOverride = null, string referer = null, Dictionary headers = null) + protected async Task RequestStringWithCookies(string url, string cookieOverride = null, string referer = null, Dictionary headers = null) { var request = new Utils.Clients.WebRequest() { @@ -452,7 +452,7 @@ namespace Jackett.Common.Indexers return result; } - protected async Task RequestStringWithCookiesAndRetry(string url, string cookieOverride = null, string referer = null, Dictionary headers = null) + protected async Task RequestStringWithCookiesAndRetry(string url, string cookieOverride = null, string referer = null, Dictionary headers = null) { Exception lastException = null; for (var i = 0; i < 3; i++) @@ -472,7 +472,7 @@ namespace Jackett.Common.Indexers throw lastException; } - protected virtual async Task RequestBytesWithCookies(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null, Dictionary headers = null) + protected virtual async Task RequestBytesWithCookies(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null, Dictionary headers = null) { var request = new Utils.Clients.WebRequest() { @@ -492,7 +492,7 @@ namespace Jackett.Common.Indexers return result; } - protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null, bool? emulateBrowser = null) + protected async Task PostDataWithCookies(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null, bool? emulateBrowser = null) { var request = new Utils.Clients.WebRequest() { @@ -514,7 +514,7 @@ namespace Jackett.Common.Indexers return result; } - protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null, bool? emulateBrowser = null) + protected async Task PostDataWithCookiesAndRetry(string url, IEnumerable> data, string cookieOverride = null, string referer = null, Dictionary headers = null, string rawbody = null, bool? emulateBrowser = null) { Exception lastException = null; for (var i = 0; i < 3; i++) @@ -534,7 +534,7 @@ namespace Jackett.Common.Indexers throw lastException; } - protected async Task RequestLoginAndFollowRedirect(string url, IEnumerable> data, string cookies, bool returnCookiesFromFirstCall, string redirectUrlOverride = null, string referer = null, bool accumulateCookies = false) + protected async Task RequestLoginAndFollowRedirect(string url, IEnumerable> data, string cookies, bool returnCookiesFromFirstCall, string redirectUrlOverride = null, string referer = null, bool accumulateCookies = false) { var request = new Utils.Clients.WebRequest() { @@ -566,7 +566,7 @@ namespace Jackett.Common.Indexers return response; } - protected void CheckTrackerDown(BaseWebResult response) + protected void CheckTrackerDown(WebClientStringResult response) { if (response.Status == System.Net.HttpStatusCode.BadGateway || response.Status == System.Net.HttpStatusCode.GatewayTimeout diff --git a/src/Jackett.Common/Indexers/BitHDTV.cs b/src/Jackett.Common/Indexers/BitHDTV.cs index 589d5bc64..93afb4207 100644 --- a/src/Jackett.Common/Indexers/BitHDTV.cs +++ b/src/Jackett.Common/Indexers/BitHDTV.cs @@ -122,7 +122,7 @@ namespace Jackett.Common.Indexers { {"cat", MapTorznabCapsToTrackers(query, true).FirstIfSingleOrDefault("0")} }; - var results = new List(); + var results = new List(); var search = new UriBuilder(SearchUrl); if (query.IsImdbQuery) { diff --git a/src/Jackett.Common/Indexers/CardigannIndexer.cs b/src/Jackett.Common/Indexers/CardigannIndexer.cs index 70bc5923f..f0dd0ff6c 100644 --- a/src/Jackett.Common/Indexers/CardigannIndexer.cs +++ b/src/Jackett.Common/Indexers/CardigannIndexer.cs @@ -26,7 +26,7 @@ namespace Jackett.Common.Indexers public class CardigannIndexer : BaseWebIndexer { protected IndexerDefinition Definition; - protected BaseWebResult landingResult; + protected WebClientStringResult landingResult; protected IHtmlDocument landingResultDocument; protected List DefaultCategories = new List(); @@ -455,7 +455,7 @@ namespace Jackett.Common.Indexers return template; } - protected bool checkForError(BaseWebResult loginResult, IList errorBlocks) + protected bool checkForError(WebClientStringResult loginResult, IList errorBlocks) { if (loginResult.Status == HttpStatusCode.Unauthorized) // e.g. used by YGGtorrent throw new ExceptionWithConfigData("401 Unauthorized, check your credentials", configData); @@ -702,7 +702,7 @@ namespace Jackett.Common.Indexers landingResult = null; landingResultDocument = null; - BaseWebResult loginResult = null; + WebClientStringResult loginResult = null; var enctype = form.GetAttribute("enctype"); if (enctype == "multipart/form-data") { @@ -1334,7 +1334,7 @@ namespace Jackett.Common.Indexers logger.Info($"Fetching: {searchUrl}"); // send HTTP request - BaseWebResult response = null; + WebClientStringResult response = null; Dictionary headers = null; if (Search.Headers != null) { @@ -1721,7 +1721,7 @@ namespace Jackett.Common.Indexers return releases; } - protected async Task handleRequest(requestBlock request, Dictionary variables = null, string referer = null) + protected async Task handleRequest(requestBlock request, Dictionary variables = null, string referer = null) { var requestLinkStr = resolvePath(applyGoTemplateText(request.Path, variables)).ToString(); logger.Debug($"CardigannIndexer ({Id}): handleRequest() requestLinkStr= {requestLinkStr}"); diff --git a/src/Jackett.Common/Indexers/Cinecalidad.cs b/src/Jackett.Common/Indexers/Cinecalidad.cs index 309087804..ffac06989 100644 --- a/src/Jackett.Common/Indexers/Cinecalidad.cs +++ b/src/Jackett.Common/Indexers/Cinecalidad.cs @@ -142,7 +142,7 @@ namespace Jackett.Common.Indexers return null; } - private List ParseReleases(BaseWebResult response, TorznabQuery query) + private List ParseReleases(WebClientStringResult response, TorznabQuery query) { var releases = new List(); diff --git a/src/Jackett.Common/Indexers/CorsaroRed.cs b/src/Jackett.Common/Indexers/CorsaroRed.cs index e94ea6548..3cfc9895c 100644 --- a/src/Jackett.Common/Indexers/CorsaroRed.cs +++ b/src/Jackett.Common/Indexers/CorsaroRed.cs @@ -107,7 +107,7 @@ namespace Jackett.Common.Indexers return IndexerConfigurationStatus.Completed; } - private dynamic CheckResponse(BaseWebResult result) + private dynamic CheckResponse(WebClientStringResult result) { try { diff --git a/src/Jackett.Common/Indexers/DanishBits.cs b/src/Jackett.Common/Indexers/DanishBits.cs index 8c9d5c2f5..53626f324 100644 --- a/src/Jackett.Common/Indexers/DanishBits.cs +++ b/src/Jackett.Common/Indexers/DanishBits.cs @@ -65,7 +65,7 @@ namespace Jackett.Common.Indexers return searchString; } - protected override async Task RequestBytesWithCookies(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null, Dictionary headers = null) + protected override async Task RequestBytesWithCookies(string url, string cookieOverride = null, RequestType method = RequestType.GET, string referer = null, IEnumerable> data = null, Dictionary headers = null) { CookieHeader = null; // Download fill fail with cookies set return await base.RequestBytesWithCookies(url, cookieOverride, method, referer, data, headers); diff --git a/src/Jackett.Common/Indexers/InternetArchive.cs b/src/Jackett.Common/Indexers/InternetArchive.cs index b9c0c2461..4bfb5bb62 100644 --- a/src/Jackett.Common/Indexers/InternetArchive.cs +++ b/src/Jackett.Common/Indexers/InternetArchive.cs @@ -150,7 +150,7 @@ namespace Jackett.Common.Indexers return releases; } - private JArray ParseResponse(BaseWebResult result) + private JArray ParseResponse(WebClientStringResult result) { try { diff --git a/src/Jackett.Common/Indexers/LostFilm.cs b/src/Jackett.Common/Indexers/LostFilm.cs index 7edd2dc2a..d2cff3a96 100644 --- a/src/Jackett.Common/Indexers/LostFilm.cs +++ b/src/Jackett.Common/Indexers/LostFilm.cs @@ -212,7 +212,7 @@ namespace Jackett.Common.Indexers } } - private async Task RequestStringAndRelogin(string url) + private async Task RequestStringAndRelogin(string url) { var results = await RequestStringWithCookies(url); if (results.ContentString.Contains("503 Service")) diff --git a/src/Jackett.Common/Indexers/NCore.cs b/src/Jackett.Common/Indexers/NCore.cs index eb697bc91..1417e11d3 100644 --- a/src/Jackett.Common/Indexers/NCore.cs +++ b/src/Jackett.Common/Indexers/NCore.cs @@ -207,7 +207,7 @@ namespace Jackett.Common.Indexers return releases; } - private List ParseTorrents(BaseWebResult results, string episodeString, TorznabQuery query, + private List ParseTorrents(WebClientStringResult results, string episodeString, TorznabQuery query, int alreadyFound, int limit, int previouslyParsedOnPage) { var releases = new List(); diff --git a/src/Jackett.Common/Indexers/NorBits.cs b/src/Jackett.Common/Indexers/NorBits.cs index b8ceb32b8..12a362079 100644 --- a/src/Jackett.Common/Indexers/NorBits.cs +++ b/src/Jackett.Common/Indexers/NorBits.cs @@ -459,9 +459,9 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryExec(string request) + private async Task QueryExec(string request) { - BaseWebResult results; + WebClientStringResult results; // Switch in we are in DEV mode with Hard Drive Cache or not if (DevMode && CacheMode) @@ -482,9 +482,9 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryCache(string request) + private async Task QueryCache(string request) { - BaseWebResult results; + WebClientStringResult results; // Create Directory if not exist System.IO.Directory.CreateDirectory(Directory); @@ -519,7 +519,7 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryTracker(string request) + private async Task QueryTracker(string request) { // Cache mode not enabled or cached file didn't exist for our query Output("\nQuerying tracker for results...."); diff --git a/src/Jackett.Common/Indexers/NordicBits.cs b/src/Jackett.Common/Indexers/NordicBits.cs index d9a11fdb1..e74f342cd 100644 --- a/src/Jackett.Common/Indexers/NordicBits.cs +++ b/src/Jackett.Common/Indexers/NordicBits.cs @@ -530,9 +530,9 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryExec(string request) + private async Task QueryExec(string request) { - BaseWebResult results; + WebClientStringResult results; // Switch in we are in DEV mode with Hard Drive Cache or not if (DevMode && CacheMode) @@ -553,9 +553,9 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryCache(string request) + private async Task QueryCache(string request) { - BaseWebResult results; + WebClientStringResult results; // Create Directory if not exist System.IO.Directory.CreateDirectory(Directory); @@ -590,7 +590,7 @@ namespace Jackett.Common.Indexers /// /// URL created by Query Builder /// Results from query - private async Task QueryTracker(string request) + private async Task QueryTracker(string request) { // Cache mode not enabled or cached file didn't exist for our query Output("\nQuerying tracker for results...."); diff --git a/src/Jackett.Common/Indexers/Partis.cs b/src/Jackett.Common/Indexers/Partis.cs index 1321035c5..77deed4c4 100644 --- a/src/Jackett.Common/Indexers/Partis.cs +++ b/src/Jackett.Common/Indexers/Partis.cs @@ -116,7 +116,7 @@ namespace Jackett.Common.Indexers var releases = new List(); //List of releases initialization var searchString = query.GetQueryString(); //get search string from query - BaseWebResult results = null; + WebClientStringResult results = null; var queryCollection = new NameValueCollection(); var catList = MapTorznabCapsToTrackers(query); // map categories from query to indexer specific var categ = string.Join(",", catList); diff --git a/src/Jackett.Common/Indexers/SceneTime.cs b/src/Jackett.Common/Indexers/SceneTime.cs index 6e87c9b84..7136d4723 100644 --- a/src/Jackett.Common/Indexers/SceneTime.cs +++ b/src/Jackett.Common/Indexers/SceneTime.cs @@ -104,7 +104,7 @@ namespace Jackett.Common.Indexers public override async Task GetConfigurationForSetup() { - BaseWebResult loginPage; + WebClientStringResult loginPage; try { loginPage = await RequestStringWithCookies(StartPageUrl, string.Empty); diff --git a/src/Jackett.Common/Indexers/Shazbat.cs b/src/Jackett.Common/Indexers/Shazbat.cs index 4f1895ae3..363b269a2 100644 --- a/src/Jackett.Common/Indexers/Shazbat.cs +++ b/src/Jackett.Common/Indexers/Shazbat.cs @@ -81,7 +81,7 @@ namespace Jackett.Common.Indexers { var releases = new List(); var queryString = query.GetQueryString(); - BaseWebResult results = null; + WebClientStringResult results = null; var searchUrls = new List(); if (!string.IsNullOrWhiteSpace(query.SanitizedSearchTerm)) { @@ -170,7 +170,7 @@ namespace Jackett.Common.Indexers return releases; } - private async Task ReloginIfNecessary(BaseWebResult response) + private async Task ReloginIfNecessary(WebClientStringResult response) { if (response.ContentString.Contains("onclick=\"document.location='logout'\"")) return response; diff --git a/src/Jackett.Common/Indexers/SolidTorrents.cs b/src/Jackett.Common/Indexers/SolidTorrents.cs index ca6e65f9d..e863d161b 100644 --- a/src/Jackett.Common/Indexers/SolidTorrents.cs +++ b/src/Jackett.Common/Indexers/SolidTorrents.cs @@ -76,7 +76,7 @@ namespace Jackett.Common.Indexers return IndexerConfigurationStatus.Completed; } - private JArray CheckResponse(BaseWebResult result) + private JArray CheckResponse(WebClientStringResult result) { try { diff --git a/src/Jackett.Common/Indexers/TVStore.cs b/src/Jackett.Common/Indexers/TVStore.cs index eae5d7a4c..707c531e3 100644 --- a/src/Jackett.Common/Indexers/TVStore.cs +++ b/src/Jackett.Common/Indexers/TVStore.cs @@ -119,7 +119,7 @@ namespace Jackett.Common.Indexers /// Number of the already found torrents.(used for limit) /// The limit to the number of torrents to download /// Current position in parsed results - private async Task> ParseTorrentsAsync(BaseWebResult results, int alreadyFound, int limit, + private async Task> ParseTorrentsAsync(WebClientStringResult results, int alreadyFound, int limit, int previouslyParsedOnPage) { var releases = new List(); diff --git a/src/Jackett.Common/Indexers/TorrenTech.cs b/src/Jackett.Common/Indexers/TorrenTech.cs index 62cb0873e..f78f48247 100644 --- a/src/Jackett.Common/Indexers/TorrenTech.cs +++ b/src/Jackett.Common/Indexers/TorrenTech.cs @@ -76,7 +76,7 @@ namespace Jackett.Common.Indexers var releases = new List(); var searchString = query.GetQueryString(); - BaseWebResult results = null; + WebClientStringResult results = null; var queryCollection = new NameValueCollection { { "act", "search" }, diff --git a/src/Jackett.Common/Utils/Clients/BaseWebResult.cs b/src/Jackett.Common/Utils/Clients/BaseWebResult.cs index fbd43feef..ed171261b 100644 --- a/src/Jackett.Common/Utils/Clients/BaseWebResult.cs +++ b/src/Jackett.Common/Utils/Clients/BaseWebResult.cs @@ -8,7 +8,6 @@ namespace Jackett.Common.Utils.Clients { public abstract class BaseWebResult { - private string _contentString; private Encoding _encoding; public Encoding Encoding @@ -21,8 +20,7 @@ namespace Jackett.Common.Utils.Clients _encoding = Request.Encoding; else if (Headers.ContainsKey("content-type")) { - var charsetRegexMatch = Regex.Match( - Headers["content-type"][0], @"charset=([\w-]+)", RegexOptions.Compiled); + var charsetRegexMatch = Regex.Match(Headers["content-type"][0], @"charset=([\w-]+)", RegexOptions.Compiled); if (charsetRegexMatch.Success) { var charset = charsetRegexMatch.Groups[1].Value; @@ -38,34 +36,19 @@ namespace Jackett.Common.Utils.Clients } _encoding ??= Encoding.UTF8; + return _encoding; } set => _encoding = value; } - public byte[] ContentBytes { get; set; } public HttpStatusCode Status { get; set; } public string Cookies { get; set; } public string RedirectingTo { get; set; } public WebRequest Request { get; set; } - public Dictionary Headers { get; protected set; } = new Dictionary(StringComparer.OrdinalIgnoreCase); - public string ContentString - { - get - { - if (_contentString != null) - return _contentString; - if (ContentBytes == null) - return null; - _contentString = Encoding.GetString(ContentBytes); - return _contentString; - } - set => _contentString = value; - } - public bool IsRedirect => Status == HttpStatusCode.Redirect || Status == HttpStatusCode.RedirectKeepVerb || Status == HttpStatusCode.RedirectMethod || diff --git a/src/Jackett.Common/Utils/Clients/WebByteResult.cs b/src/Jackett.Common/Utils/Clients/WebByteResult.cs index 5c3890b31..350eea264 100644 --- a/src/Jackett.Common/Utils/Clients/WebByteResult.cs +++ b/src/Jackett.Common/Utils/Clients/WebByteResult.cs @@ -2,5 +2,6 @@ namespace Jackett.Common.Utils.Clients { public class WebClientByteResult : BaseWebResult { + public byte[] ContentBytes { get; set; } } } diff --git a/src/Jackett.Common/Utils/Clients/WebClient.cs b/src/Jackett.Common/Utils/Clients/WebClient.cs index c36005dbf..03f1d127f 100644 --- a/src/Jackett.Common/Utils/Clients/WebClient.cs +++ b/src/Jackett.Common/Utils/Clients/WebClient.cs @@ -186,7 +186,7 @@ namespace Jackett.Common.Utils.Clients return; } - public virtual async Task GetBytes(WebRequest request) + public virtual async Task GetBytes(WebRequest request) { logger.Debug(string.Format("WebClient({0}).GetBytes(Url:{1})", ClientType, request.Url)); PrepareRequest(request); @@ -198,7 +198,7 @@ namespace Jackett.Common.Utils.Clients return result; } - public virtual async Task GetString(WebRequest request) + public virtual async Task GetString(WebRequest request) { logger.Debug(string.Format("WebClient({0}).GetString(Url:{1})", ClientType, request.Url)); PrepareRequest(request); @@ -206,7 +206,7 @@ namespace Jackett.Common.Utils.Clients var result = await Run(request); lastRequest = DateTime.Now; result.Request = request; - BaseWebResult stringResult = result; + WebClientStringResult stringResult = result; logger.Debug(string.Format("WebClient({0}): Returning {1} => {2}", ClientType, result.Status, (result.IsRedirect ? result.RedirectingTo + " " : "") + (stringResult.ContentString ?? ""))); diff --git a/src/Jackett.Common/Utils/Clients/WebClientResult.cs b/src/Jackett.Common/Utils/Clients/WebClientResult.cs index 5d0c18a48..b77e8ee08 100644 --- a/src/Jackett.Common/Utils/Clients/WebClientResult.cs +++ b/src/Jackett.Common/Utils/Clients/WebClientResult.cs @@ -2,9 +2,11 @@ namespace Jackett.Common.Utils.Clients { public class WebClientStringResult : BaseWebResult { + public string ContentString { get; set; } + public static implicit operator WebClientStringResult(WebClientByteResult br) => new WebClientStringResult() { - ContentBytes = br.ContentBytes, + ContentString = br.ContentBytes == null ? null : br.Encoding.GetString(br.ContentBytes), Cookies = br.Cookies, Encoding = br.Encoding, Headers = br.Headers, diff --git a/src/Jackett.Test/TestWebClient.cs b/src/Jackett.Test/TestWebClient.cs index 5048ca4d2..381df1a16 100644 --- a/src/Jackett.Test/TestWebClient.cs +++ b/src/Jackett.Test/TestWebClient.cs @@ -11,8 +11,8 @@ namespace Jackett.Test { public class TestWebClient : WebClient { - private readonly Dictionary> byteCallbacks = new Dictionary>(); - private readonly Dictionary> stringCallbacks = new Dictionary>(); + private readonly Dictionary> byteCallbacks = new Dictionary>(); + private readonly Dictionary> stringCallbacks = new Dictionary>(); public TestWebClient(IProcessService p, Logger l, IConfigurationService c, ServerConfig sc) : base(p: p, @@ -26,9 +26,9 @@ namespace Jackett.Test public void RegisterStringCall(WebRequest req, Func f) => stringCallbacks.Add(req, f); - public override Task GetBytes(WebRequest request) => Task.FromResult(byteCallbacks.Where(r => r.Key.Equals(request)).First().Value.Invoke(request)); + public override Task GetBytes(WebRequest request) => Task.FromResult(byteCallbacks.Where(r => r.Key.Equals(request)).First().Value.Invoke(request)); - public override Task GetString(WebRequest request) => Task.FromResult(stringCallbacks.Where(r => r.Key.Equals(request)).First().Value.Invoke(request)); + public override Task GetString(WebRequest request) => Task.FromResult(stringCallbacks.Where(r => r.Key.Equals(request)).First().Value.Invoke(request)); public override void Init() {