Esempio n. 1
0
        /// <summary>
        /// Create a wiki site, login if necessary.
        /// </summary>
        private async Task <WikiSite> CreateWikiSiteAsync(IWikiClient wikiClient, string url)
        {
            WikiSite site;

            if (url.Contains(".wikia.com"))
            {
                var uri     = new Uri(url, UriKind.Absolute);
                var options = new WikiaSiteOptions(uri.GetLeftPart(UriPartial.Authority) + "/")
                {
                    AccountAssertion = AccountAssertionBehavior.AssertAll,
                };
                site = new WikiaSite(wikiClient, options)
                {
                    Logger = OutputLoggerFactory.CreateLogger <WikiaSite>()
                };
            }
            else
            {
                var options = new SiteOptions(url)
                {
                    AccountAssertion = AccountAssertionBehavior.AssertAll,
                };
                site = new WikiSite(wikiClient, options)
                {
                    Logger = OutputLoggerFactory.CreateLogger <WikiSite>()
                };
            }
            await site.Initialization;

            if (sitesNeedsLogin.Contains(url))
            {
                await CredentialManager.LoginAsync(site);
            }
            return(site);
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes a new instance of <see cref="Board"/> from site and page title.
        /// </summary>
        /// <param name="site">The Wikia site.</param>
        /// <param name="title">Full page title of the board.</param>
        /// <param name="defaultNamespaceId">The default namespace ID to be used for the <paramref name="title"/>.</param>
        /// <exception cref="ArgumentNullException"><paramref name="site"/> or <paramref name="title"/> is <c>null</c>.</exception>
        public Board(WikiaSite site, string title, int defaultNamespaceId)
        {
            Site = site ?? throw new ArgumentNullException(nameof(site));
            var link = WikiLink.Parse(site, title, defaultNamespaceId);

            Page = new WikiPageStub(link.FullTitle, link.Namespace.Id);
        }
Esempio n. 3
0
        public static async Task <Post> PostCommentAsync(WikiaSite site, object scopeInst, WikiPageStub owner, int?parentId, string content, CancellationToken cancellationToken)
        {
            Debug.Assert(site != null);
            Debug.Assert(owner.HasTitle);
            using (site.BeginActionScope(scopeInst, owner, parentId))
            {
                var jresult = await site.InvokeWikiaAjaxAsync(new WikiaQueryRequestMessage(new
                {
                    article = owner.Id,
                    rs = "ArticleCommentsAjax",
                    method = "axPost",
                    token = await site.GetTokenAsync("edit", cancellationToken),
                    convertToFormat = "",
                    parentId = parentId,
                    wpArticleComment = content,
                }, true), WikiaJsonResponseParser.Default, cancellationToken);

                if (((int?)jresult["error"] ?? 0) != 0)
                {
                    throw new OperationFailedException((string)jresult["msg"]);
                }
                var text = (string)jresult["text"];
                var doc  = new HtmlDocument();
                doc.LoadHtml(text);
                var node = doc.DocumentNode.SelectSingleNode("li");
                if (node == null)
                {
                    throw new UnexpectedDataException("Cannot locate the text node in the Wikia API response.");
                }
                return(Post.FromHtmlNode(site, owner, node));
            }
        }
Esempio n. 4
0
        internal static Post FromHtmlNode(WikiaSite site, WikiPageStub owner, HtmlNode listItem)
        {
            Debug.Assert(listItem.Name == "li");
            var id = listItem.GetAttributeValue("data-id", 0);

            if (id > 0)
            {
            }
            if (listItem.Id.StartsWith("comm-"))
            {
                id = Convert.ToInt32(listItem.Id.Substring(5));
            }
            else
            {
                var sep = listItem.Id.LastIndexOf('-');
                if (sep >= 0)
                {
                    id = Convert.ToInt32(listItem.Id.Substring(sep + 1));
                }
            }
            if (id == 0)
            {
                throw new UnexpectedDataException($"Cannot infer comment ID from <li> node. @id={listItem.Id}.");
            }
            return(new Post(site, owner, id));
        }
Esempio n. 5
0
 /// <summary>
 /// Initializes a new instance of <see cref="Post"/>.
 /// </summary>
 /// <param name="site">The Wikia site.</param>
 /// <param name="ownerPage">Stub of the page/board that owns the post.</param>
 /// <param name="id">ID of the post.</param>
 /// <exception cref="ArgumentNullException"><paramref name="site"/> is <c>null</c>.</exception>
 /// <exception cref="ArgumentException"><paramref name="ownerPage"/>.<see cref="WikiPageStub.IsEmpty"/> is <c>true</c>.</exception>
 /// <remarks>
 /// For now, it is not possible to get the replies by using the constructor provided here.
 /// To achieve this, you need to invoke <see cref="Board.EnumPostsAsync()"/> on a <see cref="Board"/> instance.
 /// </remarks>
 public Post(WikiaSite site, WikiPageStub ownerPage, int id)
 {
     if (ownerPage.IsEmpty)
     {
         throw new ArgumentException("ownerPage is empty.", nameof(ownerPage));
     }
     Site      = site ?? throw new ArgumentNullException(nameof(site));
     OwnerPage = ownerPage;
     Id        = id;
 }
Esempio n. 6
0
        internal static Post FromHtmlNode(WikiaSite site, WikiPageStub owner, HtmlNode listItem)
        {
            Debug.Assert(listItem.Name == "li");
            var id = listItem.GetAttributeValue("data-id", 0);

            if (id > 0)
            {
            }
            if (listItem.Id.StartsWith("comm-"))
            {
                id = Convert.ToInt32(listItem.Id[5..]);
Esempio n. 7
0
 public static async Task <Post> PostWallMessageAsync(WikiaSite site, object scopeInst, WikiPageStub owner,
                                                      string messageTitle, string messageBody, IEnumerable <string> relatedPages, CancellationToken cancellationToken)
 {
     Debug.Assert(site != null);
     Debug.Assert(owner.HasTitle);
     using (site.BeginActionScope(scopeInst, owner))
     {
         var tokenPurged     = false;
         var pageTitle       = owner.Title;
         var pageNamespaceId = owner.NamespaceId;
         if (pageTitle.StartsWith("Message Wall:", StringComparison.OrdinalIgnoreCase))
         {
             pageTitle = pageTitle[13..];
Esempio n. 8
0
        public static async Task <Post> ReplyWallMessageAsync(WikiaSite site, object scopeInst, WikiPageStub owner,
                                                              int parentId, string messageBody, CancellationToken cancellationToken)
        {
            Debug.Assert(site != null);
            using (site.BeginActionScope(scopeInst, owner, parentId))
            {
                var tokenPurged = false;
BEGIN:
                var jresult = await site.InvokeNirvanaAsync(new WikiaQueryRequestMessage(new
                {
                    controller = "WallExternal",
                    method = "replyToMessage",
                    format = "json",
                    token = await site.GetTokenAsync("edit", cancellationToken),
                    pagenamespace = WikiaNamespaces.Thread,
                    pagetitle = parentId,
                    parent = parentId,
                    body = messageBody,
                    convertToFormat = "",
                }, true), WikiaJsonResonseParser.Default, cancellationToken);

                if (!string.Equals((string)jresult["status"], "True", StringComparison.OrdinalIgnoreCase))
                {
                    var errorMessage = (string)jresult["errormsg"];
                    if (errorMessage != null)
                    {
                        if (!tokenPurged)
                        {
                            if (errorMessage.IndexOf("There seems to be a problem with your login session", StringComparison.OrdinalIgnoreCase) >= 0)
                            {
                                await site.GetTokenAsync("edit", true, cancellationToken);

                                tokenPurged = true;
                                goto BEGIN;
                            }
                        }
                    }
                    errorMessage = "Status code indicates a failure: " + (string)jresult["status"];
                    throw new OperationFailedException(errorMessage);
                }
                var text = (string)jresult["message"];
                var doc  = new HtmlDocument();
                doc.LoadHtml(text);
                var node = doc.DocumentNode.SelectSingleNode("li");
                if (node == null)
                {
                    throw new UnexpectedDataException("Cannot locate the comment text node in the Wikia API response.");
                }
                return(Post.FromHtmlNode(site, owner, node));
            }
        }
Esempio n. 9
0
 /// <summary>
 /// Asynchronously fetches the specified users' information.
 /// </summary>
 /// <param name="site">The site to issue the request.</param>
 /// <param name="userNames">The user names to be fetched.</param>
 /// <exception cref="ArgumentNullException">Either <paramref name="site"/> or <paramref name="userNames"/> is <c>null</c>.</exception>
 /// <returns>
 /// An asynchronous sequence containing the detailed user information.
 /// The user names are normalized by the server. Inexistent user names are skipped.
 /// </returns>
 public static async IAsyncEnumerable <UserInfo> FetchUsersAsync(this WikiaSite site, IEnumerable <string> userNames,
                                                                 [EnumeratorCancellation] CancellationToken cancellationToken = default)
 {
     if (site == null)
     {
         throw new ArgumentNullException(nameof(site));
     }
     if (userNames == null)
     {
         throw new ArgumentNullException(nameof(userNames));
     }
     using (site.BeginActionScope(null, (object)(userNames as ICollection)))
     {
         foreach (var names in userNames.Partition(100))
         {
             JToken jresult;
             try
             {
                 jresult = await site.InvokeWikiaApiAsync("/User/Details",
                                                          new WikiaQueryRequestMessage(new { ids = string.Join(", ", names) }), cancellationToken);
             }
             catch (WikiaApiException ex) when(ex.ErrorType == "NotFoundApiException")
             {
                 // All the usesers in this batch are not found.
                 // Pity.
                 continue;
             }
             var basePath = (string)jresult["basepath"];
             var users    = jresult["items"].ToObject <ICollection <UserInfo> >();
             if (basePath != null)
             {
                 foreach (var user in users)
                 {
                     user.ApplyBasePath(basePath);
                 }
             }
             using (ExecutionContextStash.Capture())
                 foreach (var user in users)
                 {
                     yield return(user);
                 }
         }
     }
 }
Esempio n. 10
0
 /// <summary>
 /// Asynchronously fetches the specified users' information.
 /// </summary>
 /// <param name="site">The site to issue the request.</param>
 /// <param name="userNames">The user names to be fetched.</param>
 /// <exception cref="ArgumentNullException">Either <paramref name="site"/> or <paramref name="userNames"/> is <c>null</c>.</exception>
 /// <returns>
 /// An asynchronous sequence containing the detailed user information.
 /// The user names are normalized by the server. Inexistent user names are skipped.
 /// </returns>
 public static IAsyncEnumerable <UserInfo> FetchUsersAsync(this WikiaSite site, IEnumerable <string> userNames)
 {
     if (site == null)
     {
         throw new ArgumentNullException(nameof(site));
     }
     if (userNames == null)
     {
         throw new ArgumentNullException(nameof(userNames));
     }
     return(AsyncEnumerableFactory.FromAsyncGenerator <UserInfo>(async(sink, ct) =>
     {
         using (site.BeginActionScope(null, (object)(userNames as ICollection)))
         {
             foreach (var names in userNames.Partition(100))
             {
                 JToken jresult;
                 try
                 {
                     jresult = await site.InvokeWikiaApiAsync("/User/Details",
                                                              new WikiaQueryRequestMessage(new { ids = string.Join(", ", names) }), ct);
                 }
                 catch (WikiaApiException ex) when(ex.ErrorType == "NotFoundApiException")
                 {
                     // All the usesers in this batch are not found.
                     // Pity.
                     continue;
                 }
                 var basePath = (string)jresult["basepath"];
                 var users = jresult["items"].ToObject <ICollection <UserInfo> >();
                 if (basePath != null)
                 {
                     foreach (var user in users)
                     {
                         user.ApplyBasePath(basePath);
                     }
                 }
                 await sink.YieldAndWait(users);
             }
         }
     }));
 }
Esempio n. 11
0
 /// <summary>
 /// Asynchronously fetches the specified user's information.
 /// </summary>
 /// <param name="site">The site to issue the request.</param>
 /// <param name="userName">The user name to be fetched.</param>
 /// <param name="cancellationToken">A token used to cancel the request.</param>
 /// <exception cref="ArgumentNullException">Either <paramref name="site"/> or <paramref name="userName"/> is <c>null</c>.</exception>
 /// <returns>A task that returns the requested user information, or <c>null</c> for inexistent user.</returns>
 public static async Task <UserInfo> FetchUserAsync(this WikiaSite site,
                                                    string userName, CancellationToken cancellationToken)
 {
     if (site == null)
     {
         throw new ArgumentNullException(nameof(site));
     }
     if (userName == null)
     {
         throw new ArgumentNullException(nameof(userName));
     }
     if (userName.Contains(','))
     {
         throw new ArgumentException("User name cannot contain comma (,).", nameof(userName));
     }
     using (site.BeginActionScope(null, (object)userName))
     {
         JToken jresult;
         try
         {
             jresult = await site.InvokeWikiaApiAsync("/User/Details",
                                                      new WikiaQueryRequestMessage(new { ids = userName }), cancellationToken);
         }
         catch (NotFoundApiException)
         {
             return(null);
         }
         var user = jresult["items"][0].ToObject <UserInfo>();
         if (user == null)
         {
             return(null);
         }
         var basePath = (string)jresult["basepath"];
         if (basePath != null)
         {
             user.ApplyBasePath(basePath);
         }
         return(user);
     }
 }
Esempio n. 12
0
        /// <summary>
        /// Asynchronously fetches the specified page's related pages.
        /// </summary>
        /// <param name="site">The site to issue the request.</param>
        /// <param name="pageId">ID of the page to find the related ones.</param>
        /// <param name="maxCount">Maximum count of the returned items.</param>
        /// <param name="cancellationToken">A token used to cancel the operation.</param>
        /// <exception cref="ArgumentNullException"><paramref name="site"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="pageId"/> is less than or equals to 0.</exception>
        /// <exception cref="NotFoundApiException"><c>Related Pages</c> extension is not available.</exception>
        /// <returns></returns>
        public static async Task <IList <RelatedPageItem> > FetchRelatedPagesAsync(this WikiaSite site,
                                                                                   int pageId, int maxCount, CancellationToken cancellationToken)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (maxCount <= 0)
            {
                throw new ArgumentOutOfRangeException(nameof(maxCount));
            }
            using (site.BeginActionScope(null, pageId, maxCount))
            {
                var jresult = await site.InvokeWikiaApiAsync("/RelatedPages/List",
                                                             new WikiaQueryRequestMessage(new { ids = pageId, limit = maxCount }),
                                                             cancellationToken);

                var jitems = jresult["items"][pageId.ToString(CultureInfo.InvariantCulture)];
                if (jitems == null)
                {
                    jitems = ((JProperty)jresult["items"].First)?.Value;
                }
                if (jitems == null || !jitems.HasValues)
                {
                    return(Array.Empty <RelatedPageItem>());
                }
                var items    = jitems.ToObject <IList <RelatedPageItem> >();
                var basePath = (string)jresult["basepath"];
                if (basePath != null)
                {
                    foreach (var i in items)
                    {
                        i.ApplyBasePath(basePath);
                    }
                }
                return(items);
            }
        }
Esempio n. 13
0
        /// <summary>
        /// Create a wiki site, login if necessary.
        /// </summary>
        private async Task <WikiSite> CreateWikiSiteAsync(IWikiClient wikiClient, string url)
        {
            WikiSite site;

            if (url.Contains(".wikia.com") || url.Contains(".wikia.org") || url.Contains(".fandom.com"))
            {
                var uri     = new Uri(url, UriKind.Absolute);
                var rootUrl = new Uri(uri, ".").ToString();
                var options = new WikiaSiteOptions(rootUrl)
                {
                    AccountAssertion = AccountAssertionBehavior.AssertAll,
                };
                site = new WikiaSite(wikiClient, options)
                {
                    Logger = OutputLoggerFactory.CreateLogger <WikiaSite>()
                };
            }
            else
            {
                var options = new SiteOptions(url)
                {
                    AccountAssertion = AccountAssertionBehavior.AssertAll,
                };
                site = new WikiSite(wikiClient, options)
                {
                    Logger = OutputLoggerFactory.CreateLogger <WikiSite>()
                };
            }
            await site.Initialization;

            if (sitesNeedsLogin.Contains(url))
            {
                await CredentialManager.LoginAsync(site);
            }
            return(site);
        }
Esempio n. 14
0
 /// <inheritdoc cref="Board(WikiaSite,string,int)"/>
 public Board(WikiaSite site, string title) : this(site, title, BuiltInNamespaces.Main)
 {
 }
Esempio n. 15
0
 /// <inheritdoc cref="FetchUserAsync(WikiaSite,string,CancellationToken)"/>
 public static Task <UserInfo> FetchUserAsync(this WikiaSite site, string userName)
 {
     return(FetchUserAsync(site, userName, CancellationToken.None));
 }
Esempio n. 16
0
 /// <inheritdoc cref="FetchRelatedPagesAsync(WikiaSite,int,int,CancellationToken)"/>
 public static Task <IList <RelatedPageItem> > FetchRelatedPagesAsync(this WikiaSite site, int pageId, int maxCount)
 {
     return(FetchRelatedPagesAsync(site, pageId, maxCount, CancellationToken.None));
 }
 /// <summary>
 /// Initializes a new instance of <see cref="LocalWikiSearchList"/> using the target
 /// Wikia site.
 /// </summary>
 /// <inheritdoc cref="LocalWikiSearchList(WikiaSite,string)"/>
 public LocalWikiSearchList(WikiaSite site) : this(site, null)
 {
 }
 /// <summary>
 /// Initializes a new instance of <see cref="LocalWikiSearchList"/> using the target
 /// Wikia site and search keyword.
 /// </summary>
 /// <param name="site">The Wikia site this list-like object is applied to.</param>
 /// <param name="keyword">Search for all page titles (or content) that have this value.</param>
 public LocalWikiSearchList(WikiaSite site, string keyword)
 {
     Site    = site ?? throw new ArgumentNullException(nameof(site));
     Keyword = keyword;
 }
Esempio n. 19
0
 /// <summary>
 /// Initializes a new instance of <see cref="Board"/> from site and page ID.
 /// </summary>
 /// <param name="site">The Wikia site.</param>
 /// <param name="pageId">Page ID of the board.</param>
 /// <exception cref="ArgumentNullException"><paramref name="site"/> is <c>null</c>.</exception>
 public Board(WikiaSite site, int pageId)
 {
     Site = site ?? throw new ArgumentNullException(nameof(site));
     Page = new WikiPageStub(pageId);
 }
Esempio n. 20
0
        public static async Task <Post> PostWallMessageAsync(WikiaSite site, object scopeInst, WikiPageStub owner,
                                                             string messageTitle, string messageBody, IEnumerable <string> relatedPages, CancellationToken cancellationToken)
        {
            Debug.Assert(site != null);
            Debug.Assert(owner.HasTitle);
            using (site.BeginActionScope(scopeInst, owner))
            {
                var tokenPurged     = false;
                var pageTitle       = owner.Title;
                var pageNamespaceId = owner.NamespaceId;
                if (pageTitle.StartsWith("Message Wall:", StringComparison.OrdinalIgnoreCase))
                {
                    pageTitle = pageTitle.Substring(13);
                    if (!owner.HasNamespaceId)
                    {
                        pageNamespaceId = WikiaNamespaces.MessageWall;
                    }
                }
                else if (pageTitle.StartsWith("Board:", StringComparison.OrdinalIgnoreCase))
                {
                    pageTitle = pageTitle.Substring(6);
                    if (!owner.HasNamespaceId)
                    {
                        pageNamespaceId = WikiaNamespaces.Thread;
                    }
                }
                else
                {
                    var link = WikiLink.Parse(site, owner.Title);
                    pageTitle       = link.Title;
                    pageNamespaceId = link.Namespace.Id;
                }
                var queryParams = new OrderedKeyValuePairs <string, object>
                {
                    { "token", null },
                    { "controller", "WallExternal" },
                    { "method", "postNewMessage" },
                    { "format", "json" },
                    { "pagenamespace", pageNamespaceId },
                    { "pagetitle", pageTitle },
                    { "messagetitle", messageTitle },
                    { "body", messageBody },
                    { "notifyeveryone", 0 },
                    { "convertToFormat", "" },
                };
                if (relatedPages != null)
                {
                    foreach (var title in relatedPages)
                    {
                        queryParams.Add("relatedTopics[]", title);
                    }
                }
BEGIN:
                queryParams["token"] = await site.GetTokenAsync("edit", cancellationToken);

                var jresult = await site.InvokeNirvanaAsync(new WikiaQueryRequestMessage(queryParams, true), WikiaJsonResonseParser.Default, cancellationToken);

                if (!string.Equals((string)jresult["status"], "True", StringComparison.OrdinalIgnoreCase))
                {
                    var errorMessage = (string)jresult["errormsg"];
                    if (errorMessage != null)
                    {
                        if (!tokenPurged)
                        {
                            if (errorMessage.IndexOf("There seems to be a problem with your login session", StringComparison.OrdinalIgnoreCase) >= 0)
                            {
                                await site.GetTokenAsync("edit", true, cancellationToken);

                                tokenPurged = true;
                                goto BEGIN;
                            }
                        }
                    }
                    errorMessage = "Status code indicates a failure: " + (string)jresult["status"];
                    throw new OperationFailedException(errorMessage);
                }
                var text = (string)jresult["message"];
                var doc  = new HtmlDocument();
                doc.LoadHtml(text);
                var node = doc.DocumentNode.SelectSingleNode("li");
                if (node == null)
                {
                    throw new UnexpectedDataException("Cannot locate the comment text node in the Wikia API response.");
                }
                return(Post.FromHtmlNode(site, owner, node));
            }
        }
Esempio n. 21
0
 public async Task Issue39()
 {
     // Cause: cacheBuster=7030077030012 in /api/v1/Mercury/WikiVariables request exceeds Int32 limit.
     var site = new WikiaSite(WikiClient, "https://theedgechronicles.fandom.com/");
     await site.Initialization;
 }