Exemple #1
0
        /// <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);
        }
Exemple #2
0
        /// <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);
        }
Exemple #3
0
        /// <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);
        }
Exemple #4
0
        /// <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);
        }
Exemple #5
0
        /// <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;
            }
        }