/// <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); }
/// <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; } }
/// <inheritdoc cref="InvokeMediaWikiApiAsync{T}(WikiRequestMessage,IWikiResponseMessageParser{T},bool,CancellationToken)"/> /// <remarks>This overload uses <see cref="MediaWikiJsonResponseParser.Default"/> as response parser.</remarks> public Task <JToken> InvokeMediaWikiApiAsync(WikiRequestMessage message, bool suppressAccountAssertion, CancellationToken cancellationToken) { return(InvokeMediaWikiApiAsync(message, MediaWikiJsonResponseParser.Default, suppressAccountAssertion, cancellationToken)); }
/// <inheritdoc cref="InvokeMediaWikiApiAsync{T}(WikiRequestMessage,IWikiResponseMessageParser{T},bool,CancellationToken)"/> /// <remarks>This overload uses <see cref="MediaWikiJsonResponseParser.Default"/> as response parser.</remarks> public Task <JToken> InvokeMediaWikiApiAsync(WikiRequestMessage message, CancellationToken cancellationToken) { return(InvokeMediaWikiApiAsync(message, MediaWikiJsonResponseParser.Default, false, cancellationToken)); }
/// <inheritdoc cref="InvokeWikiaAjaxAsync{T}(WikiRequestMessage,IWikiResponseMessageParser{T},CancellationToken)"/> /// <remarks> /// <para>This overload uses <see cref="WikiaJsonResponseParser"/> to parse the response.</para> /// <para>This method will automatically add <c>action=ajax</c> field in the request.</para> /// </remarks> public async Task <JToken> InvokeWikiaAjaxAsync(WikiRequestMessage request, CancellationToken cancellationToken) { return(await InvokeWikiaAjaxAsync(request, WikiaJsonResponseParser.Default, cancellationToken)); }
/// <inheritdoc cref="InvokeWikiaApiAsync{T}(string,WikiRequestMessage,IWikiResponseMessageParser{T},CancellationToken)"/> /// <remarks>This overload uses <see cref="WikiaJsonResponseParser"/> to parse the response.</remarks> public Task <JToken> InvokeWikiaApiAsync(string relativeUri, WikiRequestMessage request, CancellationToken cancellationToken) { return(InvokeWikiaApiAsync(relativeUri, request, WikiaJsonResponseParser.Default, cancellationToken)); }
/// <inheritdoc cref="InvokeNirvanaAsync{T}(WikiRequestMessage,IWikiResponseMessageParser{T},CancellationToken)"/> /// <remarks>This overload uses <see cref="WikiaJsonResponseParser"/> to parse the response.</remarks> public Task <JToken> InvokeNirvanaAsync(WikiRequestMessage request, CancellationToken cancellationToken) { return(InvokeNirvanaAsync(request, WikiaJsonResponseParser.Default, cancellationToken)); }