diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 90153f4..410c9c3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -13,7 +13,7 @@ jobs: steps: - uses: actions/checkout@main - name: Run - uses: GabrielBB/xvfb-action@v1 + uses: coactions/setup-xvfb@main with: run: dotnet run env: diff --git a/Note163Checkin.csproj b/Note163Checkin.csproj index d1fca16..622a794 100644 --- a/Note163Checkin.csproj +++ b/Note163Checkin.csproj @@ -2,14 +2,14 @@ Exe - net6.0 + net7.0 enable disable - - + + diff --git a/Program.cs b/Program.cs index 2846c71..9e29ca3 100644 --- a/Program.cs +++ b/Program.cs @@ -3,12 +3,10 @@ using StackExchange.Redis; using System.Text.Json; -HttpClient _scClient = null; +const int TIMEOUT_MS = 60_000; + Conf _conf = Deserialize(GetEnvValue("CONF")); -if (!string.IsNullOrWhiteSpace(_conf.ScKey)) -{ - _scClient = new HttpClient(); -} +HttpClient _scClient = new(); #region redis @@ -45,7 +43,7 @@ if (isInvalid) { - cookie = await Login(user.Username, user.Password); + cookie = await GetCookie(user); (isInvalid, result) = await IsInvalid(cookie); Console.WriteLine("login获取cookie,状态:{0}", isInvalid ? "无效" : "有效"); if (isInvalid) @@ -105,7 +103,7 @@ return (result.Contains("error", StringComparison.OrdinalIgnoreCase), result); } -async Task Login(string username, string password) +async Task GetCookie(User user) { var launchOptions = new LaunchOptions { @@ -114,32 +112,76 @@ async Task Login(string username, string password) ExecutablePath = @"/usr/bin/google-chrome" }; var browser = await Puppeteer.LaunchAsync(launchOptions); - Page page = await browser.DefaultContext.NewPageAsync(); - - await page.GoToAsync("https://note.youdao.com/web", 60_000); - await page.WaitForSelectorAsync(".login-btn", new WaitForSelectorOptions { Visible = true }); - await page.TypeAsync(".login-username", username); - await page.TypeAsync(".login-password", password); - await Task.Delay(5_000); - await page.ClickAsync(".login-btn"); - await page.WaitForSelectorAsync("ydoc-app", new WaitForSelectorOptions { Visible = true }); - - var client = await page.Target.CreateCDPSessionAsync(); - var ckObj = await client.SendAsync("Network.getAllCookies"); - var cks = ckObj.Value("cookies") - .Where(p => p.Value("domain").Contains("note.youdao.com")) - .Select(p => $"{p.Value("name")}={p.Value("value")}"); - - await browser.DisposeAsync(); - return string.Join(';', cks); + IPage page = await browser.DefaultContext.NewPageAsync(); + + await page.GoToAsync("https://note.youdao.com/web", TIMEOUT_MS); + + bool isLogin = false; + string cookie = "fail"; + try + { + #region 登录 + + //登录 + _ = Login(page, user); + int totalDelayMs = 0, delayMs = 100; + while (true) + { + if ((isLogin = IsLogin(page)) + || totalDelayMs > TIMEOUT_MS) + { + break; + } + await Task.Delay(delayMs); + totalDelayMs += delayMs; + } + + if (isLogin) + { + var client = await page.Target.CreateCDPSessionAsync(); + var ckObj = await client.SendAsync("Network.getAllCookies"); + var cks = ckObj.Value("cookies") + .Where(p => p.Value("domain").Contains("note.youdao.com")) + .Select(p => $"{p.Value("name")}={p.Value("value")}"); + cookie = string.Join(';', cks); + } + + #endregion + } + catch (Exception ex) + { + cookie = "ex"; + Console.WriteLine($"处理Page时出现异常!{ex.Message};{ex.StackTrace}"); + } + finally + { + await browser.DisposeAsync(); + } + + return cookie; } +async Task Login(IPage page, User user) +{ + try + { + string js = await _scClient.GetStringAsync(_conf.JsUrl); + await page.EvaluateExpressionAsync(js.Replace("@U", user.Username).Replace("@P", user.Password)); + } + catch (Exception ex) + { + Console.WriteLine($"Login时出现异常!{ex.Message}. {ex.StackTrace}"); + } +} + +bool IsLogin(IPage page) => !page.Url.Contains(_conf.LoginStr, StringComparison.OrdinalIgnoreCase); + async Task Notify(string msg, bool isFailed = false) { Console.WriteLine(msg); if (_conf.ScType == "Always" || (isFailed && _conf.ScType == "Failed")) { - await _scClient?.GetAsync($"https://sc.ftqq.com/{_conf.ScKey}.send?text={msg}"); + await _scClient.GetAsync($"https://sc.ftqq.com/{_conf.ScKey}.send?text={msg}"); } } @@ -160,6 +202,8 @@ class Conf public string ScType { get; set; } public string RdsServer { get; set; } public string RdsPwd { get; set; } + public string JsUrl { get; set; } = "https://github.com/BlueHtml/pub/raw/main/code/js/note163login.js"; + public string LoginStr { get; set; } = "signIn"; } class User diff --git a/README.md b/README.md index 464a983..1b0ac7e 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,8 @@ "RdsPwd": "ppp" //redis密码,选填 } ``` - `RdsServer`和`RdsPwd`是选填的,用于配置redis,来存储cookie。后续可以重用这个cookie,避免频繁登录账号。建议配置一下,可以使用[redislabs](https://app.redislabs.com/)的免费套餐。 + - `RdsServer`和`RdsPwd`是选填的,用于配置redis,来存储cookie。后续可以重用这个cookie,避免频繁登录账号。建议配置一下,可以使用[redislabs](https://app.redislabs.com/)的免费套餐。 + - `JsUrl`和`LoginStr`这2个字段是用来登录账号的,已经设置好了默认值,**不建议**修改,所以上面的配置中没有列出来。详细请查看源码。 **步骤图示如下:** ![添加secret](https://img.guoqianfan.com/note/2020/08/添加secret.png)