Skip to content

Commit

Permalink
添加项目文件。
Browse files Browse the repository at this point in the history
  • Loading branch information
BlueHtml committed Apr 3, 2022
1 parent 0e3202e commit 211c2c6
Show file tree
Hide file tree
Showing 5 changed files with 301 additions and 0 deletions.
20 changes: 20 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
name: Run

on:
workflow_dispatch:
repository_dispatch:

jobs:
build:

if: github.actor == github.repository_owner
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@main
- name: Run
uses: GabrielBB/xvfb-action@v1
with:
run: dotnet run
env:
CONF: ${{ secrets.CONF }}
15 changes: 15 additions & 0 deletions Note163Checkin.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net6.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PuppeteerSharp" Version="6.2.0" />
<PackageReference Include="StackExchange.Redis" Version="2.5.43" />
</ItemGroup>

</Project>
25 changes: 25 additions & 0 deletions Note163Checkin.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.1.32328.378
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Note163Checkin", "Note163Checkin.csproj", "{A5132704-C07F-4689-8D84-A9F3EBEC6947}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A5132704-C07F-4689-8D84-A9F3EBEC6947}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A5132704-C07F-4689-8D84-A9F3EBEC6947}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A5132704-C07F-4689-8D84-A9F3EBEC6947}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A5132704-C07F-4689-8D84-A9F3EBEC6947}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A5F3DCA6-F4AC-4CE1-B72E-D85664BA280A}
EndGlobalSection
EndGlobal
185 changes: 185 additions & 0 deletions Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
using Newtonsoft.Json.Linq;
using PuppeteerSharp;
using StackExchange.Redis;
using System.Text.Json;

HttpClient _scClient = null;
Conf _conf = Deserialize<Conf>(GetEnvValue("CONF"));
if (!string.IsNullOrWhiteSpace(_conf.ScKey))
{
_scClient = new HttpClient();
}

#region redis

ConnectionMultiplexer redis = ConnectionMultiplexer.Connect($"{_conf.RdsServer},password={_conf.RdsPwd},name=Note163Checkin,defaultDatabase=0,allowadmin=true,abortConnect=false");
IDatabase db = redis.GetDatabase();
bool isRedis = db.IsConnected("test");
Console.WriteLine("redis:{0}", isRedis ? "有效" : "无效");

#endregion

Console.WriteLine("有道云笔记签到开始运行...");
for (int i = 0; i < _conf.Users.Length; i++)
{
User user = _conf.Users[i];
string title = $"账号 {i + 1}: {user.Task} ";
Console.WriteLine($"共 {_conf.Users.Length} 个账号,正在运行{title}...");

#region 获取cookie

string cookie = string.Empty;
bool isInvalid = true; string result = string.Empty;

string redisKey = $"Note163_{user.Username}";
if (isRedis)
{
var redisValue = await db.StringGetAsync(redisKey);
if (redisValue.HasValue)
{
cookie = redisValue.ToString();
(isInvalid, result) = await IsInvalid(cookie);
Console.WriteLine("redis获取cookie,状态:{0}", isInvalid ? "无效" : "有效");
}
}

if (isInvalid)
{
cookie = await Login(user.Username, user.Password);
(isInvalid, result) = await IsInvalid(cookie);
Console.WriteLine("login获取cookie,状态:{0}", isInvalid ? "无效" : "有效");
if (isInvalid)
{//Cookie失效
await Notify($"{title}Cookie失效,请检查登录状态!", true);
continue;
}
}

if (isRedis)
{
Console.WriteLine($"redis更新cookie:{await db.StringSetAsync(redisKey, cookie)}");
}

#endregion

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "ynote-android");
client.DefaultRequestHeaders.Add("Cookie", cookie);

long space = 0;
space += Deserialize<YdNoteRsp>(result).RewardSpace;

//签到
result = await (await client.PostAsync("https://note.youdao.com/yws/mapi/user?method=checkin", null))
.Content.ReadAsStringAsync();
space += Deserialize<YdNoteRsp>(result).Space;

//看广告
for (int j = 0; j < 3; j++)
{
result = await (await client.PostAsync("https://note.youdao.com/yws/mapi/user?method=adPrompt", null))
.Content.ReadAsStringAsync();
space += Deserialize<YdNoteRsp>(result).Space;
}

//看视频广告
for (int j = 0; j < 3; j++)
{
result = await (await client.PostAsync("https://note.youdao.com/yws/mapi/user?method=adRandomPrompt", null))
.Content.ReadAsStringAsync();
space += Deserialize<YdNoteRsp>(result).Space;
}

await Notify($"有道云笔记{title}签到成功,共获得空间 {space / 1048576} M");
}
Console.WriteLine("签到运行完毕");

async Task<(bool isInvalid, string result)> IsInvalid(string cookie)
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "ynote-android");
client.DefaultRequestHeaders.Add("Cookie", cookie);
//每日打开客户端(即登陆)
string result = await (await client.PostAsync("https://note.youdao.com/yws/api/daupromotion?method=sync", null))
.Content.ReadAsStringAsync();
return (result.Contains("error", StringComparison.OrdinalIgnoreCase), result);
}

async Task<string> Login(string username, string password)
{
var launchOptions = new LaunchOptions
{
Headless = false,
DefaultViewport = null,
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<JArray>("cookies")
.Where(p => p.Value<string>("domain").Contains("note.youdao.com"))
.Select(p => $"{p.Value<string>("name")}={p.Value<string>("value")}");

await browser.DisposeAsync();
return string.Join(';', cks);
}

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}");
}
}

T Deserialize<T>(string json) => JsonSerializer.Deserialize<T>(json, new JsonSerializerOptions
{
PropertyNameCaseInsensitive = true,
ReadCommentHandling = JsonCommentHandling.Skip
});

string GetEnvValue(string key) => Environment.GetEnvironmentVariable(key);

#region Conf

class Conf
{
public User[] Users { get; set; }
public string ScKey { get; set; }
public string ScType { get; set; }
public string RdsServer { get; set; }
public string RdsPwd { get; set; }
}

class User
{
public string Task { get; set; }
public string Username { get; set; }
public string Password { get; set; }
}

#endregion

class YdNoteRsp
{
/// <summary>
/// Sync奖励空间
/// </summary>
public int RewardSpace { get; set; }

/// <summary>
/// 其他奖励空间
/// </summary>
public int Space { get; set; }
}
56 changes: 56 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Note163Checkin

## 一、Fork 仓库

**点击右上角的`Fork`**
![fork](https://img.guoqianfan.com/note/2020/08/fork.png)

## 二、添加 Secret

**`Settings`->`Secrets`->`New secret`,添加以下Secret:**
- `Conf`:其值如下:
```json
{
"Users": [{
"Task": "CC", //自定义名字,选填
"Username": "[email protected]", //账号
"Password": "aaa" //密码
}, {
"Task": "MM",
"Username": "[email protected]",
"Password": "111"
}
],
"ScKey": "", //server酱sckey,不填不开启
"ScType": "Failed", //通知类型. Always:始终通知; Failed:失败时通知; 不填/其他:不通知;
"RdsServer": "xxx.redislabs.com:1234", //redis地址,选填
"RdsPwd": "ppp" //redis密码,选填
}
```
`RdsServer`和`RdsPwd`是选填的,用于配置redis,来存储cookie。后续可以重用这个cookie,避免频繁登录账号。建议配置一下,可以使用[redislabs](https://app.redislabs.com/)的免费套餐。

**步骤图示如下:**
![添加secret](https://img.guoqianfan.com/note/2020/08/添加secret.png)

## 三、运行

**`Actions`->`Run`->`Run workflow`**:
![run-workflow](https://img.guoqianfan.com/note/2020/08/run-workflow.png)

**注意**:本项目**不会**自动运行,需要自行在`.github/workflows/main.yml`添加定时任务。

## 四、查看运行结果

**`Actions`->`Run`->`build`**,能看到下图,表示运行成功
![查看action运行记录](https://img.guoqianfan.com/note/2020/08/查看action运行记录.png)

## 注意事项

24小时内频繁登录可能会触发验证,程序就会登录失败。此时需要在网页上手动登录一次(需要输入验证码),登录成功后再次运行本程序即可。

## 参考

参考了以下项目:
- [ydao](https://github.com/yygtboy/ydao/)
- [node-script](https://github.com/SunSeekerX/node-script)
- [youdaoyun](https://github.com/hezhizheng/youdaoyun)

0 comments on commit 211c2c6

Please sign in to comment.