diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 335c1c7d1..846705d58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,10 +28,12 @@ jobs: WCL_IS_CI_BUILD: 1 BUILD_SECRET_KEY: "${{ secrets.BUILD_SECRET }}" steps: - # Need to wait for https://github.com/actions/setup-dotnet/issues/25 to be resolved. - # - uses: actions/setup-dotnet@v1 - # with: - # dotnet-version: '3.0.100' + - uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 5.0.x + 6.0.x - uses: actions/checkout@v2 with: submodules: true @@ -65,10 +67,12 @@ jobs: WCL_IS_CI_BUILD: 1 BUILD_SECRET_KEY: "${{ secrets.BUILD_SECRET }}" steps: - # Need to wait for https://github.com/actions/setup-dotnet/issues/25 to be resolved. - # - uses: actions/setup-dotnet@v1 - # with: - # dotnet-version: '3.0.100' + - uses: actions/setup-dotnet@v1 + with: + dotnet-version: | + 3.1.x + 5.0.x + 6.0.x - uses: actions/checkout@v1 with: submodules: true diff --git a/Samples/ConsoleTestApplication1/ConsoleTestApplication1.csproj b/Samples/ConsoleTestApplication1/ConsoleTestApplication1.csproj index c94bbc555..7bb13b573 100644 --- a/Samples/ConsoleTestApplication1/ConsoleTestApplication1.csproj +++ b/Samples/ConsoleTestApplication1/ConsoleTestApplication1.csproj @@ -2,9 +2,10 @@ Exe - net5.0 + net6.0 WikiClientLibrary.Samples.ConsoleTestApplication1 Enable + Enable diff --git a/Samples/ConsoleTestApplication1/Program.cs b/Samples/ConsoleTestApplication1/Program.cs index f3d055991..9eab64611 100644 --- a/Samples/ConsoleTestApplication1/Program.cs +++ b/Samples/ConsoleTestApplication1/Program.cs @@ -1,239 +1,233 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging; using WikiClientLibrary.Client; using WikiClientLibrary.Generators; using WikiClientLibrary.Pages; using WikiClientLibrary.Sites; -namespace WikiClientLibrary.Samples.ConsoleTestApplication1 +namespace WikiClientLibrary.Samples.ConsoleTestApplication1; + +class Program { - class Program + static void Main(string[] args) { - static void Main(string[] args) + try { - try - { - HelloWikiWorld().Wait(); - //HelloWikiGenerators().Wait(); - //HelloRecentChanges().Wait(); - //InteractivePatrol().Wait(); - } - catch (Exception ex) - { - Console.Error.WriteLine(ex); - } + HelloWikiWorld().Wait(); + //HelloWikiGenerators().Wait(); + //HelloRecentChanges().Wait(); + //InteractivePatrol().Wait(); + } + catch (Exception ex) + { + Console.Error.WriteLine(ex); } + } - static async Task HelloWikiWorld() + static async Task HelloWikiWorld() + { + var loggerFactory = LoggerFactory.Create(c => c + .SetMinimumLevel(LogLevel.Information) + .AddSimpleConsole(o => o.IncludeScopes = true) + ); + // Create a MediaWiki API client. + var wikiClient = new WikiClient { - var loggerFactory = LoggerFactory.Create(c => c - .SetMinimumLevel(LogLevel.Information) - .AddSimpleConsole(o => o.IncludeScopes = true) - ); - // Create a MediaWiki API client. - var wikiClient = new WikiClient - { - // UA of Client Application. The UA of WikiClientLibrary will - // be append to the end of this when sending requests. - ClientUserAgent = "ConsoleTestApplication1/1.0", - Logger = loggerFactory.CreateLogger(), - }; - // Create a MediaWiki Site instance with the URL of API endpoint. - var site = new WikiSite(wikiClient, "https://test2.wikipedia.org/w/api.php") + // UA of Client Application. The UA of WikiClientLibrary will + // be append to the end of this when sending requests. + ClientUserAgent = "ConsoleTestApplication1/1.0", + Logger = loggerFactory.CreateLogger(), + }; + // Create a MediaWiki Site instance with the URL of API endpoint. + var site = new WikiSite(wikiClient, "https://test2.wikipedia.org/w/api.php") + { + Logger = loggerFactory.CreateLogger() + }; + // Waits for the WikiSite to initialize + await site.Initialization; + // Access site information via Site.SiteInfo + Console.WriteLine("API version: {0}", site.SiteInfo.Generator); + // Access user information via Site.UserInfo + Console.WriteLine("Hello, {0}!", site.AccountInfo.Name); + // Site login + Console.WriteLine("We will edit [[Project:Sandbox]]."); + if (Confirm($"Do you want to login into {site.SiteInfo.SiteName}?")) + { + LOGIN_RETRY: + try { - Logger = loggerFactory.CreateLogger() - }; - // Waits for the WikiSite to initialize - await site.Initialization; - // Access site information via Site.SiteInfo - Console.WriteLine("API version: {0}", site.SiteInfo.Generator); - // Access user information via Site.UserInfo - Console.WriteLine("Hello, {0}!", site.AccountInfo.Name); - // Site login - Console.WriteLine("We will edit [[Project:Sandbox]]."); - if (Confirm($"Do you want to login into {site.SiteInfo.SiteName}?")) + await site.LoginAsync(Input("User name"), Input("Password")); + } + catch (OperationFailedException ex) { - LOGIN_RETRY: - try - { - await site.LoginAsync(Input("User name"), Input("Password")); - } - catch (OperationFailedException ex) - { - Console.WriteLine(ex.ErrorMessage); - goto LOGIN_RETRY; - } - Console.WriteLine("You have successfully logged in as {0}.", site.AccountInfo.Name); - Console.WriteLine("You're in the following groups: {0}.", string.Join(",", site.AccountInfo.Groups)); + Console.WriteLine(ex.ErrorMessage); + goto LOGIN_RETRY; } - // Find out more members in Site class, such as - // page.Namespaces - // page.InterwikiMap - - // Page Operations - // Fetch information and content - var page = new WikiPage(site, site.SiteInfo.MainPage); - Console.WriteLine("Retrieving {0}…", page); - await page.RefreshAsync(PageQueryOptions.FetchContent); - - Console.WriteLine("Last touched at {0}.", page.LastTouched); - if (page.LastRevision == null) - Console.WriteLine("No last revision available: {0}", page.LastRevisionId); - else - Console.WriteLine("Last revision {0} by {1} at {2}.", page.LastRevisionId, page.LastRevision.UserName, page.LastRevision.TimeStamp); - Console.WriteLine("Content length: {0} bytes ----------", page.ContentLength); - Console.WriteLine(page.Content); - // Purge the page - if (await page.PurgeAsync()) - Console.WriteLine(" The page has been purged successfully."); - // Edit the page - page = new WikiPage(site, "Project:Sandbox"); - await page.RefreshAsync(PageQueryOptions.FetchContent); - if (!page.Exists) Console.WriteLine("Warning: The page {0} doesn't exist.", page); - page.Content += "\n\n'''Hello''' ''world''!"; - await page.UpdateContentAsync("Test edit from WikiClientLibrary."); - Console.WriteLine("{0} has been saved. RevisionId = {1}.", page, page.LastRevisionId); - // Find out more operations in Page class, such as - // page.MoveAsync() - // page.DeleteAsync() - // Logout - await site.LogoutAsync(); - Console.WriteLine("You have successfully logged out."); + Console.WriteLine("You have successfully logged in as {0}.", site.AccountInfo.Name); + Console.WriteLine("You're in the following groups: {0}.", string.Join(",", site.AccountInfo.Groups)); } + // Find out more members in Site class, such as + // page.Namespaces + // page.InterwikiMap - static async Task HelloWikiGenerators() - { - // Create a MediaWiki API client. - var wikiClient = new WikiClient(); - // Create a MediaWiki Site instance. - var site = new WikiSite(wikiClient, "https://en.wikipedia.org/w/api.php"); - await site.Initialization; - // List all pages starting from item "Wiki", without redirect pages. - var allpages = new AllPagesGenerator(site) - { - StartTitle = "Wiki", - RedirectsFilter = PropertyFilterOption.WithoutProperty - }; - // Take the first 1000 results - var pages = await allpages.EnumPagesAsync().Take(1000).ToListAsync(); - foreach (var p in pages) - Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); + // Page Operations + // Fetch information and content + var page = new WikiPage(site, site.SiteInfo.MainPage); + Console.WriteLine("Retrieving {0}…", page); + await page.RefreshAsync(PageQueryOptions.FetchContent); - // List the first 10 subcategories in Category:Cats - Console.WriteLine(); - Console.WriteLine("Cats"); - var catmembers = new CategoryMembersGenerator(site, "Category:Cats") - { - MemberTypes = CategoryMemberTypes.Subcategory - }; - pages = await catmembers.EnumPagesAsync().Take(10).ToListAsync(); - foreach (var p in pages) - Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); - } + Console.WriteLine("Last touched at {0}.", page.LastTouched); + if (page.LastRevision == null) + Console.WriteLine("No last revision available: {0}", page.LastRevisionId); + else + Console.WriteLine("Last revision {0} by {1} at {2}.", page.LastRevisionId, page.LastRevision.UserName, page.LastRevision.TimeStamp); + Console.WriteLine("Content length: {0} bytes ----------", page.ContentLength); + Console.WriteLine(page.Content); + // Purge the page + if (await page.PurgeAsync()) + Console.WriteLine(" The page has been purged successfully."); + // Edit the page + page = new WikiPage(site, "Project:Sandbox"); + await page.RefreshAsync(PageQueryOptions.FetchContent); + if (!page.Exists) Console.WriteLine("Warning: The page {0} doesn't exist.", page); + page.Content += "\n\n'''Hello''' ''world''!"; + await page.UpdateContentAsync("Test edit from WikiClientLibrary."); + Console.WriteLine("{0} has been saved. RevisionId = {1}.", page, page.LastRevisionId); + // Find out more operations in Page class, such as + // page.MoveAsync() + // page.DeleteAsync() + // Logout + await site.LogoutAsync(); + Console.WriteLine("You have successfully logged out."); + } - static async Task HelloRecentChanges() + static async Task HelloWikiGenerators() + { + // Create a MediaWiki API client. + var wikiClient = new WikiClient(); + // Create a MediaWiki Site instance. + var site = new WikiSite(wikiClient, "https://en.wikipedia.org/w/api.php"); + await site.Initialization; + // List all pages starting from item "Wiki", without redirect pages. + var allpages = new AllPagesGenerator(site) { - // Create a MediaWiki API client. - var wikiClient = new WikiClient(); - // Create a MediaWiki Site instance. - var site = new WikiSite(wikiClient, "https://en.wikipedia.org/w/api.php"); - await site.Initialization; - var rcg = new RecentChangesGenerator(site) - { - TypeFilters = RecentChangesFilterTypes.Create, - PaginationSize = 50, // We already know we're not going to fetch results as many as 500 or 5000 - // so this will help. - }; - // List the 10 latest new pages - var pages = await rcg.EnumPagesAsync().Take(10).ToListAsync(); - Console.WriteLine("New pages"); - foreach (var p in pages) - Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); - // List the 10 latest recent changes - rcg.TypeFilters = RecentChangesFilterTypes.All; - var rcs = await rcg.EnumItemsAsync().Take(10).ToListAsync(); - Console.WriteLine(); - Console.WriteLine("Recent changes"); - foreach (var rc in rcs) - Console.WriteLine(rc); - } + StartTitle = "Wiki", + RedirectsFilter = PropertyFilterOption.WithoutProperty + }; + // Take the first 1000 results + var pages = await allpages.EnumPagesAsync().Take(1000).ToListAsync(); + foreach (var p in pages) + Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); - static async Task InteractivePatrol() + // List the first 10 subcategories in Category:Cats + Console.WriteLine(); + Console.WriteLine("Cats"); + var catmembers = new CategoryMembersGenerator(site, "Category:Cats") { - // Patrol the last unpatrolled change. - // Usually a user should have the patrol right to perform such operation. + MemberTypes = CategoryMemberTypes.Subcategory + }; + pages = await catmembers.EnumPagesAsync().Take(10).ToListAsync(); + foreach (var p in pages) + Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); + } - // Create a MediaWiki API client. - var wikiClient = new WikiClient(); - // Create a MediaWiki Site instance. - var site = new WikiSite(wikiClient, Input("Wiki site API URL")); - await site.Initialization; - await site.LoginAsync(Input("User name"), Input("Password")); - var rcg = new RecentChangesGenerator(site) - { - TypeFilters = RecentChangesFilterTypes.Create, - PaginationSize = 5, - PatrolledFilter = PropertyFilterOption.WithoutProperty - }; - // List the first unpatrolled result. - var rc = await rcg.EnumItemsAsync().FirstOrDefaultAsync(); - if (rc == null) - { - Console.WriteLine("Nothing to patrol."); - return; - } - Console.WriteLine("Unpatrolled:"); + static async Task HelloRecentChanges() + { + // Create a MediaWiki API client. + var wikiClient = new WikiClient(); + // Create a MediaWiki Site instance. + var site = new WikiSite(wikiClient, "https://en.wikipedia.org/w/api.php"); + await site.Initialization; + var rcg = new RecentChangesGenerator(site) + { + TypeFilters = RecentChangesFilterTypes.Create, + PaginationSize = 50, // We already know we're not going to fetch results as many as 500 or 5000 + // so this will help. + }; + // List the 10 latest new pages + var pages = await rcg.EnumPagesAsync().Take(10).ToListAsync(); + Console.WriteLine("New pages"); + foreach (var p in pages) + Console.WriteLine("{0, -30} {1, 8}B {2}", p, p.ContentLength, p.LastTouched); + // List the 10 latest recent changes + rcg.TypeFilters = RecentChangesFilterTypes.All; + var rcs = await rcg.EnumItemsAsync().Take(10).ToListAsync(); + Console.WriteLine(); + Console.WriteLine("Recent changes"); + foreach (var rc in rcs) Console.WriteLine(rc); - // Show the involved revisions. - if (rc.OldRevisionId > 0 && rc.RevisionId > 0) - { - var rev = await Revision.FetchRevisionsAsync(site, rc.OldRevisionId, rc.RevisionId).ToListAsync(); - // Maybe we'll use some 3rd party diff lib - Console.WriteLine("Before, RevId={0}, {1}", rev[0]!.Id, rev[0]!.TimeStamp); - Console.WriteLine(rev[0]!.Content); - Console.WriteLine("After, RevId={0}, {1}", rev[1]!.Id, rev[1]!.TimeStamp); - Console.WriteLine(rev[1]!.Content); - } - else if (rc.RevisionId > 0) - { - var rev = await Revision.FetchRevisionAsync(site, rc.RevisionId); - Console.WriteLine("RevId={0}, {1}", rev.Id, rev.TimeStamp); - Console.WriteLine(rev.Content); - } - if (Confirm("Mark as patrolled?")) - { - await rc.PatrolAsync(); - Console.WriteLine("The change {0} has been marked as patrolled.", (object) rc.Title ?? rc.Id); - } - } + } - #region Console Utilities + static async Task InteractivePatrol() + { + // Patrol the last unpatrolled change. + // Usually a user should have the patrol right to perform such operation. - static string Input(string prompt) + // Create a MediaWiki API client. + var wikiClient = new WikiClient(); + // Create a MediaWiki Site instance. + var site = new WikiSite(wikiClient, Input("Wiki site API URL")); + await site.Initialization; + await site.LoginAsync(Input("User name"), Input("Password")); + var rcg = new RecentChangesGenerator(site) { - Console.Write(prompt); - Console.Write("> "); - return Console.ReadLine() ?? throw new InvalidOperationException("EOF reached."); + TypeFilters = RecentChangesFilterTypes.Create, + PaginationSize = 5, + PatrolledFilter = PropertyFilterOption.WithoutProperty + }; + // List the first unpatrolled result. + var rc = await rcg.EnumItemsAsync().FirstOrDefaultAsync(); + if (rc == null) + { + Console.WriteLine("Nothing to patrol."); + return; } - - static bool Confirm(string prompt) + Console.WriteLine("Unpatrolled:"); + Console.WriteLine(rc); + // Show the involved revisions. + if (rc.OldRevisionId > 0 && rc.RevisionId > 0) { - Console.Write(prompt); - Console.Write("[Y/N]> "); - while (true) - { - var input = Console.ReadLine()!.ToUpperInvariant(); - if (input == "Y") return true; - if (input == "N") return false; - Console.Write("> "); - } + var rev = await Revision.FetchRevisionsAsync(site, rc.OldRevisionId, rc.RevisionId).ToListAsync(); + // Maybe we'll use some 3rd party diff lib + Console.WriteLine("Before, RevId={0}, {1}", rev[0]!.Id, rev[0]!.TimeStamp); + Console.WriteLine(rev[0]!.Content); + Console.WriteLine("After, RevId={0}, {1}", rev[1]!.Id, rev[1]!.TimeStamp); + Console.WriteLine(rev[1]!.Content); } + else if (rc.RevisionId > 0) + { + var rev = await Revision.FetchRevisionAsync(site, rc.RevisionId); + Console.WriteLine("RevId={0}, {1}", rev.Id, rev.TimeStamp); + Console.WriteLine(rev.Content); + } + if (Confirm("Mark as patrolled?")) + { + await rc.PatrolAsync(); + Console.WriteLine("The change {0} has been marked as patrolled.", (object) rc.Title ?? rc.Id); + } + } + +#region Console Utilities - #endregion + static string Input(string prompt) + { + Console.Write(prompt); + Console.Write("> "); + return Console.ReadLine() ?? throw new InvalidOperationException("EOF reached."); + } + static bool Confirm(string prompt) + { + Console.Write(prompt); + Console.Write("[Y/N]> "); + while (true) + { + var input = Console.ReadLine()!.ToUpperInvariant(); + if (input == "Y") return true; + if (input == "N") return false; + Console.Write("> "); + } } -} + +#endregion + +} \ No newline at end of file diff --git a/Samples/LinqToCargo/LinqToCargo.csproj b/Samples/LinqToCargo/LinqToCargo.csproj index 237adbf56..6d75da442 100644 --- a/Samples/LinqToCargo/LinqToCargo.csproj +++ b/Samples/LinqToCargo/LinqToCargo.csproj @@ -2,9 +2,10 @@ Exe - net5.0 + net6.0 WikiClientLibrary.Samples.LinqToCargo Enable + Enable diff --git a/Samples/LinqToCargo/Program.cs b/Samples/LinqToCargo/Program.cs index 88da56e35..799c31d10 100644 --- a/Samples/LinqToCargo/Program.cs +++ b/Samples/LinqToCargo/Program.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel.DataAnnotations.Schema; -using System.Linq; +using System.ComponentModel.DataAnnotations.Schema; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; using WikiClientLibrary.Cargo.Linq; diff --git a/Samples/ScribuntoInteractive/Program.cs b/Samples/ScribuntoInteractive/Program.cs index 257ed83b3..2d6836344 100644 --- a/Samples/ScribuntoInteractive/Program.cs +++ b/Samples/ScribuntoInteractive/Program.cs @@ -1,149 +1,144 @@ -using System; -using System.Linq; -using System.Reflection; +using System.Reflection; using System.Runtime.InteropServices; -using System.Threading.Tasks; using WikiClientLibrary.Client; using WikiClientLibrary.Scribunto; using WikiClientLibrary.Sites; -namespace WikiClientLibrary.Samples.ScribuntoInteractive +namespace WikiClientLibrary.Samples.ScribuntoInteractive; + +internal static class Program { - internal static class Program - { - internal static async Task Main(string[] args) + internal static async Task Main(string[] args) + { + var endPoint = args.Length > 0 ? args[0] : "https://test2.wikipedia.org/w/api.php"; + using var client = new WikiClient { ClientUserAgent = "ScribuntoConsoleTestApplication1/0.1" }; + var site = new WikiSite(client, endPoint); + await site.Initialization; + var sc = new ScribuntoConsole(site); + await ResetSessionAsync(sc); + var eofShortcut = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Ctrl + Z" : "Ctrl + D"; + Console.WriteLine("* Enter any Lua expression to evaluate. EOF ({0}) to exit.", eofShortcut); + Console.WriteLine("* Precede a line with '=' to evaluate it as an expression or use \x1b[36mprint()\x1b[0m. Use \x1b[36mmw.logObject()\x1b[0m for tables."); + Console.WriteLine("* Use \x1b[36mmw.log()\x1b[0m and \x1b[36mmw.logObject()\x1b[0m in module code to send messages to this console."); + Console.WriteLine("* Enter .help for a list of local commands."); + while (true) { - var endPoint = args.Length > 0 ? args[0] : "https://test2.wikipedia.org/w/api.php"; - using var client = new WikiClient { ClientUserAgent = "ScribuntoConsoleTestApplication1/0.1" }; - var site = new WikiSite(client, endPoint); - await site.Initialization; - var sc = new ScribuntoConsole(site); - await ResetSessionAsync(sc); - var eofShortcut = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "Ctrl + Z" : "Ctrl + D"; - Console.WriteLine("* Enter any Lua expression to evaluate. EOF ({0}) to exit.", eofShortcut); - Console.WriteLine("* Precede a line with '=' to evaluate it as an expression or use \x1b[36mprint()\x1b[0m. Use \x1b[36mmw.logObject()\x1b[0m for tables."); - Console.WriteLine("* Use \x1b[36mmw.log()\x1b[0m and \x1b[36mmw.logObject()\x1b[0m in module code to send messages to this console."); - Console.WriteLine("* Enter .help for a list of local commands."); - while (true) + Console.Write("> "); + var l = Console.ReadLine(); + if (l == null) + break; + if (string.IsNullOrWhiteSpace(l)) + continue; + if (l.StartsWith(".")) { - Console.Write("> "); - var l = Console.ReadLine(); - if (l == null) + if (string.Equals(l, ".exit", StringComparison.OrdinalIgnoreCase)) break; - if (string.IsNullOrWhiteSpace(l)) - continue; - if (l.StartsWith(".")) + await ExecuteCommandAsync(l[1..], sc); + continue; + } + try + { + var result = await sc.EvaluateAsync(l); + if (result.IsNewSession) { - if (string.Equals(l, ".exit", StringComparison.OrdinalIgnoreCase)) - break; - await ExecuteCommandAsync(l[1..], sc); - continue; + Console.WriteLine("---------- Session Cleared ----------"); } - try + if (!string.IsNullOrEmpty(result.Output)) { - var result = await sc.EvaluateAsync(l); - if (result.IsNewSession) - { - Console.WriteLine("---------- Session Cleared ----------"); - } - if (!string.IsNullOrEmpty(result.Output)) - { - Console.WriteLine(result.Output); - } - if (!string.IsNullOrEmpty(result.ReturnValue)) - { - Console.ForegroundColor = ConsoleColor.White; - Console.WriteLine(result.ReturnValue); - Console.ResetColor(); - } + Console.WriteLine(result.Output); } - catch (ScribuntoConsoleException ex) + if (!string.IsNullOrEmpty(result.ReturnValue)) { - if (!string.IsNullOrEmpty(ex.EvaluationResult?.Output)) - { - Console.WriteLine(ex.EvaluationResult.Output); - } - WriteError($"{ex.ErrorCode}: {ex.ErrorMessage}"); + Console.ForegroundColor = ConsoleColor.White; + Console.WriteLine(result.ReturnValue); + Console.ResetColor(); } } - } - - private static void WriteError(string message) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.Error.WriteLine(message); - Console.ResetColor(); - } - - - private static async Task ExecuteCommandAsync(string command, ScribuntoConsole sc) - { - var method = typeof(Program).GetMethods(BindingFlags.Static | BindingFlags.NonPublic) - .FirstOrDefault(m => string.Equals(m.GetCustomAttribute()?.Command, command, StringComparison.OrdinalIgnoreCase)); - if (method == null) + catch (ScribuntoConsoleException ex) { - WriteError("Invalid command: " + command + "."); - return; + if (!string.IsNullOrEmpty(ex.EvaluationResult?.Output)) + { + Console.WriteLine(ex.EvaluationResult.Output); + } + WriteError($"{ex.ErrorCode}: {ex.ErrorMessage}"); } - var result = method.Invoke(null, new object[] { sc }); - if (result is Task t) - await t; } + } - [ConsoleCommand("reset", "Clears the Lua evaluation session.")] - private static async Task ResetSessionAsync(ScribuntoConsole sc) - { - await sc.ResetAsync(); - Console.WriteLine("Initialized Scribunto console on {0} with session ID {1}.", sc.Site.SiteInfo.SiteName, sc.SessionId); - } + private static void WriteError(string message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine(message); + Console.ResetColor(); + } - [ConsoleCommand("help", "Shows the command list.")] - private static void ShowHelp(ScribuntoConsole sc) - { - var commands = typeof(Program).GetMethods(BindingFlags.Static | BindingFlags.NonPublic) - .Select(m => (method: m, attr: m.GetCustomAttribute())) - .Where(t => t.attr != null) - .Select(t => (command: t.attr!.Command, desc: t.attr.Description, method: t.method)) - .OrderBy(t => t.command); - foreach ((string command, string desc, _) in commands) - { - Console.WriteLine(".{0,-15} {1}", command, desc); - } - } - [ConsoleCommand("memory", "Shows the server-side memory usage.")] - private static void ShowMemory(ScribuntoConsole sc) + private static async Task ExecuteCommandAsync(string command, ScribuntoConsole sc) + { + var method = typeof(Program).GetMethods(BindingFlags.Static | BindingFlags.NonPublic) + .FirstOrDefault(m => string.Equals(m.GetCustomAttribute()?.Command, command, StringComparison.OrdinalIgnoreCase)); + if (method == null) { - Console.WriteLine("Memory used / maximum allowed: {0}/{1}", sc.SessionSize, sc.SessionMaxSize); + WriteError("Invalid command: " + command + "."); + return; } + var result = method.Invoke(null, new object[] { sc }); + if (result is Task t) + await t; + } + + [ConsoleCommand("reset", "Clears the Lua evaluation session.")] + private static async Task ResetSessionAsync(ScribuntoConsole sc) + { + await sc.ResetAsync(); + Console.WriteLine("Initialized Scribunto console on {0} with session ID {1}.", sc.Site.SiteInfo.SiteName, sc.SessionId); + } - [ConsoleCommand("exit", "Exits the interactive console.")] - private static void Exit(ScribuntoConsole sc) + [ConsoleCommand("help", "Shows the command list.")] + private static void ShowHelp(ScribuntoConsole sc) + { + var commands = typeof(Program).GetMethods(BindingFlags.Static | BindingFlags.NonPublic) + .Select(m => (method: m, attr: m.GetCustomAttribute())) + .Where(t => t.attr != null) + .Select(t => (command: t.attr!.Command, desc: t.attr.Description, method: t.method)) + .OrderBy(t => t.command); + foreach ((string command, string desc, _) in commands) { - // Stub + Console.WriteLine(".{0,-15} {1}", command, desc); } + } + [ConsoleCommand("memory", "Shows the server-side memory usage.")] + private static void ShowMemory(ScribuntoConsole sc) + { + Console.WriteLine("Memory used / maximum allowed: {0}/{1}", sc.SessionSize, sc.SessionMaxSize); } - [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] - sealed class ConsoleCommandAttribute : Attribute + [ConsoleCommand("exit", "Exits the interactive console.")] + private static void Exit(ScribuntoConsole sc) { + // Stub + } - public string Command { get; } +} - public string? Description { get; } +[AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)] +sealed class ConsoleCommandAttribute : Attribute +{ - public ConsoleCommandAttribute(string command) : this(command, null) - { - } + public string Command { get; } - public ConsoleCommandAttribute(string command, string? description) - { - Command = command; - Description = description; - } + public string? Description { get; } + public ConsoleCommandAttribute(string command) : this(command, null) + { } -} + public ConsoleCommandAttribute(string command, string? description) + { + Command = command; + Description = description; + } + +} \ No newline at end of file diff --git a/Samples/ScribuntoInteractive/ScribuntoInteractive.csproj b/Samples/ScribuntoInteractive/ScribuntoInteractive.csproj index 6e0c14d51..c659c9d11 100644 --- a/Samples/ScribuntoInteractive/ScribuntoInteractive.csproj +++ b/Samples/ScribuntoInteractive/ScribuntoInteractive.csproj @@ -2,9 +2,10 @@ Exe - net5.0 + net6.0 WikiClientLibrary.Samples.ScribuntoInteractive Enable + Enable diff --git a/Samples/WpfTestApplication1/App.xaml.cs b/Samples/WpfTestApplication1/App.xaml.cs index 7da17ac6b..bcd7400ad 100644 --- a/Samples/WpfTestApplication1/App.xaml.cs +++ b/Samples/WpfTestApplication1/App.xaml.cs @@ -1,17 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Configuration; -using System.Data; -using System.Linq; -using System.Threading.Tasks; -using System.Windows; +using System.Windows; -namespace WikiClientLibrary.Samples.WpfTestApplication1 +namespace WikiClientLibrary.Samples.WpfTestApplication1; + +/// +/// App.xaml 的交互逻辑 +/// +public partial class App : Application { - /// - /// App.xaml 的交互逻辑 - /// - public partial class App : Application - { - } } diff --git a/Samples/WpfTestApplication1/MainWindow.xaml.cs b/Samples/WpfTestApplication1/MainWindow.xaml.cs index 7ef7670cd..9097d5f04 100644 --- a/Samples/WpfTestApplication1/MainWindow.xaml.cs +++ b/Samples/WpfTestApplication1/MainWindow.xaml.cs @@ -1,155 +1,143 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; +using System.Diagnostics; using System.IO; -using System.Linq; using System.Net; using System.Resources; -using System.Text; using System.Text.RegularExpressions; -using System.Threading; -using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; -using System.Windows.Data; -using System.Windows.Documents; using System.Windows.Input; -using System.Windows.Media; -using System.Windows.Media.Imaging; using System.Windows.Navigation; using WikiClientLibrary.Client; using WikiClientLibrary.Pages.Parsing; using WikiClientLibrary.Sites; -namespace WikiClientLibrary.Samples.WpfTestApplication1 +namespace WikiClientLibrary.Samples.WpfTestApplication1; + +/// +/// MainWindow.xaml 的交互逻辑 +/// +public partial class MainWindow : Window { - /// - /// MainWindow.xaml 的交互逻辑 - /// - public partial class MainWindow : Window - { - private readonly WikiClient client; - private WikiSite? site; - private CancellationTokenSource? lastNavigationCancellation; - private Regex? articleUrlMatcher; + private readonly WikiClient client; + private WikiSite? site; + private CancellationTokenSource? lastNavigationCancellation; + private Regex? articleUrlMatcher; - public const string EndPointUrl = "https://en.wikipedia.org/w/api.php"; + public const string EndPointUrl = "https://en.wikipedia.org/w/api.php"; - private readonly string pageTemplate; + private readonly string pageTemplate; - public MainWindow() + public MainWindow() + { + InitializeComponent(); + using var s = typeof (MainWindow).Assembly.GetManifestResourceStream("WikiClientLibrary.Samples.WpfTestApplication1.WikiPageTemplate.html"); + if (s == null) throw new MissingManifestResourceException("Wiki page template file is missing."); + using var reader = new StreamReader(s); + pageTemplate = reader.ReadToEnd(); + client = new WikiClient { - InitializeComponent(); - using var s = typeof (MainWindow).Assembly.GetManifestResourceStream("WikiClientLibrary.Samples.WpfTestApplication1.WikiPageTemplate.html"); - if (s == null) throw new MissingManifestResourceException("Wiki page template file is missing."); - using var reader = new StreamReader(s); - pageTemplate = reader.ReadToEnd(); - client = new WikiClient - { - ClientUserAgent = "WpfApplicationTest/1.0 (.NET CLR " + Environment.Version + ")", - }; - } + ClientUserAgent = "WpfApplicationTest/1.0 (.NET CLR " + Environment.Version + ")", + }; + } - private void SetStatus(string? status = null) - { - StatusLabel.Content = status; - } + private void SetStatus(string? status = null) + { + StatusLabel.Content = status; + } - private async Task NavigateCoreAsync(string title, CancellationToken token) + private async Task NavigateCoreAsync(string title, CancellationToken token) + { + TitleTextBox.Text = title; + SetStatus("Navigating to: " + title); + ParsedContentInfo parsed; + Debug.Assert(site != null); + try { - TitleTextBox.Text = title; - SetStatus("Navigating to: " + title); - ParsedContentInfo parsed; - Debug.Assert(site != null); - try - { - parsed = await site.ParsePageAsync(title, ParsingOptions.DisableToc, token); - } - catch (Exception ex) - { - MessageBox.Show(ex.ToString()); - SetStatus(ex.Message); - return; - } - if (token.IsCancellationRequested) goto CLEANUP; - SetStatus("Parsing: " + parsed.Title); - TitleTextBox.Text = parsed.Title; - // Fill the page. - var text = pageTemplate; - void FillParam(string name, string value) => text = text.Replace("", value); - FillParam("SITE NAME", site.SiteInfo.SiteName); - FillParam("DISPLAY TITLE", parsed.DisplayTitle); - FillParam("CONTENT", parsed.Content); - if (token.IsCancellationRequested) goto CLEANUP; - PageFrame.NavigateToString(text); - if (token.IsCancellationRequested) goto CLEANUP; - // Fill TOC. - TocListBox.Items.Clear(); - foreach (var s in parsed.Sections) - { - TocListBox.Items.Add(s); - } - CLEANUP: - SetStatus(); + parsed = await site.ParsePageAsync(title, ParsingOptions.DisableToc, token); } - - private void Navigate(string title) + catch (Exception ex) { - lastNavigationCancellation?.Cancel(); - lastNavigationCancellation = new CancellationTokenSource(); - var task = NavigateCoreAsync(title, lastNavigationCancellation.Token); + MessageBox.Show(ex.ToString()); + SetStatus(ex.Message); + return; } - - private async void Window_Loaded(object sender, RoutedEventArgs e) + if (token.IsCancellationRequested) goto CLEANUP; + SetStatus("Parsing: " + parsed.Title); + TitleTextBox.Text = parsed.Title; + // Fill the page. + var text = pageTemplate; + void FillParam(string name, string value) => text = text.Replace("", value); + FillParam("SITE NAME", site.SiteInfo.SiteName); + FillParam("DISPLAY TITLE", parsed.DisplayTitle); + FillParam("CONTENT", parsed.Content); + if (token.IsCancellationRequested) goto CLEANUP; + PageFrame.NavigateToString(text); + if (token.IsCancellationRequested) goto CLEANUP; + // Fill TOC. + TocListBox.Items.Clear(); + foreach (var s in parsed.Sections) { - // Play with some real wiki. - SetStatus("Loading wiki site info: " + EndPointUrl); - site = new WikiSite(client, EndPointUrl); - await site.Initialization; - articleUrlMatcher = new Regex(Regex.Escape(site.SiteInfo.ArticlePath).Replace(@"\$1", "(.+?)") + "$"); - Navigate(site.SiteInfo.MainPage); + TocListBox.Items.Add(s); } + CLEANUP: + SetStatus(); + } - private void PageFrame_LoadCompleted(object sender, NavigationEventArgs e) - { + private void Navigate(string title) + { + lastNavigationCancellation?.Cancel(); + lastNavigationCancellation = new CancellationTokenSource(); + var task = NavigateCoreAsync(title, lastNavigationCancellation.Token); + } - } + private async void Window_Loaded(object sender, RoutedEventArgs e) + { + // Play with some real wiki. + SetStatus("Loading wiki site info: " + EndPointUrl); + site = new WikiSite(client, EndPointUrl); + await site.Initialization; + articleUrlMatcher = new Regex(Regex.Escape(site.SiteInfo.ArticlePath).Replace(@"\$1", "(.+?)") + "$"); + Navigate(site.SiteInfo.MainPage); + } - private void TitleTextBox_KeyDown(object sender, KeyEventArgs e) + private void PageFrame_LoadCompleted(object sender, NavigationEventArgs e) + { + + } + + private void TitleTextBox_KeyDown(object sender, KeyEventArgs e) + { + if (e.Key == Key.Enter) { - if (e.Key == Key.Enter) - { - Navigate(TitleTextBox.Text); - } + Navigate(TitleTextBox.Text); } + } - private void TocListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + private void TocListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (e.AddedItems != null && e.AddedItems.Count > 0) { - if (e.AddedItems != null && e.AddedItems.Count > 0) + if (e.AddedItems[0] is ContentSectionInfo section) { - if (e.AddedItems[0] is ContentSectionInfo section) - { - dynamic doc = PageFrame.Document; - var anchor = doc?.getElementById(section.Anchor); - if (anchor != null && !Convert.IsDBNull(anchor)) - anchor.ScrollIntoView(true); - } + dynamic doc = PageFrame.Document; + var anchor = doc?.getElementById(section.Anchor); + if (anchor != null && !Convert.IsDBNull(anchor)) + anchor!.ScrollIntoView(true); } } + } - private void PageFrame_Navigating(object sender, NavigatingCancelEventArgs e) + private void PageFrame_Navigating(object sender, NavigatingCancelEventArgs e) + { + if (e.Uri != null && articleUrlMatcher != null) { - if (e.Uri != null && articleUrlMatcher != null) + // Actual navigation is to take place. + TocListBox.Items.Clear(); + var titleMatch = articleUrlMatcher.Match(e.Uri.ToString()); + if (titleMatch.Success) { - // Actual navigation is to take place. - TocListBox.Items.Clear(); - var titleMatch = articleUrlMatcher.Match(e.Uri.ToString()); - if (titleMatch.Success) - { - e.Cancel = true; - Navigate(WebUtility.UrlDecode(titleMatch.Groups[1].Value)); - } + e.Cancel = true; + Navigate(WebUtility.UrlDecode(titleMatch.Groups[1].Value)); } } } diff --git a/Samples/WpfTestApplication1/WpfTestApplication1.csproj b/Samples/WpfTestApplication1/WpfTestApplication1.csproj index af75ab44e..f3ad23edb 100644 --- a/Samples/WpfTestApplication1/WpfTestApplication1.csproj +++ b/Samples/WpfTestApplication1/WpfTestApplication1.csproj @@ -2,10 +2,11 @@ WinExe - net5.0-windows + net6.0-windows WikiClientLibrary.Samples.WpfTestApplication1 true Enable + Enable diff --git a/UnitTestProject1/UnitTestProject1.csproj b/UnitTestProject1/UnitTestProject1.csproj index 0d31ea9da..33e2326f1 100644 --- a/UnitTestProject1/UnitTestProject1.csproj +++ b/UnitTestProject1/UnitTestProject1.csproj @@ -2,7 +2,7 @@ - netcoreapp3.1;net5.0 + netcoreapp3.1;net6.0 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} WikiClientLibrary.Tests.UnitTestProject1 Enable diff --git a/WikiClientLibrary.Commons/CI/PrepEnv.ps1 b/WikiClientLibrary.Commons/CI/PrepEnv.ps1 index e7541998a..2b58a561b 100644 --- a/WikiClientLibrary.Commons/CI/PrepEnv.ps1 +++ b/WikiClientLibrary.Commons/CI/PrepEnv.ps1 @@ -18,52 +18,13 @@ function CheckLastExitCode($ExitCode = $LASTEXITCODE) { } } -function checkDotNetSdkVersions { - [CmdletBinding()] param([string] $Channel) - - [string[]]$sdks = dotnet --list-sdks - - $matchingSdks = $sdks | ? { $_ -match "^$Channel\." } - - Write-Host "Installed .NET Core SDK $Channel.x:" - Write-Host $matchingSdks - - if ($matchingSdks) { - return $true - } - else { - Write-Error "No matching SDK installed for channel: $Channel." - return $false - } -} - # Assumes $PWD is the repo root if ($IsLinux) { if ($SHFB) { Write-Error "SHFB is not supported on Linux." } - if (-not (checkDotNetSdkVersions -Channel 3 -ErrorAction Continue)) { - sudo apt install dotnet-sdk-3.1 - CheckLastExitCode - checkDotNetSdkVersions -Channel 3 - } - if (-not (checkDotNetSdkVersions -Channel 5 -ErrorAction Continue)) { - sudo apt install dotnet-sdk-5.0 - CheckLastExitCode - checkDotNetSdkVersions -Channel 5 - } } elseif ($IsWindows) { - # dotnet - Invoke-WebRequest 'https://dot.net/v1/dotnet-install.ps1' -OutFile 'DotNet-Install.ps1' - if (-not (checkDotNetSdkVersions -Channel 3 -ErrorAction Continue)) { - ./DotNet-Install.ps1 -Version 3.1.10 - checkDotNetSdkVersions -Channel 3 - } - if (-not (checkDotNetSdkVersions -Channel 5 -ErrorAction Continue)) { - ./DotNet-Install.ps1 -Version 5.0 - checkDotNetSdkVersions -Channel 5 - } # SHFB if ($SHFB) { Write-Host "Downloading SHFB."