/// <summary> /// Invokes <c>index.php</c> call with <c>action=ajax</c> query. /// </summary> /// <param name="request">The request message.</param> /// <param name="responseParser">The parser used to parse the response.</param> /// <param name="cancellationToken">The token used to cancel the operation.</param> /// <returns>The parsed JSON root of response.</returns> /// <exception cref="ArgumentNullException">Either <paramref name="request"/> or <paramref name="responseParser"/> is <c>null</c>.</exception> /// <remarks>This method will automatically add <c>action=ajax</c> field in the request.</remarks> public async Task <T> InvokeWikiaAjaxAsync <T>(WikiRequestMessage request, IWikiResponseMessageParser <T> responseParser, CancellationToken cancellationToken) { if (request == null) { throw new ArgumentNullException(nameof(request)); } if (responseParser == null) { throw new ArgumentNullException(nameof(responseParser)); } var localRequest = request; if (request is WikiaQueryRequestMessage queryRequest) { var fields = new List <KeyValuePair <string, object> >(queryRequest.Fields.Count + 1) { new KeyValuePair <string, object>("action", "ajax") }; fields.AddRange(queryRequest.Fields); localRequest = new WikiaQueryRequestMessage(request.Id, fields, queryRequest.UseHttpPost); } Logger.LogDebug("Invoking Wikia Ajax: {Request}", localRequest); var result = await WikiClient.InvokeAsync(Options.ScriptUrl, localRequest, responseParser, cancellationToken); return(result); }
/// <inheritdoc /> /// <remarks> /// To logout the user, this override sends a POST request to <c>https://www.wikia.com/logout</c>. /// </remarks> protected override async Task SendLogoutRequestAsync() { string logoutUrl; if (SiteInfo.ServerUrl.EndsWith(".wikia.com", StringComparison.OrdinalIgnoreCase)) { logoutUrl = "https://www.wikia.com/logout"; } else if (SiteInfo.ServerUrl.EndsWith(".wikia.org", StringComparison.OrdinalIgnoreCase)) { logoutUrl = "https://www.wikia.org/logout"; } else if (SiteInfo.ServerUrl.EndsWith(".fandom.com", StringComparison.OrdinalIgnoreCase)) { logoutUrl = "https://www.fandom.com/logout"; } else { logoutUrl = MediaWikiHelper.MakeAbsoluteUrl(SiteInfo.ServerUrl, "logout"); // User is using WikiaSite instance outside Wikia… I wish you good luck. this.Logger.LogWarning("WikiaSite is instantiated with a non-FANDOM site URL: {Url}. Assuming logout URL as {LogoutUrl}.", SiteInfo.ServerUrl, logoutUrl); } await WikiClient.InvokeAsync(logoutUrl, new MediaWikiFormRequestMessage(new { redirect = "" }), DiscardingResponseMessageParser.Instance, CancellationToken.None); }
/// <summary> /// Invokes Wikia API v1 call. /// </summary> /// <param name="relativeUri">The URI relative to <see cref="WikiaSiteOptions.WikiaApiRootUrl"/>. It often starts with a slash.</param> /// <param name="request">The request message.</param> /// <param name="responseParser">The parser used to parse the response.</param> /// <param name="cancellationToken">The token used to cancel the operation.</param> /// <exception cref="ArgumentNullException">Either <paramref name="request"/> or <paramref name="responseParser"/> is <c>null</c>.</exception> /// <returns>The parsed JSON root of response.</returns> public async Task <T> InvokeWikiaApiAsync <T>(string relativeUri, WikiRequestMessage request, IWikiResponseMessageParser <T> responseParser, CancellationToken cancellationToken) { Logger.LogDebug("Invoking Wikia API v1: {Request}", request); var result = await WikiClient.InvokeAsync(Options.WikiaApiRootUrl + relativeUri, request, responseParser, cancellationToken); return(result); }
/// <summary> /// Invokes nirvana API call. /// </summary> /// <param name="request">The request message.</param> /// <param name="responseParser">The parser used to parse the response.</param> /// <param name="cancellationToken">The token used to cancel the operation.</param> /// <exception cref="ArgumentNullException">Either <paramref name="request"/> or <paramref name="responseParser"/> is <c>null</c>.</exception> /// <returns>The parsed JSON root of response.</returns> /// <seealso cref="WikiaSiteOptions.NirvanaEndPointUrl"/> public async Task <T> InvokeNirvanaAsync <T>(WikiRequestMessage request, IWikiResponseMessageParser <T> responseParser, CancellationToken cancellationToken) { Logger.LogDebug("Invoking Nirvana API: {Request}", request); var result = await WikiClient.InvokeAsync(Options.NirvanaEndPointUrl, request, responseParser, cancellationToken); return(result); }
/// <summary> /// Invokes MediaWiki API and gets JSON result. /// </summary> /// <param name="message">The request message.</param> /// <param name="responseParser">The parser that checks and parses the API response into <see cref="JToken"/>.</param> /// <param name="suppressAccountAssertion">Whether to temporarily disable account assertion as set in <see cref="SiteOptions.AccountAssertion"/>.</param> /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned task.</param> /// <exception cref="InvalidActionException">Specified action is not supported.</exception> /// <exception cref="OperationFailedException">There is "error" node in returned JSON. Instances of derived types may be thrown.</exception> /// <exception cref="AccountAssertionFailureException">You enabled account assertion, the assertion failed, and it also failed to retry logging in.</exception> /// <returns>A task that returns the JSON response when completed.</returns> /// <remarks> /// Some enhancements are available only if <paramref name="message"/> is <see cref="MediaWikiFormRequestMessage"/>, including /// <list type="bullet"> /// <item><description> /// Account assertion, as specified in <see cref="SiteOptions.AccountAssertion"/>. /// </description></item> /// <item><description> /// Automatic token-refreshing on <c>badtoken</c> error. This requires you to set all your <c>token</c> /// fields in the <paramref name="message"/> to a placeholder of type <see cref="WikiSiteToken"/>, /// instead of the actual token string. /// </description></item> /// </list> /// </remarks> public async Task <T> InvokeMediaWikiApiAsync <T>(WikiRequestMessage message, IWikiResponseMessageParser <T> responseParser, bool suppressAccountAssertion, CancellationToken cancellationToken) { if (message == null) { throw new ArgumentNullException(nameof(message)); } if (responseParser == null) { throw new ArgumentNullException(nameof(responseParser)); } var form = message as MediaWikiFormRequestMessage; var localRequest = message; var badTokenRetries = 0; RETRY: if (form != null) { // Apply tokens var newFields = new List <KeyValuePair <string, object> >(form.Fields.Count + 3) { new KeyValuePair <string, object>("format", "json") }; foreach (var tokenField in form.Fields) { var value = tokenField.Value; if (value is WikiSiteToken) { value = await tokensManager.GetTokenAsync( ((WikiSiteToken)tokenField.Value).Type, false, cancellationToken); } newFields.Add(new KeyValuePair <string, object>(tokenField.Key, value)); } // Apply account assertions if (!suppressAccountAssertion && _AccountInfo != null) { if ((options.AccountAssertion & AccountAssertionBehavior.AssertBot) == AccountAssertionBehavior.AssertBot && _AccountInfo.IsBot) { newFields.Add(new KeyValuePair <string, object>("assert", "bot")); } else if ((options.AccountAssertion & AccountAssertionBehavior.AssertUser) == AccountAssertionBehavior.AssertUser && _AccountInfo.IsUser) { newFields.Add(new KeyValuePair <string, object>("assert", "user")); } } localRequest = new MediaWikiFormRequestMessage(form.Id, newFields, form.AsMultipartFormData); } Logger.LogDebug("Sending request {Request}, SuppressAccountAssertion={SuppressAccountAssertion}", localRequest, suppressAccountAssertion); try { return(await WikiClient.InvokeAsync(options.ApiEndpoint, localRequest, responseParser, cancellationToken)); } catch (AccountAssertionFailureException) { if (AccountAssertionFailureHandler != null) { // ISSUE Relogin might be called multiple times. if (reLoginTask == null) { Logger.LogWarning("Account assertion failed. Try to relogin."); Volatile.Write(ref reLoginTask, Relogin()); } else { Logger.LogWarning("Account assertion failed. Waiting for relongin."); } var result = await reLoginTask; if (result) { goto RETRY; } } throw; } catch (BadTokenException) { // Allows retrying once. if (form == null || badTokenRetries >= 1) { throw; } string invalidatedToken = null; foreach (var tokenField in form.Fields.Where(p => p.Value is WikiSiteToken)) { invalidatedToken = ((WikiSiteToken)tokenField.Value).Type; tokensManager.ClearCache(invalidatedToken); } if (invalidatedToken == null) { throw; } Logger.LogWarning("BadTokenException: {Request}. Will retry after invalidating the token: {Token}.", message, invalidatedToken); badTokenRetries++; goto RETRY; } }