From b180bd4595bd905dfa47584cf0d940c07c0ebf82 Mon Sep 17 00:00:00 2001 From: andy840119 Date: Sun, 14 Jan 2024 11:24:47 +0800 Subject: [PATCH] Separate the logic for get the pull-request info from the url. --- .../Changelog/ChangelogPullRequestInfoTest.cs | 37 +++++++ .../Changelog/ChangeLogMarkdownContainer.cs | 56 +++-------- .../Changelog/ChangelogPullRequestInfo.cs | 97 +++++++++++++++++++ 3 files changed, 147 insertions(+), 43 deletions(-) create mode 100644 osu.Game.Rulesets.Karaoke.Tests/Overlays/Changelog/ChangelogPullRequestInfoTest.cs create mode 100644 osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs diff --git a/osu.Game.Rulesets.Karaoke.Tests/Overlays/Changelog/ChangelogPullRequestInfoTest.cs b/osu.Game.Rulesets.Karaoke.Tests/Overlays/Changelog/ChangelogPullRequestInfoTest.cs new file mode 100644 index 000000000..bce06d127 --- /dev/null +++ b/osu.Game.Rulesets.Karaoke.Tests/Overlays/Changelog/ChangelogPullRequestInfoTest.cs @@ -0,0 +1,37 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System.Linq; +using NUnit.Framework; +using osu.Game.Rulesets.Karaoke.Overlays.Changelog; + +namespace osu.Game.Rulesets.Karaoke.Tests.Overlays.Changelog; + +public class ChangelogPullRequestInfoTest +{ + [TestCase("#2152@andy840119", new[] { 2152 }, new[] { "andy840119" })] + [TestCase("#2152", new[] { 2152 }, new string[] { })] + [TestCase("@andy840119", new int[] { }, new[] { "andy840119" })] + [TestCase("#2152#2153", new[] { 2152, 2153 }, new string[] { })] + [TestCase("#2152#2152", new[] { 2152 }, new string[] { })] + [TestCase("@andy@andy840119", new int[] { }, new[] { "andy", "andy840119" })] + [TestCase("@andy840119@andy840119", new int[] { }, new[] { "andy840119" })] + [TestCase("https://raw.githubusercontent.com/karaoke-dev/karaoke-dev.github.io/master/content/changelog/2023.1212/#2152@andy840119", new[] { 2152 }, new[] { "andy840119" })] // the actual data that will be get in this method. + public void TestGetPullRequestInfoFromLink(string url, int[] expectedPrs, string[] expectedUserNames) + { + var result = ChangelogPullRequestInfo.GetPullRequestInfoFromLink("karaoke", url)!; + + Assert.AreEqual(expectedPrs, result.PullRequests.Select(x => x.Number)); + Assert.AreEqual(expectedUserNames, result.Users.Select(x => x.UserName)); + } + + [TestCase("unknown_repo", "#2152@andy840119")] // "unknown_repo" does not in the repo list. + [TestCase("karaoke", "")] // there's no pr number or username. + [TestCase("karaoke", "hello")] // invalid pr number or username. + [TestCase("karaoke", "#aaa")] // invalid pr number. + public void TestTestGetPullRequestInfoFromLinkWithNull(string link, string url) + { + var result = ChangelogPullRequestInfo.GetPullRequestInfoFromLink(link, url); + Assert.IsNull(result); + } +} diff --git a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs index 66d094fab..c1ce7c354 100644 --- a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs +++ b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangeLogMarkdownContainer.cs @@ -2,16 +2,13 @@ // See the LICENCE file in the repository root for full licence text. using System; -using System.Collections.Generic; using System.Linq; -using System.Text.RegularExpressions; using Markdig.Syntax.Inlines; using osu.Framework.Graphics; using osu.Framework.Graphics.Sprites; using osu.Framework.Layout; using osu.Game.Graphics; using osu.Game.Graphics.Containers.Markdown; -using osu.Game.Rulesets.Karaoke.Extensions; using osu.Game.Rulesets.Karaoke.Online.API.Requests.Responses; using osuTK; @@ -40,78 +37,51 @@ public partial class ChangeLogMarkdownTextFlowContainer : OsuMarkdownTextFlowCon { protected override void AddImage(LinkInline linkInline) => AddDrawable(new ChangeLogMarkdownImage(linkInline)); - private readonly IDictionary githubUrls = new Dictionary - { - { "karaoke", "https://github.com/karaoke-dev/karaoke/" }, - { "edge", "https://github.com/karaoke-dev/karaoke/" }, - { "github.io", "https://github.com/karaoke-dev/karaoke-dev.github.io/" }, - { "launcher", "https://github.com/karaoke-dev/launcher/" }, - { "sample", "https://github.com/karaoke-dev/sample-beatmap/" }, - { "microphone-package", "https://github.com/karaoke-dev/osu-framework-microphone/" }, - { "font-package", "https://github.com/karaoke-dev/osu-framework-font/" }, - }; - protected override void AddLinkText(string text, LinkInline linkInline) { if (linkInline.Url == null) return; - if (!githubUrls.ContainsKey(text)) + var pullRequestInfo = ChangelogPullRequestInfo.GetPullRequestInfoFromLink(text, linkInline.Url); + + if (pullRequestInfo == null) { base.AddLinkText(text, linkInline); return; } - var baseUri = new Uri(githubUrls[text]); - - // Get hash tag with number - const string issue_regex = "#(?[0-9]+)|@(?[0-9A-z]+)"; - var result = Regex.Matches(linkInline.Url, issue_regex, RegexOptions.IgnoreCase); - - if (!result.Any()) - return; + var pullRequests = pullRequestInfo.PullRequests; + var users = pullRequestInfo.Users; - // add issue if has user - string[] issues = result.Select(x => x.GetGroupValue("issue")).Where(x => !string.IsNullOrEmpty(x)).ToArray(); - - if (issues.Any()) + if (pullRequests.Any()) { AddText("("); - foreach (string issue in issues) + foreach (var pullRequest in pullRequests) { - if (string.IsNullOrEmpty(issue)) - continue; - - AddDrawable(new OsuMarkdownLinkText($"{text}#{issue}", new LinkInline + AddDrawable(new OsuMarkdownLinkText($"{text}#{pullRequest.Number}", new LinkInline { - Url = new Uri(baseUri, $"pull/{issue}").AbsoluteUri, + Url = pullRequest.Url, })); - if (issue != issues.LastOrDefault()) + if (pullRequest != pullRequests.LastOrDefault()) AddText(", "); } AddText(")"); } - // add use name if has user - var usernames = result.Select(x => x.GetGroupValue("username")).Where(x => !string.IsNullOrEmpty(x)); - - foreach (string user in usernames) + foreach (var user in users) { - if (string.IsNullOrEmpty(user)) - return; - var textScale = new Vector2(0.7f); AddText(" by ", t => { t.Scale = textScale; t.Padding = new MarginPadding { Top = 6 }; }); - AddDrawable(new UserLinkText(user, new LinkInline + AddDrawable(new UserLinkText(user.UserName, new LinkInline { - Url = $"https://github.com/{user}", + Url = user.UserUrl, }) { Scale = textScale, diff --git a/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs new file mode 100644 index 000000000..cab7994bc --- /dev/null +++ b/osu.Game.Rulesets.Karaoke/Overlays/Changelog/ChangelogPullRequestInfo.cs @@ -0,0 +1,97 @@ +// Copyright (c) andy840119 . Licensed under the GPL Licence. +// See the LICENCE file in the repository root for full licence text. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text.RegularExpressions; +using osu.Game.Rulesets.Karaoke.Extensions; + +namespace osu.Game.Rulesets.Karaoke.Overlays.Changelog; + +public class ChangelogPullRequestInfo +{ + private static readonly IDictionary repo_urls = new Dictionary + { + { "karaoke", "https://github.com/karaoke-dev/karaoke/" }, + { "edge", "https://github.com/karaoke-dev/karaoke/" }, + { "github.io", "https://github.com/karaoke-dev/karaoke-dev.github.io/" }, + { "launcher", "https://github.com/karaoke-dev/launcher/" }, + { "sample", "https://github.com/karaoke-dev/sample-beatmap/" }, + { "microphone-package", "https://github.com/karaoke-dev/osu-framework-microphone/" }, + { "font-package", "https://github.com/karaoke-dev/osu-framework-font/" }, + }; + + public PullRequestInfo[] PullRequests { get; set; } = Array.Empty(); + + public UserInfo[] Users { get; set; } = Array.Empty(); + + public class PullRequestInfo + { + public int Number { get; set; } + + public string Url { get; set; } = string.Empty; + } + + public class UserInfo + { + public string UserName { get; set; } = string.Empty; + + public string UserUrl => $"https://github.com/{UserName}"; + } + + /// + /// Trying to parse the pull-request info from the url. + /// + /// + /// #2152@andy840119
+ /// #2152
+ /// #2152#2153
+ /// @andy840119
+ /// @andy@andy840119 + ///
+ /// Link text + /// Link url + /// + public static ChangelogPullRequestInfo? GetPullRequestInfoFromLink(string text, string url) + { + if (!repo_urls.ContainsKey(text)) + return null; + + const string pull_request_key = "pull_request"; + const string username_key = "username"; + const string pull_request_regex = $"#(?<{pull_request_key}>[0-9]+)|@(?<{username_key}>[0-9A-z]+)"; + + // note: should have at least one pr number or one username, + var result = Regex.Matches(url, pull_request_regex, RegexOptions.IgnoreCase); + if (!result.Any()) + return null; + + // get pull-request or username + var prs = result.Select(x => x.GetGroupValue(pull_request_key)) + .Where(x => !string.IsNullOrEmpty(x)) + .Distinct(); + var usernames = result.Select(x => x.GetGroupValue(username_key)) + .Where(x => !string.IsNullOrEmpty(x)) + .Distinct(); + + return new ChangelogPullRequestInfo + { + PullRequests = prs.Select(x => generatePullRequestInfo(repo_urls[text], x)).ToArray(), + Users = usernames.Select(generateUserInfo).ToArray(), + }; + + static PullRequestInfo generatePullRequestInfo(string url, string pr) => + new() + { + Number = int.Parse(pr), + Url = new Uri(new Uri(url), $"pull/{pr}").AbsoluteUri, + }; + + static UserInfo generateUserInfo(string username) => + new() + { + UserName = username, + }; + } +}