Beispiel #1
0
        /// <summary>
        /// Given the prefix of a page, asynchronously search for a list of titles for auto completion.
        /// </summary>
        /// <remarks>Do not modify the returned list.</remarks>
        public async Task <IList <OpenSearchResultEntry> > GetAutoCompletionItemsAsync(string expression,
                                                                                       int defaultNamespace = BuiltInNamespaces.Main)
        {
            if (expression == null)
            {
                throw new ArgumentNullException(nameof(expression));
            }
            string normalizedExpression;

            try
            {
                normalizedExpression = WikiLink.NormalizeWikiLink(await GetSiteAsync(), expression);
            }
            catch (ArgumentException)
            {
                normalizedExpression = expression;
            }
            var tp     = Tuple.Create(normalizedExpression, defaultNamespace);
            var cached = _AutoCompletionItemsCache.TryGetValue(tp);

            if (cached != null && DateTime.Now - cached.Item2 < _CacheExpiry)
            {
                return(cached.Item1);
            }
            var site = await GetSiteAsync();

            var entries = await site.OpenSearchAsync(expression, 20, defaultNamespace, OpenSearchOptions.None);

            _AutoCompletionItemsCache[tp] = Tuple.Create(entries, DateTime.Now);
            return(entries);
        }
        /// <summary>
        /// Imports the Lua module with the specified name and evaluates the specified Lua code with it.
        /// </summary>
        /// <typeparam name="T">The expected evaluation return value type.</typeparam>
        /// <param name="site">The MediaWiki site on which to evaluate the module.</param>
        /// <param name="moduleName">Name of the module to be imported, with or without <c>Module:</c> prefix.</param>
        /// <param name="epilog">The Lua code snippet used to return value from the imported module (denoted as <c>p</c> in Lua),
        /// or <c>null</c> to use default epilog (<c>return p</c>).</param>
        /// <param name="serializer">The JsonSerializer used to deserialize the return value from JSON, or <c>null</c> to use default JSON serializer.</param>
        /// <param name="cancellationToken">A token used to cancel the operation.</param>
        /// <returns>The deserialized Lua evaluation result.</returns>
        public static Task <T> ScribuntoLoadDataAsync <T>(this WikiSite site, string moduleName, string?epilog,
                                                          JsonSerializer?serializer, CancellationToken cancellationToken)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (string.IsNullOrEmpty(moduleName))
            {
                throw new ArgumentException(Prompts.ExceptionArgumentNullOrEmpty, nameof(moduleName));
            }
            cancellationToken.ThrowIfCancellationRequested();
            var moduleLink           = WikiLink.Parse(site, moduleName);
            var normalizedModuleName = moduleLink.FullTitle;

            if (string.IsNullOrEmpty(moduleLink.NamespaceName))
            {
                normalizedModuleName = "Module:" + normalizedModuleName;
            }
            if (epilog == null)
            {
                epilog = "return p";
            }
            var sb = new StringBuilder("-- ScribuntoLoadDataAsync\n\n", 64 + normalizedModuleName.Length + epilog.Length);

            sb.Append("local p = require([==[");
            sb.Append(normalizedModuleName);
            sb.Append("]==])\n\n");
            sb.Append(epilog);
            sb.AppendLine();
            return(ScribuntoExecuteLuaAsync <T>(site, sb.ToString(), serializer, cancellationToken));
        }
Beispiel #3
0
        public async Task InterwikiLinkTests()
        {
            // We will not login onto any site…
            var originSite = await Family.GetSiteAsync("test2");

            // With originating WikiSite
            var link = await WikiLink.ParseAsync(originSite, Family, "WikiPedia:SANDBOX");

            AssertWikiLink(link, null, "Wikipedia", "SANDBOX");
            link = await WikiLink.ParseAsync(originSite, Family, "FR___:_ __Wp__ _:  SANDBOX");

            AssertWikiLink(link, "fr", "Wikipédia", "SANDBOX");
            link = await WikiLink.ParseAsync(originSite, Family, "EN:fr:   LZH:Project:SANDBOX");

            AssertWikiLink(link, "lzh", "維基大典", "SANDBOX");
            // We don't have de in WikiFamily, but WP has de in its inter-wiki table.
            // Should works as if we haven't specified Family.
            link = await WikiLink.ParseAsync(originSite, Family, "de:Project:SANDBOX");

            AssertWikiLink(link, "de", null, "Project:SANDBOX");
            // Without originating WikiSite
            await Assert.ThrowsAsync <ArgumentException>(() => WikiLink.ParseAsync(Family, "WikiPedia:SANDBOX"));

            link = await WikiLink.ParseAsync(Family, "FR___:_ __Wp__ _:  SANDBOX");

            AssertWikiLink(link, "fr", "Wikipédia", "SANDBOX");
            link = await WikiLink.ParseAsync(Family, "EN:fr:   LZH:Project:SANDBOX");

            AssertWikiLink(link, "lzh", "維基大典", "SANDBOX");
            await Assert.ThrowsAsync <ArgumentException>(() => WikiLink.ParseAsync(Family, "unk:WikiPedia:SANDBOX"));
        }
Beispiel #4
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);
        }
        /// <summary>
        /// Asynchronously uploads a file in this title.
        /// </summary>
        /// <param name="site"></param>
        /// <param name="title"></param>
        /// <param name="source">Source of the file.</param>
        /// <param name="comment">Comment of the upload, as well as the page content if it doesn't exist.</param>
        /// <param name="ignoreWarnings">Ignore any warnings. This must be set to upload a new version of an existing image.</param>
        /// <param name="watch">Whether to add the file into your watchlist.</param>
        /// <param name="cancellationToken">The cancellation token that will be checked prior to completing the returned task.</param>
        /// <exception cref="UnauthorizedAccessException">You do not have the permission to upload the file.</exception>
        /// <exception cref="OperationFailedException">
        /// There's an general failure while uploading the file.
        /// - or -
        /// Since MW 1.31, if you are uploading the exactly same content to the same title
        /// with <paramref name="ignoreWarnings"/> set to <c>true</c>,
        /// you will reveive this exception with <see cref="OperationFailedException.ErrorCode"/>
        /// set to <c>fileexists-no-change</c>. See https://gerrit.wikimedia.org/r/378702 .
        /// </exception>
        /// <exception cref="TimeoutException">Timeout specified in <see cref="WikiClient.Timeout"/> has been reached.</exception>
        /// <returns>An <see cref="UploadResult"/>. You need to check <see cref="UploadResult.ResultCode"/> for further action.</returns>
        public static async Task <UploadResult> UploadAsync(this WikiSite site, string title, WikiUploadSource source, string comment, bool ignoreWarnings,
                                                            AutoWatchBehavior watch, CancellationToken cancellationToken)
        {
            if (source == null)
            {
                throw new ArgumentNullException(nameof(source));
            }
            Debug.Assert(source != null);
            var link = WikiLink.Parse(site, title, BuiltInNamespaces.File);

            using (site.BeginActionScope(null, title, source))
            {
                var requestFields = new Dictionary <string, object>
                {
                    { "action", "upload" },
                    { "watchlist", watch },
                    { "token", WikiSiteToken.Edit },
                    { "filename", link.Title },
                    { "comment", comment },
                    { "ignorewarnings", ignoreWarnings },
                };
                foreach (var p in source.GetUploadParameters(site.SiteInfo))
                {
                    requestFields[p.Key] = p.Value;
                }
                var request = new MediaWikiFormRequestMessage(requestFields, true);
                site.Logger.LogDebug("Start uploading.");
                var jresult = await site.InvokeMediaWikiApiAsync(request, cancellationToken);

                var result = jresult["upload"].ToObject <UploadResult>(Utility.WikiJsonSerializer);
                site.Logger.LogInformation("Uploaded. Result={Result}.", result.ResultCode);
                return(result);
            }
        }
Beispiel #6
0
        public async Task WikiLinkTest1()
        {
            var WpTestSite = await WpTest2SiteAsync;
            var link1      = WikiLink.Parse(WpTestSite, "____proJEct__talk_:___sandbox_");
            var link2      = WikiLink.Parse(WpTestSite, "__ _pROject_ _talk_:___sandbox_", BuiltInNamespaces.Category);
            var link3      = WikiLink.Parse(WpTestSite, "___sandbox_  test__", BuiltInNamespaces.Category);
            var link4      = WikiLink.Parse(WpTestSite, "__:   sandbox test  ", BuiltInNamespaces.Template);
            var link5      = WikiLink.Parse(WpTestSite, "___lZh__:project:test|", BuiltInNamespaces.Template);

            Assert.Equal("Wikipedia talk:Sandbox", link1.ToString());
            Assert.Equal("Wikipedia talk", link1.NamespaceName);
            Assert.Equal("Sandbox", link1.Title);
            Assert.Equal("Wikipedia talk:Sandbox", link1.Target);
            Assert.Equal("Wikipedia talk:Sandbox", link1.DisplayText);
            Assert.Equal("https://test2.wikipedia.org/wiki/Wikipedia%20talk:Sandbox", link1.TargetUrl);
            Assert.Null(link1.InterwikiPrefix);
            Assert.Null(link1.Section);
            Assert.Null(link1.Anchor);
            Assert.Equal("Wikipedia talk:Sandbox", link2.ToString());
            Assert.Equal("Category:Sandbox test", link3.ToString());
            Assert.Equal("Sandbox test", link4.ToString());
            Assert.Equal("lzh:Project:test|", link5.ToString());
            Assert.Equal("Project:test", link5.DisplayText);
            Assert.Equal("lzh", link5.InterwikiPrefix);
            Assert.Equal("lzh:Project:test", link5.Target);
            Assert.Equal("", link5.Anchor);
            var link6 = WikiLink.Parse(WpTestSite, "sandbox#sect|anchor", BuiltInNamespaces.Template);

            Assert.Equal("Template:Sandbox#sect|anchor", link6.ToString());
            Assert.Equal("Template:Sandbox#sect", link6.Target);
            Assert.Equal("sect", link6.Section);
            Assert.Equal("anchor", link6.Anchor);
            Assert.Equal("anchor", link6.DisplayText);
        }
Beispiel #7
0
        public async Task RunAsync()
        {
            var apg = new AllPagesGenerator(Site)
            {
                NamespaceId    = Site.Namespaces["Item"].Id,
                PaginationSize = 100
            };

            using (var writer = File.CreateText(FileName))
                using (var ie = apg.EnumItemsAsync().Buffer(100).GetEnumerator())
                {
                    while (await ie.MoveNext())
                    {
                        var entities = ie.Current.Select(s => new Entity(Site, WikiLink.Parse(Site, s.Title).Title)).ToList();
                        await entities.RefreshAsync(EntityQueryOptions.FetchLabels, new[]
                        {
                            "en", "zh", "zh-cn", "zh-hans"
                        });

                        foreach (var entity in entities)
                        {
                            writer.Write(entity.Id);
                            writer.Write('\t');
                            writer.Write(entity.Labels["en"]);
                            writer.Write('\t');
                            writer.Write(entity.Labels["zh-cn"] ?? entity.Labels["zh-hans"] ?? entity.Labels["zh"]);
                            writer.WriteLine();
                        }
                    }
                }
        }
Beispiel #8
0
        protected void ReloadPageContent()
        {
            // Switch content model, if necessary.
            var newContentModel = WikiPage.ContentModel ?? MediaWikiUtility.InferContentModelFromTitle(
                WikiLink.Parse(WikiPage.Site, WikiPage.Title));

            if (EditorContentModel != newContentModel)
            {
                var ls = _SettingsService.GetSettingsByWikiContentModel(newContentModel);
                if (string.IsNullOrEmpty(ls.LanguageName))
                {
                    TextEditor = null;
                }
                else
                {
                    TextEditor                 = _TextEditorFactory.CreateTextEditor(ls.LanguageName, true);
                    TextEditor.WikiSite        = SiteContext;
                    TextEditor.DocumentOutline = DocumentOutline;
                }
                EditorContentModel = newContentModel;
            }
            if (TextEditor != null)
            {
                TextEditor.TextBox.Text = WikiPage.Content;
                TextEditor.InvalidateDocumentOutline(true);
            }
        }
 private void CheckNode(WikiLink link, DiagnosticEmitter e)
 {
     if (string.IsNullOrWhiteSpace(link.Target?.ToString()))
     {
         e.EmptyWikilinkTarget(link.ToRange());
     }
 }
Beispiel #10
0
        /// <summary>
        /// Initializes a new <see cref="Topic"/> instance from MW site and topic page title.
        /// </summary>
        /// <param name="site">MediaWiki site.</param>
        /// <param name="title">Either full page title of the Flow discussion board including <c>Topic:</c> namespace prefix, or the workflow ID of the board.</param>
        /// <exception cref="ArgumentNullException"><paramref name="site"/> or <paramref name="title"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="title"/> is not a valid title.</exception>
        public Topic(WikiSite site, string title)
        {
            Site = site ?? throw new ArgumentNullException(nameof(site));
            var link = WikiLink.Parse(site, title, FlowNamespaces.Topic);

            Title      = link.ToString();
            WorkflowId = link.Title.ToLowerInvariant();
        }
Beispiel #11
0
        public async Task TestMethod2()
        {
            var WikiaTestSite = await WikiaTestSiteAsync;
            var link1         = WikiLink.Parse(WikiaTestSite, "__ _project_ _talk_:___sandbox_", BuiltInNamespaces.Category);
            var link2         = WikiLink.Parse(WikiaTestSite, "part1:part2:part3", BuiltInNamespaces.Category);

            Assert.Equal("Mediawiki 1.19 test Wiki talk:Sandbox", link1.ToString());
            Assert.Equal("Category:Part1:part2:part3", link2.ToString());
        }
Beispiel #12
0
 public BoardHeader(WikiSite site, string boardTitle)
 {
     if (site == null)
     {
         throw new ArgumentNullException(nameof(site));
     }
     Site       = site;
     BoardTitle = WikiLink.NormalizeWikiLink(site, boardTitle);
 }
        private string CreateHtmlLink(PagePath parsedPage, WikiLink link)
        {
            if (link.Exists)
            {
                return string.Format(@"<a href=""{0}"" class=""wiki-link"">{1}</a>", parsedPage.GetPathRelativeTo(link.PagePath), link.Title);
            }

            return string.Format(
                @"<a href=""{0}?title={1}"" class=""wiki-link missing"">{2}</a>", parsedPage.GetPathRelativeTo(link.PagePath),
                link.Title, link.Title);
        }
Beispiel #14
0
 public static string InferContentModel(this Page page)
 {
     if (page == null)
     {
         throw new ArgumentNullException(nameof(page));
     }
     if (page.ContentModel != null)
     {
         return(page.ContentModel);
     }
     // For older MediaWiki sites...
     return(InferContentModelFromTitle(WikiLink.Parse(page.Site, page.Title)));
 }
Beispiel #15
0
        private void linkList_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (linkList.SelectedItem == null)
            {
                return;
            }

            WikiLink link = (WikiLink)linkList.SelectedItem;

            titleBox.Text = link.DestPageURL;

            FetchPage(link.DestPageURL);
        }
Beispiel #16
0
        private WikiLink ParseWikiLink()
        {
            // Note that wikilink cannot nest itself.
            ParseStart(@"\||\n|\[\[|\]\]", true);
            if (ConsumeToken(@"\[\[") == null)
            {
                return(ParseFailed <WikiLink>());
            }
            var target = new Run();

            if (!ParseRun(RunParsingMode.ExpandableText, target, true))
            {
                if (options.AllowEmptyWikiLinkTarget)
                {
                    target = null;
                }
                else
                {
                    return(ParseFailed <WikiLink>());
                }
            }
            var node = new WikiLink {
                Target = target
            };

            if (ConsumeToken(@"\|") != null)
            {
                var text = new Run();
                // Text accepts pipe
                CurrentContext.Terminator = Terminator.Get(@"\n|\[\[|\]\]");
                // For [[target|]], Text == Empty Run
                // For [[target]], Text == null
                if (ParseRun(RunParsingMode.ExpandableText, text, true))
                {
                    node.Text = text;
                }
            }
            if (ConsumeToken(@"\]\]") == null)
            {
                if (options.AllowClosingMarkInference)
                {
                    node.SetInferredClosingMark();
                }
                else
                {
                    return(ParseFailed <WikiLink>());
                }
            }
            return(ParseSuccessful(node));
        }
Beispiel #17
0
    public void WikiLinkTest()
    {
        var value = new WikiLink(false, false, false, false, "Test Title", "Test Namespace");

        var json = JsonSerializer.Serialize(value);

        Console.WriteLine();
        Console.WriteLine(json);
        var deserialized = JsonSerializer.Deserialize <WikiLink>(json);

        Assert.AreEqual(value, deserialized);
        Assert.AreEqual(json, JsonSerializer.Serialize(deserialized));

        value = new WikiLink(false, true, false, false, "Test Title", "Test Namespace");

        json = JsonSerializer.Serialize(value);
        Console.WriteLine();
        Console.WriteLine(json);
        deserialized = JsonSerializer.Deserialize <WikiLink>(json);
        Assert.AreEqual(value, deserialized);
        Assert.AreEqual(json, JsonSerializer.Serialize(deserialized));

        value = new WikiLink(true, false, false, false, "Test Title", _Options.CategoryNamespace);

        json = JsonSerializer.Serialize(value);
        Console.WriteLine();
        Console.WriteLine(json);
        deserialized = JsonSerializer.Deserialize <WikiLink>(json);
        Assert.AreEqual(value, deserialized);
        Assert.AreEqual(json, JsonSerializer.Serialize(deserialized));

        value = new WikiLink(true, true, false, false, "Test Title", _Options.CategoryNamespace);

        json = JsonSerializer.Serialize(value);
        Console.WriteLine();
        Console.WriteLine(json);
        deserialized = JsonSerializer.Deserialize <WikiLink>(json);
        Assert.AreEqual(value, deserialized);
        Assert.AreEqual(json, JsonSerializer.Serialize(deserialized));

        value = new WikiLink(false, false, true, false, "Test Title", "Test Namespace");

        json = JsonSerializer.Serialize(value);
        Console.WriteLine();
        Console.WriteLine(json);
        deserialized = JsonSerializer.Deserialize <WikiLink>(json);
        Assert.AreEqual(value, deserialized);
        Assert.AreEqual(json, JsonSerializer.Serialize(deserialized));
    }
        /// <inheritdoc />
        protected override async Task ProcessRecordAsync(CancellationToken cancellationToken)
        {
            using (var fs = new FileStream(File.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, 1024 * 4,
                                           FileOptions.Asynchronous | FileOptions.SequentialScan))
            {
                var titleLink = WikiLink.Parse(WikiSite, Title, BuiltInNamespaces.File);
                WikiUploadSource uploadSource;
                if (Chunked)
                {
                    if (!ShouldProcess($"{File}", "Chunked stash"))
                    {
                        return;
                    }
                    var src = new ChunkedUploadSource(WikiSite, fs, File.Name)
                    {
                        DefaultChunkSize = 512 * 1024
                    };
                    var progress = new ProgressRecord(0, $"Stash {File}", null);
                    WriteProgress(progress);
                    do
                    {
                        var r = await src.StashNextChunkAsync(cancellationToken);

                        if (r.ResultCode == UploadResultCode.Warning)
                        {
                            WriteWarning(r.Warnings.ToString());
                        }
                        progress.PercentComplete = (int)(100.0 * src.UploadedSize / src.TotalSize);
                    } while (!src.IsStashed);
                    progress.RecordType = ProgressRecordType.Completed;
                    uploadSource        = src;
                }
                else
                {
                    uploadSource = new StreamUploadSource(fs);
                }
                if (!ShouldProcess($"{File} -> {titleLink}", "Upload"))
                {
                    return;
                }
                var result = await WikiSite.UploadAsync(Title, uploadSource, Comment, Force, Utility.ParseAutoWatchBehavior(Watch), cancellationToken);

                if (result.ResultCode == UploadResultCode.Warning)
                {
                    WriteWarning(result.Warnings.ToString());
                }
                WriteObject(result);
            }
        }
        public async Task InterwikiLinkTests()
        {
            // We will not login onto any site…
            var homeSite = await Family.GetSiteAsync("test2");

            var link = await WikiLink.ParseAsync(homeSite, Family, "WikiPedia:SANDBOX");

            AssertWikiLink(link, null, "Wikipedia", "SANDBOX");
            link = await WikiLink.ParseAsync(homeSite, Family, "FR___:_ __Wp__ _:  SANDBOX");

            AssertWikiLink(link, "fr", "Wikipédia", "SANDBOX");
            link = await WikiLink.ParseAsync(homeSite, Family, "EN:fr:   LZH:Project:SANDBOX");

            AssertWikiLink(link, "lzh", "維基大典", "SANDBOX");
        }
        /// <summary>
        /// Initializes a new instance of <see cref="WikiPage"/> from page title.
        /// </summary>
        /// <param name="site">The wiki site this page is on.</param>
        /// <param name="title">Page title with or without namespace prefix.</param>
        /// <param name="defaultNamespaceId">The default namespace ID for page title without namespace prefix.</param>
        /// <remarks>The initialized instance does not contain any live information from MediaWiki site.
        /// Use <see cref="RefreshAsync()"/> to fetch for information from server.</remarks>
        public WikiPage(WikiSite site, string title, int defaultNamespaceId)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (string.IsNullOrWhiteSpace(title))
            {
                throw new ArgumentNullException(nameof(title));
            }
            Site = site;
            var parsedTitle = WikiLink.Parse(site, title, defaultNamespaceId);

            PageStub = new WikiPageStub(parsedTitle.FullTitle, parsedTitle.Namespace !.Id);
        }
Beispiel #21
0
        public WikiPage(WikiSite site, string title, int defaultNamespaceId)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (string.IsNullOrWhiteSpace(title))
            {
                throw new ArgumentNullException(nameof(title));
            }
            Site       = site;
            WikiClient = Site.WikiClient;
            Debug.Assert(WikiClient != null);
            var parsedTitle = WikiLink.Parse(site, title, defaultNamespaceId);

            Title       = parsedTitle.FullTitle;
            NamespaceId = parsedTitle.Namespace.Id;
        }
Beispiel #22
0
        public async Task <PageEditorViewModel> OpenPageEditorAsync(WikiSiteViewModel wikiSite, string pageTitle)
        {
            var site = await wikiSite.GetSiteAsync();

            var normalizedTitle = WikiLink.NormalizeWikiLink(site, pageTitle);
            var editor          = _ChildViewModelService.Documents
                                  .OfType <PageEditorViewModel>()
                                  .Where(vm => vm.SiteContext == wikiSite)
                                  .FirstOrDefault(vm => vm.WikiPage.Title == normalizedTitle);

            if (editor == null)
            {
                editor = CreatePageEditor(wikiSite);
                editor.SetWikiPageAsync(pageTitle).Forget();
                _ChildViewModelService.Documents.Add(editor);
            }
            editor.IsActive = true;
            return(editor);
        }
Beispiel #23
0
        /// <summary>
        /// Get all possible namespace-alias - title combinations.
        /// </summary>
        private IEnumerable <string> PageTitleCombinations(string title, Site site, bool leadingColon, bool transclusion)
        {
            var link = WikiLink.Parse(site, title);

            if (link.Namespace.Id == BuiltInNamespaces.Main)
            {
                if (transclusion)
                {
                    return new[] { ":" + link.Title }
                }
                ;
                return(new[] { link.Title });
            }
            if (transclusion && link.Namespace.Id == BuiltInNamespaces.Template)
            {
                return new[] { link.Title }
            }
            ;
            return(link.Namespace.Aliases.Concat(new[] { link.Namespace.CanonicalName, link.Namespace.CustomName })
                   .Distinct().Where(n => n != null)
                   .Select(n => (leadingColon ? ":" : null) + n + ":" + link.Title));
        }
Beispiel #24
0
 /// <summary>
 /// Infers MediaWiki content model name from the title of the page.
 /// This is for MediaWiki version lower than 1.21 .
 /// </summary>
 public static string InferContentModelFromTitle(WikiLink title)
 {
     if (title == null)
     {
         throw new ArgumentNullException(nameof(title));
     }
     if (title.Namespace.Id == BuiltInNamespaces.MediaWiki || title.Namespace.Id == BuiltInNamespaces.User)
     {
         if (title.Title.EndsWith(".js", StringComparison.OrdinalIgnoreCase))
         {
             return(ContentModels.JavaScript);
         }
         if (title.Title.EndsWith(".css", StringComparison.OrdinalIgnoreCase))
         {
             return(ContentModels.Css);
         }
     }
     if (title.Namespace.CanonicalName == "Module")
     {
         return(ContentModels.Scribunto);
     }
     return(ContentModels.Wikitext);
 }
Beispiel #25
0
        /// <summary>
        /// Create an instance of <see cref="WikiPage"/> or its derived class,
        /// depending on the namespace the page is in.
        /// </summary>
        /// <param name="site">Site instance.</param>
        /// <param name="title">Title of the page, with or without namespace prefix.</param>
        /// <param name="defaultNamespaceId">
        /// The namespace id of the page used when there's no explicit namespace prefix in <paramref name="title"/>.
        /// See <see cref="BuiltInNamespaces"/> for a list of possible values.
        /// </param>
        /// <exception cref="ArgumentNullException">Either <paramref name="site"/> or <paramref name="title"/> is <c>null</c>.</exception>
        /// <exception cref="ArgumentException"><paramref name="title"/> has invalid title patterns.</exception>
        /// <exception cref="InvalidOperationException"><paramref name="title"/> is an interwiki link.</exception>
        public static WikiPage FromTitle(WikiSite site, string title, int defaultNamespaceId)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (title == null)
            {
                throw new ArgumentNullException(nameof(title));
            }
            WikiLink link;

            try
            {
                link = WikiLink.Parse(site, title, defaultNamespaceId);
            }
            catch (ArgumentException ex)
            {
                throw new ArgumentException(ex.Message, nameof(title), ex);
            }
            if (link.InterwikiPrefix != null)
            {
                throw new InvalidOperationException($"Interwiki title is not supported: {title} .");
            }
            switch (link.Namespace.Id)
            {
            case BuiltInNamespaces.Category:
                return(new CategoryPage(site, title));

            case BuiltInNamespaces.File:
                return(new CategoryPage(site, title));

            default:
                return(new WikiPage(site, title, defaultNamespaceId));
            }
        }
Beispiel #26
0
 /// <summary>
 /// Initializes the generator from the site and category title.
 /// </summary>
 /// <param name="site">Site instance.</param>
 /// <param name="categoryTitle">Title of the category, with or without Category: prefix.</param>
 public CategoryMembersGenerator(WikiSite site, string categoryTitle) : base(site)
 {
     CategoryTitle = WikiLink.NormalizeWikiLink(site, categoryTitle, BuiltInNamespaces.Category);
 }
Beispiel #27
0
        public async Task TestMethod4()
        {
            var site = await WpTest2SiteAsync;

            Assert.Throws <ArgumentException>(() => WikiLink.Parse(site, "Project:"));
        }
Beispiel #28
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));
            }
        }
Beispiel #29
0
        //content can be
        //  Stream          file content
        //  string          url to fetch
        //  UploadResult    the previous failed upload
        private static async Task <UploadResult> UploadAsyncInternal(WikiSite site, object content, string title, string comment,
                                                                     bool ignoreWarnings, AutoWatchBehavior watch, CancellationToken cancellationToken)
        {
            if (site == null)
            {
                throw new ArgumentNullException(nameof(site));
            }
            if (content == null)
            {
                throw new ArgumentNullException(nameof(content));
            }
            if (title == null)
            {
                throw new ArgumentNullException(nameof(title));
            }
            var link = WikiLink.Parse(site, title);

            if (link.Namespace.Id != BuiltInNamespaces.File)
            {
                throw new ArgumentException($"Invalid namespace for file title: {title} .", nameof(title));
            }
            var token = await site.GetTokenAsync("edit");

            long?streamPosition = null;

            HttpContent RequestFactory()
            {
                var requestContent = new MultipartFormDataContent
                {
                    { new StringContent("json"), "format" },
                    { new StringContent("upload"), "action" },
                    { new StringContent(Utility.ToWikiQueryValue(watch)), "watchlist" },
                    { new StringContent(token), "token" },
                    { new StringContent(link.Title), "filename" },
                    { new StringContent(comment), "comment" },
                };

                if (content is Stream streamContent)
                {
                    if (streamPosition < 0)
                    {
                        return(null);
                    }
                    // Memorize/reset the stream position.
                    if (streamContent.CanSeek)
                    {
                        if (streamPosition == null)
                        {
                            streamPosition = streamContent.Position;
                        }
                        else
                        {
                            streamContent.Position = streamPosition.Value;
                        }
                        Debug.Assert(streamPosition >= 0);
                    }
                    else
                    {
                        // Mark for do-not-retry.
                        streamPosition = -1;
                    }
                    requestContent.Add(new KeepAlivingStreamContent(streamContent), "file", title);
                }
                else if (content is string stringContent)
                {
                    requestContent.Add(new StringContent(stringContent), "url");
                }
                else if (content is UploadResult resultContent)
                {
                    var key = (resultContent).FileKey;
                    if (string.IsNullOrEmpty(key))
                    {
                        throw new InvalidOperationException("The specified UploadResult has no valid FileKey.");
                    }
                    // sessionkey: Same as filekey, maintained for backward compatibility (deprecated in 1.18)
                    requestContent.Add(new StringContent(key),
                                       site.SiteInfo.Version >= new Version(1, 18) ? "filekey" : "sessionkey");
                }
                else
                {
                    Debug.Assert(false, "Unrecognized content argument type.");
                }
                if (ignoreWarnings)
                {
                    requestContent.Add(new StringContent(""), "ignorewarnings");
                }
                return(requestContent);
            }

            site.Logger?.Info(site, $"Uploading: {link.Title} .");
            var jresult = await site.PostContentAsync(RequestFactory, cancellationToken);

            var result = jresult["upload"].ToObject <UploadResult>(Utility.WikiJsonSerializer);

            site.Logger?.Info(site, $"Upload[{link.Title}]: {result}.");
            switch (result.ResultCode)
            {
            case UploadResultCode.Warning:
                throw new UploadException(result);

            default:
                // UploadResult.Result setter should have thrown an exception.
                Debug.Assert(result.ResultCode == UploadResultCode.Success ||
                             result.ResultCode == UploadResultCode.Continue);
                break;
            }
            return(result);
        }
Beispiel #30
0
        /// <summary>
        /// Given the summary of a page asynchronously.
        /// </summary>
        /// <exception cref="ArgumentNullException">title is null.</exception>
        /// <exception cref="ArgumentException">title is invalid.</exception>
        /// <remarks>Do not modify the returned objects.</remarks>
        public async Task <IList <PageInfo> > GetPageSummaryAsync(IEnumerable <string> titles)
        {
            if (titles == null)
            {
                throw new ArgumentNullException(nameof(titles));
            }
            var site = await GetSiteAsync();

            var titleList            = titles.Select(t => WikiLink.NormalizeWikiLink(site, t)).ToArray();
            var pagesToCheck         = new List <Page>();
            var pagesToFetch         = new List <Page>();
            var pagesToCheckRedirect = new List <Tuple <Page, PageInfo> >();
            var parser = new Lazy <WikitextParser>();

            // First, check whether we need to contact the server for each of the page title.
            foreach (var title in titleList)
            {
                var cached = _PageSummaryCache.TryGetValue(title);
                if (cached != null && DateTime.Now - cached.Item2 < _CacheExpiry)
                {
                    continue;
                }
                pagesToCheck.Add(new Page(site, title));
            }
            await pagesToCheck.RefreshAsync();

            foreach (var page in pagesToCheck)
            {
                var cached = _PageSummaryCache.TryGetValue(page.Title);
                // Check if the cache is obsolete.
                if (cached != null && page.LastRevisionId == cached.Item1.LastRevisionId)
                {
                    _PageSummaryCache[page.Title] = Tuple.Create(cached.Item1, DateTime.Now);
                    continue;
                }
                // We need to fetch the whole page.
                pagesToFetch.Add(page);
            }
            // Fetch information & content.
            await pagesToFetch.RefreshAsync(PageQueryOptions.FetchContent);

            foreach (var page in pagesToFetch)
            {
                var info = PageInfoBuilder.BuildBasicInfo(page, parser.Value);
                _PageSummaryCache[page.Title] = Tuple.Create(info, DateTime.Now);
                if (page.IsRedirect)
                {
                    pagesToCheckRedirect.Add(Tuple.Create(page, info));
                }
            }
            // Fetch redirects.
            await pagesToCheckRedirect.Select(t => t.Item1).RefreshAsync(PageQueryOptions.ResolveRedirects);

            foreach (var tp in pagesToCheckRedirect)
            {
                var path = tp.Item1.RedirectPath.ToList();
                // Add & complete redirect path
                path.Add(tp.Item1.Title);
                tp.Item2.RedirectPath = path;
            }
            return(titleList.Select(t => _PageSummaryCache[t].Item1).ToArray());
        }
Beispiel #31
0
 private void AssertWikiLink(WikiLink link, string interwiki, string ns, string localTitle)
 {
     Assert.Equal(interwiki, link.InterwikiPrefix);
     Assert.Equal(ns, link.NamespaceName);
     Assert.Equal(localTitle, link.Title);
 }