Пример #1
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);
        }
        /// <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));
        }
Пример #3
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);
            }
        }
        /// <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);
            }
        }
Пример #5
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);
        }
Пример #6
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();
                        }
                    }
                }
        }
Пример #7
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();
        }
Пример #8
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());
        }
Пример #9
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)));
 }
Пример #10
0
        /// <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);
            }
        }
Пример #11
0
        /// <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);
        }
Пример #12
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;
        }
Пример #13
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));
        }
Пример #14
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));
            }
        }
Пример #15
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));
            }
        }
Пример #16
0
        public async Task <WikipediaArticle> GetArticleAsync(string language, string name)
        {
            if (rateLimiter.IsRatelimited())
            {
                return(null);
            }

            var article = new WikipediaArticle
            {
                Url = $"https://{language}.wikipedia.org/wiki/{name}"
            };

            var page = new WikiPage(wikipediaSite, name);

            await page.RefreshAsync(new WikiPageQueryProvider
            {
                Properties =
                {
                    new ExtractsPropertyProvider
                    {
                        MaxCharacters    = 1024,
                        AsPlainText      = true,
                        IntroductionOnly = true
                    }
                }
            });

            var extractGroup = page.GetPropertyGroup <ExtractsPropertyGroup>();

            article.Name = page.Title;
            article.Url  = WikiLink.Parse(wikipediaSite, name).TargetUrl;

            article.Description = extractGroup.Extract;

            if (article.Description.Length >= 1024)
            {
                var split = article.Description.Split(". ").ToList();
                article.Description = string.Join(". ", split.Take(4)) + ".";
            }

            var response = await HttpWebClient.ReturnStringAsync(new System.Uri($"https://www.wikidata.org/w/api.php?action=wbgetentities&format=json&sites={language}wiki&props=claims&titles={name}"));

            var jsonresp  = JObject.Parse(response);
            var container = (JObject)jsonresp["entities"].First.Value <JProperty>().Value;
            var claims    = container["claims"];

            //P18/P154/P242/P109/P1621
            JToken snak = null;

            if (claims["P18"] is not null)
            {
                snak = claims["P18"];
            }
            else if (claims["P154"] is not null)
            {
                snak = claims["P154"];
            }
            else if (claims["P242"] is not null)
            {
                snak = claims["P242"];
            }
            else if (claims["P109"] is not null)
            {
                snak = claims["P109"];
            }
            else if (claims["P1621"] is not null)
            {
                snak = claims["P1621"];
            }

            if (snak is not null)
            {
                var val = snak.First["mainsnak"]["datavalue"]["value"].ToObject <string>();

                val = val.Replace(" ", "_");

                var md5 = val.CreateMD5(true);;

                article.ImageUrl = $"https://upload.wikimedia.org/wikipedia/commons/{md5[0]}/{md5[0]}{md5[1]}/{val}";
            }

            return(article);
        }
Пример #17
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);
        }
Пример #18
0
        private static async Task FetchLabels(WikiSite site, Func <string, Task <WikiSite> > getExternalSiteAsync, string originEntity)
        {
            var apg = new BacklinksGenerator(site, originEntity)
            {
                NamespaceIds    = new[] { site.Namespaces["Item"].Id },
                RedirectsFilter = PropertyFilterOption.WithoutProperty,
                PaginationSize  = 100
            };
            var itemCounter = 0;
            var enSite      = await getExternalSiteAsync("en");

            await foreach (var stubs in apg.EnumItemsAsync().Buffer(100))
            {
                var items = stubs.Select(s => new Entity(site, WikiLink.Parse(site, s.Title).Title)).ToList();
                await items.RefreshAsync(EntityQueryOptions.FetchLabels | EntityQueryOptions.FetchSiteLinks, new List <string> {
                    "en"
                });

                var enwwPages = items.ToDictionary(i => i, i =>
                {
                    var enwwtitle = i.SiteLinks.ContainsKey("enwarriorswiki") ? i.SiteLinks["enwarriorswiki"].Title : null;
                    if (string.IsNullOrEmpty(enwwtitle))
                    {
                        Console.WriteLine("{0}: No enww sitelink available.", i);
                        return(null);
                    }
                    return(new WikiPage(enSite, enwwtitle));
                });
                Console.WriteLine("Fetching language links from enww.");
                await enwwPages.Values.Where(p => p != null).RefreshAsync(new WikiPageQueryProvider {
                    Properties = { new LanguageLinksPropertyProvider() }
                });

                foreach (var item in items)
                {
                    var enPage = enwwPages[item];
                    if (enPage == null)
                    {
                        continue;
                    }
                    foreach (var langLink in enPage.GetPropertyGroup <LanguageLinksPropertyGroup>().LanguageLinks
                             // Wikia returns duplicate language links
                             .Select(l => (l.Language, l.Title)).Distinct())
                    {
                        if (langLink.Language == "zh")
                        {
                            continue;
                        }
                        var siteName = langLink.Language + "warriorswiki";
                        if (item.SiteLinks.ContainsKey(siteName))
                        {
                            continue;
                        }
                        Console.Write("{0}: Add {1}:{2}...", item, siteName, langLink.Title);
                        try
                        {
                            await item.EditAsync(new[]
                            {
                                new EntityEditEntry(nameof(item.SiteLinks),
                                                    new EntitySiteLink(siteName, langLink.Title))
                            },
                                                 "Add sitelink from enwarriorswiki.", EntityEditOptions.Bot);

                            Console.WriteLine("Success.");
                        }
                        catch (OperationFailedException ex) when(ex.ErrorCode == "no-external-page")
                        {
                            Console.WriteLine("No external page.");
                        }
                        catch (OperationFailedException ex) when(ex.ErrorCode == "failed-save")
                        {
                            Console.WriteLine("Save failed.");
                            Console.WriteLine(ex.ErrorMessage);
                        }
                    }
                }
                itemCounter += items.Count;
                Console.WriteLine("Processed {0} items.", itemCounter);
            }
        }
Пример #19
0
        /// <summary>
        /// Moves (renames) a page. (MediaWiki 1.12)
        /// </summary>
        public async Task MoveAsync(string newTitle, string reason, PageMovingOptions options, AutoWatchBehavior watch,
                                    CancellationToken cancellationToken)
        {
            if (newTitle == null)
            {
                throw new ArgumentNullException(nameof(newTitle));
            }
            if (newTitle == Title)
            {
                return;
            }
            using (Site.BeginActionScope(this))
                using (await Site.ModificationThrottler.QueueWorkAsync("Move: " + this, cancellationToken))
                {
                    // When passing this to the Edit API, always pass the token parameter last
                    // (or at least after the text parameter). That way, if the edit gets interrupted,
                    // the token won't be passed and the edit will fail.
                    // This is done automatically by mw.Api.
                    JToken jresult;
                    try
                    {
                        jresult = await Site.InvokeMediaWikiApiAsync(new MediaWikiFormRequestMessage(new
                        {
                            action = "move",
                            token = WikiSiteToken.Move,
                            from = PageStub.HasTitle ? PageStub.Title : null,
                            fromid = PageStub.HasTitle ? null : (int?)PageStub.Id,
                            to = newTitle,
                            maxlag = 5,
                            movetalk = (options & PageMovingOptions.LeaveTalk) != PageMovingOptions.LeaveTalk,
                            movesubpages = (options & PageMovingOptions.MoveSubpages) == PageMovingOptions.MoveSubpages,
                            noredirect = (options & PageMovingOptions.NoRedirect) == PageMovingOptions.NoRedirect,
                            ignorewarnings = (options & PageMovingOptions.IgnoreWarnings) ==
                                             PageMovingOptions.IgnoreWarnings,
                            watchlist = watch,
                            reason = reason,
                        }), cancellationToken);
                    }
                    catch (OperationFailedException ex)
                    {
                        switch (ex.ErrorCode)
                        {
                        case "cantmove":
                        case "protectedpage":
                        case "protectedtitle":
                            throw new UnauthorizedOperationException(ex);

                        default:
                            if (ex.ErrorCode.StartsWith("cantmove"))
                            {
                                throw new UnauthorizedOperationException(ex);
                            }
                            throw;
                        }
                    }
                    var fromTitle = (string)jresult["move"]["from"];
                    var toTitle   = (string)jresult["move"]["to"];
                    Site.Logger.LogInformation("Page [[{fromTitle}]] has been moved to [[{toTitle}]].", fromTitle, toTitle);
                    var link = WikiLink.Parse(Site, toTitle);
                    PageStub = new WikiPageStub(PageStub.Id, toTitle, link.Namespace.Id);
                }
        }
Пример #20
0
        private static async Task UpdateLabels(WikiSite site, string originEntity)
        {
            var apg = new BacklinksGenerator(site, originEntity)
            {
                NamespaceIds    = new[] { site.Namespaces["Item"].Id },
                RedirectsFilter = PropertyFilterOption.WithoutProperty,
                PaginationSize  = 100
            };
            var itemCounter = 0;

            await foreach (var stubs in apg.EnumItemsAsync().Buffer(100))
            {
                var items = stubs.Select(s => new Entity(site, WikiLink.Parse(site, s.Title).Title)).ToList();
                await items.RefreshAsync(EntityQueryOptions.FetchLabels | EntityQueryOptions.FetchAliases | EntityQueryOptions.FetchSiteLinks);

                foreach (var item in items)
                {
                    var enLabels = new HashSet <string>();
                    {
                        var enSiteLink = item.SiteLinks.FirstOrDefault(sl => sl.Site == "enwarriorswiki")?.Title;
                        if (!string.IsNullOrEmpty(enSiteLink))
                        {
                            enLabels.Add(LabelFromTitle(enSiteLink));
                        }
                        enLabels.Add(item.Labels["en"]);
                        enLabels.Add(item.Labels["en-us"]);
                        enLabels.Add(item.Labels["en-gb"]);
                        foreach (var alias in item.Aliases["en"])
                        {
                            enLabels.Add(alias);
                        }
                        enLabels.Remove(null);
                    }
                    foreach (var siteLink in item.SiteLinks.Where(sl => sl.Site.EndsWith("warriorswiki")))
                    {
                        var language = siteLink.Site.Substring(0, siteLink.Site.Length - 12);
                        if (language == "zh")
                        {
                            continue;
                        }
                        var culture  = CultureInfo.GetCultureInfo(language);
                        var label    = Regex.Replace(siteLink.Title, @"(?!<=^)\s*\(.+", "");
                        var curLabel = item.Labels[language];
                        //if (language != "en")
                        //{
                        //    if (enLabels.Contains(curLabel))
                        //    {
                        //        Console.Write("{0}: Remove label: {1}@{2}", item, curLabel, language);
                        //        await item.EditAsync(new[]
                        //        {
                        //            new EntityEditEntry(nameof(item.Labels), new WbMonolingualText(language, "dummy"), EntityEditEntryState.Removed)
                        //        }, "", EntityEditOptions.Bot);
                        //        Console.WriteLine();
                        //    }
                        //    foreach (var alias in item.Aliases[language])
                        //    {
                        //        if (enLabels.Contains(alias))
                        //        {
                        //            Console.Write("{0}: Remove alias: {1}@{2}", item, alias, language);
                        //            await item.EditAsync(new[]
                        //            {
                        //                new EntityEditEntry(nameof(item.Aliases), new WbMonolingualText(language, alias), EntityEditEntryState.Removed)
                        //            }, "", EntityEditOptions.Bot);
                        //            Console.WriteLine();
                        //        }
                        //    }
                        //}
                        if (!enLabels.Contains(label) && (curLabel == null || label.ToLower(culture) != curLabel.ToLower(culture)))
                        {
                            var convertToAlias = !string.IsNullOrWhiteSpace(curLabel) && !enLabels.Contains(curLabel);
                            Console.Write("{0}: {1}: {2} -> {3}", item, language, curLabel, label);
                            var changes = new List <EntityEditEntry>
                            {
                                new EntityEditEntry(nameof(item.Labels), new WbMonolingualText(language, label))
                            };
                            if (convertToAlias)
                            {
                                Console.Write(" (New alias)");
                                changes.Add(new EntityEditEntry(nameof(item.Aliases), new WbMonolingualText(language, curLabel)));
                            }
                            await item.EditAsync(changes, "Update label from " + siteLink.Site + ".", EntityEditOptions.Bot);

                            Console.WriteLine();
                        }
                    }
                }
                itemCounter += items.Count;
                Console.WriteLine("Processed {0} items.", itemCounter);
            }
        }
Пример #21
0
        public async Task TestMethod4()
        {
            var site = await WpTest2SiteAsync;

            Assert.Throws <ArgumentException>(() => WikiLink.Parse(site, "Project:"));
        }