From 0b65918d4630f5bed6510a38524bf4052eb095e0 Mon Sep 17 00:00:00 2001
From: layui0320 <58420846@qq.com>
Date: Sun, 21 Aug 2022 21:46:33 +0800
Subject: [PATCH 01/12] =?UTF-8?q?Docker=E9=83=A8=E7=BD=B2=E6=96=87?=
 =?UTF-8?q?=E6=A1=A3=E8=A1=A5=E5=85=85&=E4=BF=AE=E6=94=B9=20(#253)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* Docker部署文档补充&修改

* Docker部署文档补充&修改

* Docker部署文档补充&修改
---
 docker/README.md               | 115 +++++++++++++++-----
 docker/sample/appsettings.json | 191 +++++++++++++++++++++++++++++++++
 2 files changed, 279 insertions(+), 27 deletions(-)
 create mode 100644 docker/sample/appsettings.json

diff --git a/docker/README.md b/docker/README.md
index 4731bb7d8..f280363cb 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -2,60 +2,120 @@
 <!-- TOC depthFrom:2 -->
 
 - [1. 前期工作](#1-前期工作)
-    - [1.1. docker环境](#11-docker环境)
-    - [1.2. 良好的网络](#12-良好的网络)
-- [2. 生成容器并运行](#2-生成容器并运行)
-    - [2.1. 本地创建文件](#21-本地创建文件)
-    - [2.2. 编辑文件内容,填入相关配置](#22-编辑文件内容填入相关配置)
-    - [2.3. 启动并运行容器](#23-启动并运行容器)
-- [3. 自己构建镜像(非必须)](#3-自己构建镜像非必须)
-- [4. 其他](#4-其他)
+    - [1.1. Docker环境](#11-docker环境)
+	- [1.2. 须知](#12-须知)
+- [2. Docker Compose版](#2-docker-compose版推荐)
+- [3. Docker版](#3-docker版)
+	- [3.1. Docker启动](#31-docker启动)
+	- [3.2. 通过Watchtower手动更新容器](#32-通过watchtower手动更新容器)
+- [4. 自己构建镜像(非必须)](#4-自己构建镜像非必须)
+- [5. 其他](#5-其他)
+
+
+
+
 
 <!-- /TOC -->
 ## 1. 前期工作
 
-### 1.1. docker环境
+### 1.1. Docker环境
 
-请确认已安装了docker所需环境([docker](https://docs.docker.com/get-docker/)和[docker compose](https://docs.docker.com/compose/cli-command/))。
+请确认已安装了Docker所需环境([Docker](https://docs.docker.com/get-docker/)和[Docker Compose](https://docs.docker.com/compose/cli-command/))。
 
 Window系统推荐使用Docker Desktop,官方下载安装包,一路鼠标点下去就能装好,运行时也有可视化页面。
 
 安装完成后,请执行`docker --version`检查`docker`是否安装成功,请执行`docker compose version`检查`docker compose`是否安装成功。
 
-### 1.2. 良好的网络
+### 1.2. 须知
 
-第一次运行,可能时间比较长,因为本地没有镜像缓存,第二次之后构建速度就很快了。
 
-## 2. 生成容器并运行
+每次容器启动会去跑一遍 Test 任务,用于测试 Cookie 。其他任务由设定的cron来指定定时触发,
+
+想手动运行某任务的话,请进入容器后输入相应命令来启动执行。
+
 
-推荐使用 docker-compose 来运行容器,步骤如下:
 
-### 2.1. 本地创建文件
-在本地任意文件夹下,创建一个目录 `bilibili_tool` ,在其下新建`docker-compose.yml`文件和`my_crontab`文件,文件结构如下:
+## 2. Docker-Compose版(推荐) 
+在本地任意文件夹下,创建一个目录 `bilibili_tool` 
 
 ```
+# 下载项目里面的模板,`my_crontab`文件以及`docker-compose.yml`文件
+
+# 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
+wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/my_crontab
+
+# 根据 docker-compose.yaml 里面的注释编辑所需配置,`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
+wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/docker-compose.yml
+
+最终文件结构如下:
 bilibili_tool
 ├── docker-compose.yml
 └── my_crontab
+
+# 启动 docker-compose
+docker-compose up -d
+
+# 停止 docker-compose
+docker-compose stop
+
+# 查看实时日志
+docker logs -f bilibili_tool_pro
+
+# 进入容器
+docker exec -it bilibili_tool_pro /bin/bash
+
+# 手动更新容器
+docker-compose pull && docker-compose up -d
+
 ```
 
-### 2.2. 编辑文件内容,填入相关配置
-`docker-compose.yml`的文件内容请拷贝 [默认docker-compose.yml](../docker/sample/docker-compose.yml) 内容。`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
 
-`my_crontab`的文件内容请拷贝 [默认my_crontab](../docker/sample/my_crontab) 内容,注意末尾有个换行不要丢了。
+## 3. Docker版
 
-### 2.3. 启动并运行容器
-在当前目录(有docker-compose.yml的目录)执行启动容器命令:`docker compose up -d`。
+### 3.1. Docker启动
+```
+# 下载项目里面的模板,`my_crontab`文件以及`appsetting.json`文件
 
-提示成功的话,即表示容器启动成功。
+# 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
+wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/my_crontab
 
-可以进入容器查看详细运行日志,Desktop 通过点击相应容器名就能进入,可以很清晰的看到日志和容器信息;linux 的话请使用相应的docker命令查看,另外当前目录也会生成 Logs 日志文件。
+# 根据 appsettings.json 里面的注释编辑所需配置
+wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/appsettings.json
 
-每次容器启动会去跑一遍 Test 任务,用于测试 Cookie 。其他任务由设定的cron来指定定时触发,如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
+# Docker启动命令,/root/bilibili_tool/为映射目录
+docker run -d --restart always --name="bilibili_tool_pro" \
+    -v /root/bilibili_tool/logs:/app/Logs \
+    -v /root/bilibili_tool/my_crontab:/app/custom_crontab \
+    -v /root/bilibili_tool/appsettings.json:/app/appsettings.json \
+    zai7lou/bilibili_tool_pro
 
-想手动运行某任务的话,请进入容器后输入相应命令来启动执行。
+# 查看实时日志
+docker logs -f bilibili_tool_pro
+
+# 启动容器
+docker start bilibili_tool_pro
+
+# 停止容器
+docker stop bilibili_tool_pro
+
+# 删除容器
+docker rm bilibili_tool_pro
 
-## 3. 自己构建镜像(非必须)
+# 进入容器
+docker exec -it bilibili_tool_pro /bin/bash
+
+```
+
+### 3.2. 通过Watchtower手动更新容器
+```
+docker run --rm \
+    -v /var/run/docker.sock:/var/run/docker.sock \
+    containrrr/watchtower \
+    --run-once --cleanup \
+    bilibili_tool_pro
+```
+
+## 4. 自己构建镜像(非必须)
 
 目前我提供和维护的镜像:`[zai7lou/bilibili_tool_pro](https://hub.docker.com/repository/docker/zai7lou/bilibili_tool_pro)`;
 
@@ -67,10 +127,11 @@ bilibili_tool
 
  `TARGET_NAME`为镜像名称和版本,可以自己起个名字
 
-## 4. 其他
+## 5. 其他
 
 代码编译和发布环境: mcr.microsoft.com/dotnet/sdk:6.0
 
 代码运行环境: mcr.microsoft.com/dotnet/runtime:6.0
 
 apt-get 包源用的国内网易的。
+
diff --git a/docker/sample/appsettings.json b/docker/sample/appsettings.json
new file mode 100644
index 000000000..a32cb5712
--- /dev/null
+++ b/docker/sample/appsettings.json
@@ -0,0 +1,191 @@
+{
+  //Cookie集合,取自浏览器,必填
+  "BiliBiliCookies": [ //Cookie字符串集合,登录bilibili后F12获取,形如"_uuid=abcd; buvid3=1234; sid=abc123"
+    ""
+  ],
+
+  "RunTasks": "Daily", //要运行的任务名称[Daily,LiveLottery,UnfollowBatched,VipBigPoint,Test],多个使用&分隔,如“Daily&LiveLottery”,建议使用命令行参数指定
+
+  //程序自定义个性化配置
+  "DailyTaskConfig": {
+    "IsWatchVideo": true, //是否观看视频
+    "IsShareVideo": true, //是否分享视频
+    "NumberOfCoins": 5, //每日设定的投币数 [0,5]
+    "SelectLike": true, //投币时是否同时点赞[false,true]
+    "SupportUpIds": "", //优先选择支持的up主Id集合,多个以英文逗号分隔,如:"123,456"。配置后会优先从指定的up主下挑选视频进行观看、分享和投币,不配置或配置为-1则表示没有特别支持的up,会从关注和排行耪中随机获取支持视频
+    "DayOfAutoCharge": -1, //每月几号自动充电[-1,31],-1表示不指定,默认月底最后一天;0表示不充电
+    "AutoChargeUpId": "-1", //指定支持的UP主Id,-1表示自己
+    "ChargeComment": "", //充电后留言
+    "DayOfReceiveVipPrivilege": 1, //每月几号自动领取会员权益的[-1,31],-1表示不指定,默认每月1号;0表示不自动领取
+    "DayOfExchangeSilver2Coin": 0, //每月几号执行银瓜子兑换硬币[-1,31],-1表示不指定,默认每月最后一天;-2表示每天;0表示不进行兑换
+    "DevicePlatform": "android" //执行客户端操作时的平台 [ios,android]
+  },
+
+  "LiveLotteryTaskConfig": {
+    "ExcludeAwardNames": "舰|船|航海|代金券|自拍|照|写真|图|提督", //根据关键字排除包含这些文字的奖品名称,多个用“|”分隔,如“照|舰|船|航海|代金券|自拍”
+    "IncludeAwardNames": "", //根据关键字指定奖品名称必须包含的文字,多个用“|”分隔,如“红包|现金|块|元”
+    "AutoGroupFollowings": true, //抽奖结束后是否自动将关注的主播分组到“天选时刻”分组,值域[true,false]
+    "DenyUids": "65566781,1277481241,1643654862,603676925" //主播Uid黑名单(一般是中奖后的老赖),多个用英文逗号分隔,配置后不会参加黑名单中的主播的抽奖活动
+  },
+
+  "UnfollowBatchedTaskConfig": {
+    "GroupName": "天选时刻", //取关的分组名称
+    "Count": 1, //本次取关个数(倒序,从后往前取关)
+    "RetainUids": "108569350" //白名单(保留的UpId),多个用英文都好分隔,配置后,批量取关时不会取关配置的Up
+  },
+
+  "ReceiveVipPrivilegeConfig": {
+    "IsEnable": true //开关 
+  },
+
+  //安全相关配置
+  "Security": {
+    "IsSkipDailyTask": false, //是否跳过执行任务,用于特殊情况下,通过配置灵活的开启和关闭任务
+    "RandomSleepMaxMin": 10, //随机睡眠的最大时长(单位为分钟),用于使每天运行时间在范围内相对随机,值域[0,+];配置为0表示不进行休眠
+    "IntervalSecondsBetweenRequestApi": 20, //两次调用api之间的间隔[0,+](单位为秒)。因为有人担心在几秒内连续调用api会被b站安全机制发现,所以为不放心的朋友添加了间隔秒数配置,两次连续调用Api之间会大于该秒数
+    "IntervalMethodTypes": "GET,POST", //间隔秒数所针对的HttpMethod,多个用英文逗号隔开,当前有GET和POST两种,可配置如“GET,POST”
+    "UserAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36 Edg/99.0.1150.55", //请求B站接口时头部传递的User-Agent
+    "WebProxy": "" //代理,user:password@host:port
+  },
+
+  // 推送
+  "Notification": {
+    "IsSingleAccountSingleNotify": true //是否开启每个账号单独推送消息
+  },
+
+  //日志
+  "Serilog": {
+    "Using": [
+      "Serilog.Sinks.Console",
+      "Serilog.Sinks.Debug",
+      "Serilog.Sinks.File",
+      "Ray.Serilog.Sinks.TelegramBatched",
+      "Ray.Serilog.Sinks.WorkWeiXinBatched",
+      "Ray.Serilog.Sinks.DingTalkBatched",
+      "Ray.Serilog.Sinks.ServerChanBatched",
+      "Ray.Serilog.Sinks.CoolPushBatched",
+      "Ray.Serilog.Sinks.OtherApiBatched",
+      "Ray.Serilog.Sinks.PushPlusBatched",
+      "Ray.Serilog.Sinks.MicrosoftTeamsBatched",
+      "Ray.Serilog.Sinks.WorkWeiXinAppBatched"
+    ],
+    "MinimumLevel": {
+      "Default": "Debug",
+      "Override": {
+        "Microsoft": "Warning",
+        "System": "Warning",
+        "Microsoft.AspNetCore": "Warning"
+      }
+    },
+    "WriteTo": [
+      //0.Console
+      {
+        "Name": "Console",
+        "Args": {
+          "restrictedToMinimumLevel": "Information",
+          "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
+        }
+      },
+      //1.Debug
+      { "Name": "Debug" },
+      //2.File
+      {
+        "Name": "File",
+        "Args": {
+          "path": "Logs/log.txt",
+          "restrictedToMinimumLevel": "Verbose",
+          "rollingInterval": 3
+        }
+      },
+
+      //3.Telegram机器人(https://core.telegram.org/bots/api#available-methods)
+      {
+        "Name": "TelegramBatched",
+        "Args": {
+          "botToken": "",
+          "chatId": "",
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //4.企业微信机器人(https://work.weixin.qq.com/api/doc/90000/90136/91770)
+      {
+        "Name": "WorkWeiXinBatched",
+        "Args": {
+          "webHookUrl": "", //群机器人生成
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //5.钉钉机器人(https://developers.dingtalk.com/document/app/overview-of-group-robots)
+      {
+        "Name": "DingTalkBatched",
+        "Args": {
+          "webHookUrl": "", //群机器人生成
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //6.Server酱(http://sc.ftqq.com/9.version)
+      {
+        "Name": "ServerChanBatched",
+        "Args": {
+          "scKey": "", //已过时,待删除
+          "turboScKey": "", //平台生成的ScKey
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //7.酷推
+      {
+        "Name": "CoolPushBatched",
+        "Args": {
+          "sKey": "",
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //8.自定义Api
+      {
+        "Name": "OtherApiBatched",
+        "Args": {
+          "api": "",
+          "placeholder": "#msg#", //占位符
+          "bodyJsonTemplate": "{\"msgtype\":\"markdown\",\"markdown\":{\"content\":#msg#}}", //json模板,会当作post的body,占位符会被日志内容替换(日志文本为json字符串,已经带有引号,所有模板中占位符不用使用引号包裹,如例子所示为企业微信的标准推送格式)
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //9.PushPlus(http://www.pushplus.plus/doc/)
+      {
+        "Name": "PushPlusBatched",
+        "Args": {
+          "token": "",
+          "channel": "", //渠道,值域[wechat,webhook,cp,sms,mail],分别对应[微信公众号,指定第三方webhook,企业微信应用,短信,邮件]
+          "topic": "", //群组编码,用于群发,没有就不填(不填仅发送给自己);channel为webhook时无效
+          "webhook": "", //webhook编码(不是地址),仅在channel使用webhook渠道和CP渠道时需要填写
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //10.MicrosoftTeams
+      {
+        "Name": "MicrosoftTeamsBatched",
+        "Args": {
+          "webhook": "", //webhook完整地址
+          "restrictedToMinimumLevel": "Information"
+        }
+      },
+      //11.企业微信应用推送
+      {
+        "Name": "WorkWeiXinAppBatched",
+        "Args": {
+          "corpId": "", //必填
+          "agentId": "", //必填
+          "secret": "", //必填
+          "toUser": "@all",
+          "toParty": "",
+          "toTag": "",
+          "restrictedToMinimumLevel": "Information"
+        }
+      }
+    ],
+    "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
+  },
+
+  "PlateformType": "GitHubActions",
+  "IsPrd": false
+}

From d775ca8972d55abb8aa6a555c55cc5c3e5141f21 Mon Sep 17 00:00:00 2001
From: syrinka <syrinka@foxmail.com>
Date: Tue, 23 Aug 2022 10:52:23 +0800
Subject: [PATCH 02/12] =?UTF-8?q?cron=20=E7=8E=AF=E5=A2=83=E5=8F=98?=
 =?UTF-8?q?=E9=87=8F=E8=BD=AC=E4=B9=89=20&=20=E6=96=B0=E7=9A=84=E7=8E=AF?=
 =?UTF-8?q?=E5=A2=83=E5=8F=98=E9=87=8F=20Ray=5FCrontab=20(#256)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* refactor: env value escape

ref: https://stackoverflow.com/a/48651061

* refactor: 简化条件

* feat: 支持通过环境变量指定 crontab

* docs: 补充 Ray_Crontab 的文档

* docs: 顺便 fix 一下

* fix: miss spelling
---
 README.md             |  2 +-
 docker/README.md      |  1 +
 docker/entry.sh       | 13 ++++++++-----
 docs/configuration.md | 21 +++++++++++++++++++++
 4 files changed, 31 insertions(+), 6 deletions(-)

diff --git a/README.md b/README.md
index 982927150..c84dbb92c 100644
--- a/README.md
+++ b/README.md
@@ -270,7 +270,7 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 
 * 确认没有同类 issue 后,自己可新建 issue,描述问题或建议
 
-* 如果想自己解决,请 fork 仓库后,在**devlop 分支**进行编码开发,完成后**提交 pr 到 devlop 分支**,并标注解决的 issue 编号
+* 如果想自己解决,请 fork 仓库后,在**develop 分支**进行编码开发,完成后**提交 pr 到 develop 分支**,并标注解决的 issue 编号
 
 我会尽快进行代码审核,测试成功后会合并入 main 主分支,提前感谢您的贡献。
 
diff --git a/docker/README.md b/docker/README.md
index f280363cb..ef65939ec 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -42,6 +42,7 @@ Window系统推荐使用Docker Desktop,官方下载安装包,一路鼠标点
 # 下载项目里面的模板,`my_crontab`文件以及`docker-compose.yml`文件
 
 # 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
+# 或考虑配置`Ray_Crontab`环境变量
 wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/my_crontab
 
 # 根据 docker-compose.yaml 里面的注释编辑所需配置,`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
diff --git a/docker/entry.sh b/docker/entry.sh
index a4d9edc8d..c7bc8cffe 100644
--- a/docker/entry.sh
+++ b/docker/entry.sh
@@ -3,17 +3,20 @@ set -e
 
 # https://stackoverflow.com/questions/27771781/how-can-i-access-docker-set-environment-variables-from-a-cron-job
 echo "[step 1/4]导入环境变量"
-printenv | grep -v "no_proxy" > /etc/environment
+declare -p | grep -v "no_proxy" > /etc/cron.env
 echo "=>完成"
 
 echo "[step 2/4]配置cron定时任务"
-myarray=(`find /app -maxdepth 1 -name "custom_crontab"`)
-if [ ${#myarray[@]} -gt 0 ]; then 
+echo "BASH_ENV=/etc/cron.env" > /etc/cron.d/bilicron
+if ! [ -z $Ray_Crontab ]; then
+	echo "=>检测到对应的环境变量,使用其值作为配置"
+	echo $Ray_Crontab >> /etc/cron.d/bilicron
+elif [ -e "/app/custom_crontab" ]; then 
 	echo "=>检测到自定义了cron定时任务,使用自定义配置"
-	cp /app/custom_crontab /etc/cron.d/bilicron
+	cat /app/custom_crontab >> /etc/cron.d/bilicron
 else
 	echo "=>使用默认cron定时任务配置"
-	cp /app/crontab /etc/cron.d/bilicron
+	cat /app/crontab >> /etc/cron.d/bilicron
 fi
 echo "=>完成"
 
diff --git a/docs/configuration.md b/docs/configuration.md
index 09a81d50f..8523f7669 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -70,6 +70,7 @@
     - [3.7. 日志相关](#37-日志相关)
         - [3.7.1. Console日志输出等级](#371-console日志输出等级)
         - [3.7.2. Console日志输出样式](#372-console日志输出样式)
+    - [3.8. crontab相关](#38-crontab相关)
 
 <!-- /TOC -->
 
@@ -642,6 +643,7 @@ https://cp.xuthus.cc/
 | 默认值   | 空 |
 | 环境变量   | `Ray_Serilog__WriteTo__8__Args__api` |
 | GitHub Secrets  | `PUSHOTHERAPI` |
+
 <a id="markdown-3672-placeholder" name="3672-placeholder"></a>
 ##### 3.6.7.2. placeholder
 
@@ -652,6 +654,7 @@ https://cp.xuthus.cc/
 | 默认值   | 空 |
 | 环境变量   | `Ray_Serilog__WriteTo__8__Args__placeholder` |
 | GitHub Secrets  | `PUSHOTHERPLACEHOLDER` |
+
 <a id="markdown-3673-bodyjsontemplate" name="3673-bodyjsontemplate"></a>
 ##### 3.6.7.3. bodyJsonTemplate
 
@@ -828,3 +831,21 @@ BiliBiliTool 使用 Serilog 作为日志组件,所以可以参考 Serilog 的
 | 环境变量   | `Ray_Serilog__WriteTo__0__Args__outputTemplate` |
 | GitHub Secrets  | `CONSOLELOGTEMPLATE` |
 
+<a id="markdown-38-crontab相关" name="38-crontab相关"></a>
+#### 3.8 crontab相关
+适用于 [方式四:docker容器化运行(推荐)](../docker/README.md),用于配置定时任务,效果与 `my_crontab` 文件相同,且优先级高于 `my_crontab`。
+
+使用例:
+```yaml
+environment:
+  Ray_BiliBiliCookies: somecookies
+  Ray_Crontab: |
+    0 15 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=Daily >> /var/log/cron.log
+    0 22 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=LiveLottery >> /var/log/cron.log
+```
+
+|   TITLE   | CONTENT   |
+| ---------- | -------------- |
+| 值域   | 一串字符串 |
+| 默认值   | 空 |
+| 环境变量   | `Ray_Crontab` |

From df44f2e3e3ba3336fc66d786b4068b5684ed933d Mon Sep 17 00:00:00 2001
From: layui0320 <58420846@qq.com>
Date: Wed, 24 Aug 2022 00:37:46 +0800
Subject: [PATCH 03/12] =?UTF-8?q?=E5=86=8D=E6=AC=A1=E4=BF=AE=E6=94=B9?=
 =?UTF-8?q?=E6=96=87=E6=A1=A3=20(#257)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* 修改docker部署文档下载链接错误

* 项目文档修改
---
 README.md        | 136 +++++++++++++++++++++++------------------------
 docker/README.md |  34 ++++++------
 2 files changed, 82 insertions(+), 88 deletions(-)

diff --git a/README.md b/README.md
index c84dbb92c..7630ba1a9 100644
--- a/README.md
+++ b/README.md
@@ -18,18 +18,35 @@ BiliBiliTool
 
 </div>
 
+**BiliBiliTool 是一个自动执行任务的工具,当我们忘记做某项任务时,它会像一个贴心小助手,按照我们预先吩咐它的命令,在指定频率、时间范围内帮助我们完成计划的任务。**
+
+详细功能如下:
+
+- **每日获取满额升级经验(登录、投币、点赞、分享视频)(支持指定支持up主)**
+- **每天漫画签到**
+- **每天直播签到**
+- **直播中心银瓜子兑换为硬币**
+- **每月领取大会员赠送的 5 张 B 币券和福利(忘记或者不领就浪费了哦)**
+- **每月领取大会员漫画福利**
+- **月底在 B 币券过期前进行充电(支持指定想要支持的up主,如果没有喜欢的up,也可以为自己充个电啊,做个用爱为自己发电的人~)**
+- **直播中心天选时刻自动参与抽奖**
+- **批量取关**
+- **大会员大积分任务**
+- **支持多账号**
+- **理论上支持所有远端的日志推送(默认支持推送到Telegram、企业微信、钉钉、PushPlus、Server酱、钉钉、酷推,另外也支持自定义推送到任意api)**
+---
 [目录]
 
 <!-- TOC depthFrom:2 -->
 
 - [1. 如何使用](#1-如何使用)
-    - [1.1. 第一步:获取自己的 Cookie](#11-第一步获取自己的-cookie)
+    - [1.1. 第一步:获取BiliBili的 Cookie](#11-第一步获取BiliBili的-cookie)
     - [1.2. 第二步:配置 Cookie 并运行 BiliBiliTool](#12-第二步配置-cookie-并运行-bilibilitool)
-        - [1.2.1. 方式一:xxx](#121-方式一xxx)
-        - [1.2.2. 方式二:下载程序包到本地或服务器运行](#122-方式二下载程序包到本地或服务器运行)
-        - [1.2.3. 方式三:腾讯云函数SCF](#123-方式三腾讯云函数scf)
-        - [1.2.4. 方式四:docker容器化运行(推荐)](#124-方式四docker容器化运行推荐)
-        - [1.2.5. 方式五:青龙运行](#125-方式五青龙运行)
+		- [1.2.1. 方式一:Docker容器化运行(推荐)](#121-方式一docker容器化运行推荐)
+        - [1.2.2. 方式二:青龙运行](#122-方式二青龙运行)
+        - [1.2.3. 方式三:下载程序包到本地或服务器运行](#123-方式三下载程序包到本地或服务器运行)
+        - [1.2.4. 方式四:腾讯云函数SCF](#124-方式四腾讯云函数scf)
+        - ~~[1.2.5. 方式五:GitHub Actions](#125-方式五github-actions)~~
 - [2. 功能任务说明](#2-功能任务说明)
 - [3. 个性化自定义配置](#3-个性化自定义配置)
 - [4. 多账号支持](#4-多账号支持)
@@ -43,27 +60,7 @@ BiliBiliTool
 
 <!-- /TOC -->
 
-**BiliBiliTool 是一个自动执行任务的工具,当我们忘记做某项任务时,它会像一个小助手一样,按照我们预先吩咐她的命令,在指定时间、按照指定频率,帮助我们自动完成计划的任务。**
-
-详细功能如下:
-
-- **每日获取满额升级经验(登录、投币、点赞、分享视频)(支持指定支持up主)**
-- **每天漫画签到**
-- **每天直播签到**
-- **直播中心银瓜子兑换为硬币**
-- **每月领取大会员赠送的 5 张 B 币券和福利(忘记或者不领就浪费了哦)**
-- **每月领取大会员漫画福利**
-- **月底在 B 币券过期前进行充电(支持指定想要支持的up主,如果没有喜欢的up,也可以为自己充个电啊,做个用爱为自己发电的人~)**
-- **直播中心天选时刻自动参与抽奖**
-- **批量取关**
-- **大会员大积分任务**
-- **支持多账号**
-- **理论上支持所有远端的日志推送(默认支持推送到Telegram、企业微信、钉钉、PushPlus、Server酱、钉钉、酷推,另外也支持自定义推送到任意api)**
-
-还有其他一些辅助小功能,大家可以自己去自由探索~
-
-![运行图示](docs/imgs/run-exe.png)
-
+---
 **Github 仓库地址:[RayWangQvQ/BiliBiliToolPro](https://github.com/RayWangQvQ/BiliBiliToolPro)**
 
 **注意:**
@@ -72,52 +69,43 @@ BiliBiliTool
 - **所有代码都是开源且透明的,任何人均可查看,程序不会保存或滥用任何用户的个人信息**
 - **应用内几乎所有功能都开放为了配置(如任务开关、日期、upId等),请仔细阅读配置文档,自己对自己的配置负责**
 
+
+本地运行图示:
+
+![运行图示](docs/imgs/run-exe.png)
+
 _(如果图片挂了,请自己架梯子,没有的也可以先参考 [我的博客](https://www.cnblogs.com/RayWang/p/13909784.html),但内容不保证最新)_
 
+
 ## 1. 如何使用
 
 BiliBiliTool 实现自动完成任务的原理,是通过调用一系列开放的api实现的。
 
 **要使用 BiliBiliTool,我们只需要做两步:获取自己的 Cookie 作为配置,然后将其输入 BiliBiliTool 并运行即可。**
 
-### 1.1. 第一步:获取自己的 Cookie
+### 1.1. 第一步:获取BiliBili的 Cookie
 
-- 浏览器打开并登录 [bilibili 网站](https://www.bilibili.com/)
+- 浏览器打开并登录 [BiliBili 网站](https://www.bilibili.com/)
 - 登录成功后,访问 `https://api.bilibili.com/x/web-interface/nav`,按 **F12** 打开"开发者工具",按 **F5** 刷新一下
 - 在"开发者工具"面板中,点击 **网络(Network)**,在左侧的请求列表中,找到名称为 `nav` 的接口,点击它
 - 依次查找 **Headers** ——> **RequestHeader** ——> **cookie**,可以看到很长一串以英文分号分隔的字符串,复制整个这个cookie字符串(不要使用右键复制,请使用 Ctrl+C 复制,部分浏览器右键可能会进行 UrlDecode ),保存它们到记事本,待会儿会用到。
 
 ![获取Cookie图示](docs/imgs/get-bilibili-web-cookie.jpg)
 
-### 1.2. 第二步:配置 Cookie 并运行 BiliBiliTool
-
-运行 BiliBiliTool 主要有 5 种方式:
-* Github Actions
-* 下载Release包到本地或服务器运行
-* 云函数部署
-* docker容器化运行
-* 青龙运行
-
-熟悉 GitHub 的朋友,推荐使用方式一,可以实现线上的每天自动运行,不需自己动手,一劳永逸。
 
-想先快速运行一下尝个鲜、或是要部署到自己服务器的朋友,可以跳转到方式二 Release 包运行,操作简单快速。
-
-云函数则可以作为 GitHub Actions 的替代平台,优点是触发器独立灵活、可以国内ip,缺点是日志浏览很不人性。
-
-熟悉docker的朋友,可以跳转到方式四 docker容器化运行,以后因为可能涉及到需要持久话的功能,Serverless就不太方便,所以有能力、有条件的话还是建议使用docker。
+### 1.2. 第二步:配置 Cookie 并运行 BiliBiliTool
 
-已经部署好了青龙面板跑其他自动任务的朋友,也可以直接在青龙面板中跑BiliBiliTool。
+#### 1.2.1. 方式一:Docker容器化运行(推荐)
 
-以下 5 种方式任选一种适合自己的即可。
+[>>Docker部署说明](docker/README.md)
 
-#### 1.2.1. 方式一:xxx
-暂时删掉该方式避避风头。
 
-也建议所有还在使用该方式运行的朋友,暂时先替换为下面的其他运行方式,避免造成不必要的损失。
+#### 1.2.2. 方式二:青龙运行
 
-#### 1.2.2. 方式二:下载程序包到本地或服务器运行
+[>>青龙部署教程](qinglong/README.md)
+#### 1.2.3. 方式三:下载程序包到本地或服务器运行
 
-如果是 DotNet 开发者,直接 clone 源码然后 vs 打开解决方案,配置 Cookie 后即可直接本地进行运行和调试。
+如果是 DotNet 开发者,直接 Clone 源码,然后 VS 打开解决方案,配置 Cookie 后即可直接本地进行运行和调试。
 
 对于不是开发者的朋友,可以通过下载 Release 包到本地或任意服务器运行,步骤如下。
 <details>
@@ -172,18 +160,15 @@ Ray.BiliBiliTool.Console
 
 </details>
 
-#### 1.2.3. 方式三:腾讯云函数SCF
+#### 1.2.4. 方式四:腾讯云函数SCF
 
 [>>腾讯云函数部署说明](tencentScf/README.md)
 
-#### 1.2.4. 方式四:docker容器化运行(推荐)
-
-[>>docker部署说明](docker/README.md)
-
-#### 1.2.5. 方式五:青龙运行
 
-[>>青龙部署教程](qinglong/README.md)
+#### 1.2.5. 方式五:GitHub Actions
+暂时删掉该方式避避风头。
 
+**建议所有使用该方式运行的朋友,暂时先替换其他运行方式,避免造成不必要的损失。**
 
 
 如果配置了推送,执行成功后接收端会收到推送消息,推送效果如下所示:
@@ -228,17 +213,27 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 
 ## 4. 多账号支持
 
-对于 GitHub Actions 托管的,可以通过添加 Key 为 `COOKIESTR2` 和 `COOKIESTR3` 的 Secret ,来支持最多 3 个账号。
+~~对于 GitHub Actions 托管的,可以通过添加 Key 为 `COOKIESTR2` 和 `COOKIESTR3` 的 Secret ,来支持最多 3 个账号。~~
 
-对于其他本地或 docker 托管的,因配置项 `BiliBiliCookies` 被设计为一个字符串数组,所以理论可以添加任意个数的账号。例如,使用环境变量配置的话,可以添加 Key 为 `Ray_BiliBiliCookies__2`、`Ray_BiliBiliCookies__3`、`Ray_BiliBiliCookies__4`...的环境变量,以此类推。
+Docker或其他方式托管的,因配置项 `BiliBiliCookies` 被设计为一个字符串数组,所以理论可以添加任意个数的账号,例:
+```
+ "BiliBiliCookies": [
+    "cookies1",
+    "cookies2",
+    "..."
+  ],
+
+```
+
+使用环境变量配置的话,可以添加 Key 为 `Ray_BiliBiliCookies__2`、`Ray_BiliBiliCookies__3`、`Ray_BiliBiliCookies__4`...的环境变量,以此类推。
 
 ## 5. 常见问题
 
 [>>点击查看常见问题文档](docs/questions.md)
 
-[issues(议题)](https://github.com/RayWangQvQ/BiliBiliToolPro/issues)板块可以用来提交**Bug**和**建议**;
+[Issues(议题)](https://github.com/RayWangQvQ/BiliBiliToolPro/issues)板块可以用来提交**Bug**和**建议**;
 
-[discussions(讨论)](https://github.com/RayWangQvQ/BiliBiliToolPro/discussions)板块可以用来**提问**和**讨论**。
+[Discussions(讨论)](https://github.com/RayWangQvQ/BiliBiliToolPro/discussions)板块可以用来**提问**和**讨论**。
 
 大部分问题其实都可以在文档、议题和讨论中找到答案。
 
@@ -247,13 +242,13 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 * 请先确认是否可以通过升级到最新版本解决
 * 然后搜索文档(特别是配置说明文档和常见问题文档)、议题和讨论,查看是否已有其他人遇到相同问题、是否已有解决方案
 
-如果确认还未解决,可以自己提交 issue,或发布 discussions 与大家一起探讨,我会尽快确认并解决。
+如果确认还未解决,可以自己提交 Issue,或发布 Discussions 与大家一起探讨,我会尽快确认并解决。
 
-(关于如何正确的提交issue,请详见**常见问题文档**)。
+(关于如何正确的提交Issue,请详见**常见问题文档**)。
 
 ## 6. 版本发布及更新
 
-当前正处于稳定的迭代开发中,正常情况下每 2 周会发布一个小版本,详细待更新和计划内容可参见 [projects](https://github.com/RayWangQvQ/BiliBiliToolPro/projects) 和 [issues](https://github.com/RayWangQvQ/BiliBiliTool/issues) 。
+当前正处于稳定的迭代开发中,~~正常情况下每 2 周会发布一个小版本~~,详细待更新和计划内容可参见 [Projects](https://github.com/RayWangQvQ/BiliBiliToolPro/projects) 和 [Issues](https://github.com/RayWangQvQ/BiliBiliTool/issues) 。
 
 关于新版本发布后,如何同步最新的内容到自己 Fork 的仓库,可参考**常见问题文档**中的 《**我 Fork 之后如何同步原作者的更新内容?**》章节。
 
@@ -266,16 +261,16 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 ### 7.1. 贡献代码
 如果你有好的想法,欢迎向仓库贡献你的代码,贡献步骤:
 
-* 搜索查看 issue,确定是否已有人提过同类问题
+* 搜索查看 Issue,确定是否已有人提过同类问题
 
-* 确认没有同类 issue 后,自己可新建 issue,描述问题或建议
+* 确认没有同类 Issue 后,自己可新建 Issue,描述问题或建议
 
-* 如果想自己解决,请 fork 仓库后,在**develop 分支**进行编码开发,完成后**提交 pr 到 develop 分支**,并标注解决的 issue 编号
+* 如果想自己解决,请 Fork 仓库后,在**develop 分支**进行编码开发,完成后**提交 PR 到 develop 分支**,并标注解决的 Issue 编号
 
 我会尽快进行代码审核,测试成功后会合并入 main 主分支,提前感谢您的贡献。
 
 ### 7.2. 贡献文档
-文档部分由于我个人精力有限(写文档比写代码累多了),所以有些地方写的很简略,有些地方甚至有遗漏和错别字,不能贡献代码的朋友也欢迎来一起维护文档,欢迎 PR 来纠正我,一样都算是对开源做贡献了。
+文档部分由于我个人精力有限(写文档比写代码累多了),所以有些地方写的很简略,甚至有遗漏和错别字,不能贡献代码的朋友也欢迎来一起维护文档,欢迎 PR 来纠正我,一样都算是对开源做贡献了。
 
 ## 8. 捐赠支持
 
@@ -295,7 +290,7 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 
 ![赞赏码](docs/imgs/donate.jpg)
 
-另外,应用中的优先支持的UP主的配置项,默认是作者的 UpId (只是作为了 json 配置文件的默认值,代码是干净的),需要更改的话,直接修改相应配置即可(secrets或环境变量等各种方式都行)。
+> 项目中的优先支持的UP主的配置项,默认是作者的 UpId (只是作为了 JSON 配置文件的默认值,代码是干净的),需要更改的话,直接修改相应配置即可(secrets或环境变量等各种方式都行)。
 
 当然,不改的话,也算是另一种捐赠支持作者的方式啦。
 
@@ -316,3 +311,4 @@ dotnet Ray.BiliBiliTool.Console.dll --runTasks=Daily&LiveLottery
 Thanks to `JetBrain` for the free certificate support:
 
 ![ReSharper logo](https://resources.jetbrains.com/storage/products/company/brand/logos/ReSharper.svg)
+
diff --git a/docker/README.md b/docker/README.md
index ef65939ec..6953c79e5 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -12,41 +12,40 @@
 - [5. 其他](#5-其他)
 
 
-
-
-
 <!-- /TOC -->
 ## 1. 前期工作
 
 ### 1.1. Docker环境
 
-请确认已安装了Docker所需环境([Docker](https://docs.docker.com/get-docker/)和[Docker Compose](https://docs.docker.com/compose/cli-command/))。
+请确认已安装了Docker所需环境([Docker](https://docs.docker.com/get-docker/)和[Docker Compose](https://docs.docker.com/compose/cli-command/))
+
+Linux一键安装命令:
+`curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun`
 
 Window系统推荐使用Docker Desktop,官方下载安装包,一路鼠标点下去就能装好,运行时也有可视化页面。
 
-安装完成后,请执行`docker --version`检查`docker`是否安装成功,请执行`docker compose version`检查`docker compose`是否安装成功。
+安装完成后,请执行`docker --version`检查`Docker`是否安装成功,请执行`docker compose version`检查`Docker Compose`是否安装成功。
 
 ### 1.2. 须知
 
 
-每次容器启动会去跑一遍 Test 任务,用于测试 Cookie 。其他任务由设定的cron来指定定时触发,
-
-想手动运行某任务的话,请进入容器后输入相应命令来启动执行。
+每次容器启动会去跑一遍 Test 任务,用于测试 Cookie ,其他任务由设定的Cron来指定定时触发。
 
+想手动运行某任务的话,[查看功能任务参数](https://github.com/RayWangQvQ/BiliBiliToolPro/tree/develop#2-功能任务说明) 请进入容器后输入命令来启动执行。
 
 
 ## 2. Docker-Compose版(推荐) 
-在本地任意文件夹下,创建一个目录 `bilibili_tool` 
+在本地路径下,创建并进入目录 `bilibili_tool` 
 
 ```
 # 下载项目里面的模板,`my_crontab`文件以及`docker-compose.yml`文件
 
 # 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
 # 或考虑配置`Ray_Crontab`环境变量
-wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/my_crontab
+wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/my_crontab
 
 # 根据 docker-compose.yaml 里面的注释编辑所需配置,`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
-wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/docker-compose.yml
+wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/docker-compose.yml
 
 最终文件结构如下:
 bilibili_tool
@@ -75,13 +74,13 @@ docker-compose pull && docker-compose up -d
 
 ### 3.1. Docker启动
 ```
-# 下载项目里面的模板,`my_crontab`文件以及`appsetting.json`文件
+# 下载项目里面的模板,`my_crontab`文件以及`appsettings.json`文件
 
 # 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
-wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/my_crontab
+wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/my_crontab
 
-# 根据 appsettings.json 里面的注释编辑所需配置
-wget https://github.com/RayWangQvQ/BiliBiliToolPro/blob/main/docker/sample/appsettings.json
+# 根据 appsettings.json 里面的注释编辑所需配置 (暂定develop分支下载路径)
+wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/develop/docker/sample/appsettings.json
 
 # Docker启动命令,/root/bilibili_tool/为映射目录
 docker run -d --restart always --name="bilibili_tool_pro" \
@@ -107,7 +106,7 @@ docker exec -it bilibili_tool_pro /bin/bash
 
 ```
 
-### 3.2. 通过Watchtower手动更新容器
+### 3.2. 使用Watchtower更新容器
 ```
 docker run --rm \
     -v /var/run/docker.sock:/var/run/docker.sock \
@@ -122,7 +121,7 @@ docker run --rm \
 
 如果有需要(大部分都不需要),可以使用源码自己构建镜像,如下:
 
-在有Dockerfile的目录运行
+在有项目的Dockerfile的目录运行
 
 `docker build -t TARGET_NAME .`
 
@@ -135,4 +134,3 @@ docker run --rm \
 代码运行环境: mcr.microsoft.com/dotnet/runtime:6.0
 
 apt-get 包源用的国内网易的。
-

From 8111ef53eeb807fc5d1f841eae0044b247807ee9 Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Wed, 24 Aug 2022 01:55:24 +0800
Subject: [PATCH 04/12] chore: update current tag

---
 CHANGELOG.md | 3 +++
 common.props | 2 +-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5aecfbd1..ebdebd6d7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -48,3 +48,6 @@
 - 【#197】合并PR,新增了阅读漫画功能到每日任务中(@ChanceLuo)
 ## 0.2.0
 - 新增大会员大积分任务
+## 0.2.1
+- 合并PR(#253、#257),更新文档(@layui0320)
+- 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
diff --git a/common.props b/common.props
index 77ce7f072..4a3626e8a 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
 <Project>
   <PropertyGroup>
     <Authors>Ray</Authors>
-    <Version>0.2.0</Version>
+    <Version>0.2.1</Version>
     <NoWarn>$(NoWarn);CS1591;CS0436</NoWarn>
   </PropertyGroup>
 </Project>

From 87a21823514e1cc9d062a824655ae1f9da4c5568 Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Wed, 24 Aug 2022 03:40:13 +0800
Subject: [PATCH 05/12] feat: TG push use proxy

---
 CHANGELOG.md                                  |  1 +
 src/Ray.BiliBiliTool.Console/appsettings.json |  3 +-
 .../TelegramApiClient.cs                      | 47 ++++++++++++++++++-
 .../TelegramBatchedSink.cs                    |  5 +-
 .../TelegramLoggerConfigurationExtensions.cs  |  3 +-
 5 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index ebdebd6d7..0e9b4341c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -51,3 +51,4 @@
 ## 0.2.1
 - 合并PR(#253、#257),更新文档(@layui0320)
 - 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
+- Feature(#65):新增TG推送配置并使用代理功能
diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json
index a32cb5712..1282cff1b 100644
--- a/src/Ray.BiliBiliTool.Console/appsettings.json
+++ b/src/Ray.BiliBiliTool.Console/appsettings.json
@@ -104,7 +104,8 @@
         "Args": {
           "botToken": "",
           "chatId": "",
-          "restrictedToMinimumLevel": "Information"
+          "restrictedToMinimumLevel": "Information",
+          "proxy": "" //代理,user:password@host:port
         }
       },
       //4.企业微信机器人(https://work.weixin.qq.com/api/doc/90000/90136/91770)
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramApiClient.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramApiClient.cs
index 1d733f8d7..3004c40ef 100644
--- a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramApiClient.cs
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramApiClient.cs
@@ -1,4 +1,5 @@
 using System;
+using System.Net;
 using System.Net.Http;
 using System.Text;
 using System.Threading.Tasks;
@@ -12,6 +13,7 @@ public class TelegramApiClient : PushService
         //https://core.telegram.org/bots/api#available-methods
 
         private readonly string _chatId;
+        private readonly string _proxy;
         private const string TelegramBotApiUrl = "https://api.telegram.org/bot";
 
         /// <summary>
@@ -25,12 +27,12 @@ public class TelegramApiClient : PushService
         private readonly HttpClient _httpClient = new HttpClient();
 
         /// <summary>
-        /// Initializes a new instance of the <see cref="TelegramClient"/> class.
+        /// Initializes a new instance of the <see cref="TelegramApiClient"/> class.
         /// </summary>
         /// <param name="botToken">The Telegram bot token.</param>
         /// <param name="timeoutSeconds">The timeout seconds.</param>
         /// <exception cref="ArgumentException">Thrown if the bot token is null or empty.</exception>
-        public TelegramApiClient(string botToken, string chatId, int timeoutSeconds = 10)
+        public TelegramApiClient(string botToken, string chatId, string proxy="", int timeoutSeconds = 10)
         {
             if (string.IsNullOrWhiteSpace(botToken))
             {
@@ -39,8 +41,21 @@ public TelegramApiClient(string botToken, string chatId, int timeoutSeconds = 10
             }
 
             _chatId = chatId;
+            _proxy = proxy;
 
             this._apiUrl = new Uri($"{TelegramBotApiUrl}{botToken}/sendMessage");
+
+            if (proxy.IsNotNullOrEmpty())
+            {
+                var webProxy = GetWebProxy(proxy);
+                var proxyHttpClientHandler = new HttpClientHandler
+                {
+                    Proxy = webProxy,
+                    UseProxy = true,
+                };
+                _httpClient = new HttpClient(proxyHttpClientHandler);
+            }
+
             this._httpClient.Timeout = TimeSpan.FromSeconds(timeoutSeconds);
         }
 
@@ -48,6 +63,8 @@ public TelegramApiClient(string botToken, string chatId, int timeoutSeconds = 10
 
         public override HttpResponseMessage DoSend()
         {
+            SelfLog.WriteLine($"使用代理:{_proxy.IsNotNullOrEmpty()}");
+
             var json = new
             {
                 chat_id = _chatId,
@@ -67,6 +84,32 @@ public override void BuildMsg()
 
             base.BuildMsg();
         }
+
+        private WebProxy GetWebProxy(string proxyAddress)
+        {
+            //todo:抽象到公共方法库
+            WebProxy webProxy;
+
+            //user:password@host:port http proxy only .Tested with tinyproxy-1.11.0-rc1
+            if (proxyAddress.Contains("@"))
+            {
+                string userPass = proxyAddress.Split("@")[0];
+                string address = proxyAddress.Split("@")[1];
+
+                string proxyUser = userPass.Split(":")[0];
+                string proxyPass = userPass.Split(":")[1];
+
+                var credentials = new NetworkCredential(proxyUser, proxyPass);
+
+                webProxy = new WebProxy(address, true,null, credentials);
+            }
+            else
+            {
+                webProxy = new WebProxy(proxyAddress, true);
+            }
+
+            return webProxy;
+        }
     }
 
     public enum TeleMsgType
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramBatchedSink.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramBatchedSink.cs
index d81cd849f..5ac1455aa 100644
--- a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramBatchedSink.cs
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramBatchedSink.cs
@@ -14,10 +14,12 @@ public class TelegramBatchedSink : BatchedSink
     {
         private readonly string _botToken;
         private readonly string _chatId;
+        private readonly string _proxy;
 
         public TelegramBatchedSink(
             string botToken,
             string chatId,
+            string proxy,
             Predicate<LogEvent> predicate,
             bool sendBatchesAsOneMessages,
             IFormatProvider formatProvider,
@@ -26,6 +28,7 @@ LogEventLevel minimumLogEventLevel
         {
             _botToken = botToken;
             _chatId = chatId;
+            _proxy = proxy;
         }
 
         public override void Emit(LogEvent logEvent)
@@ -34,7 +37,7 @@ public override void Emit(LogEvent logEvent)
             base.Emit(logEvent);
         }
 
-        protected override PushService PushService => new TelegramApiClient(_botToken, _chatId, 5);
+        protected override PushService PushService => new TelegramApiClient(_botToken, _chatId, _proxy, 5);
 
         public override void Dispose()
         {
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramLoggerConfigurationExtensions.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramLoggerConfigurationExtensions.cs
index ec873e031..ab9ebb466 100644
--- a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramLoggerConfigurationExtensions.cs
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.TelegramBatched/TelegramLoggerConfigurationExtensions.cs
@@ -12,6 +12,7 @@ public static LoggerConfiguration TelegramBatched(
             this LoggerSinkConfiguration loggerSinkConfiguration,
             string botToken,
             string chatId,
+            string proxy,
             string containsTrigger = Constants.DefaultContainsTrigger,
             bool sendBatchesAsOneMessages = true,
             IFormatProvider formatProvider = null,
@@ -21,7 +22,7 @@ public static LoggerConfiguration TelegramBatched(
             if (containsTrigger.IsNullOrEmpty()) containsTrigger = Constants.DefaultContainsTrigger;
             Predicate<LogEvent> predicate = x => x.MessageTemplate.Text.Contains(containsTrigger);
 
-            return loggerSinkConfiguration.Sink(new TelegramBatchedSink(botToken, chatId, predicate, sendBatchesAsOneMessages, formatProvider, restrictedToMinimumLevel), restrictedToMinimumLevel);
+            return loggerSinkConfiguration.Sink(new TelegramBatchedSink(botToken, chatId, proxy, predicate, sendBatchesAsOneMessages, formatProvider, restrictedToMinimumLevel), restrictedToMinimumLevel);
         }
     }
 }

From fea0e26304a7ee3683780199a482c31af8b6e132 Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Wed, 24 Aug 2022 21:42:14 +0800
Subject: [PATCH 06/12] feat: update doc for telegram push proxy

---
 docs/configuration.md | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/docs/configuration.md b/docs/configuration.md
index 8523f7669..ae37acb26 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -44,6 +44,7 @@
         - [3.6.2. Telegram机器人](#362-telegram机器人)
             - [3.6.2.1. botToken](#3621-bottoken)
             - [3.6.2.2. chatId](#3622-chatid)
+            - [3.6.2.3. proxy](#3623-proxy)
         - [3.6.3. 企业微信机器人](#363-企业微信机器人)
             - [3.6.3.1. webHookUrl](#3631-webhookurl)
         - [3.6.4. 钉钉机器人](#364-钉钉机器人)
@@ -70,7 +71,7 @@
     - [3.7. 日志相关](#37-日志相关)
         - [3.7.1. Console日志输出等级](#371-console日志输出等级)
         - [3.7.2. Console日志输出样式](#372-console日志输出样式)
-    - [3.8. crontab相关](#38-crontab相关)
+        - [3.7.3. crontab相关](#373-crontab相关)
 
 <!-- /TOC -->
 
@@ -558,6 +559,20 @@ P.S.访问链接需要能访问“外网”,有vpn的挂vpn。
 | 命令行示范   | 无 |
 | GitHub Secrets  | `PUSHTGCHATID`|
 
+<a id="markdown-3623-proxy" name="3623-proxy"></a>
+##### 3.6.2.3. proxy
+
+使用代理
+
+|   TITLE   | CONTENT   |
+| ---------- | -------------- |
+| 配置Key | `Serilog:WriteTo:3:Args:proxy` |
+| 值域   | 一串字符串,格式为user:password@host:port |
+| 默认值   | 空 |
+| 环境变量   | `Ray_Serilog__WriteTo__3__Args__proxy` |
+| 命令行示范   | 无 |
+| GitHub Secrets  | ``|
+
 <a id="markdown-363-企业微信机器人" name="363-企业微信机器人"></a>
 #### 3.6.3. 企业微信机器人
 
@@ -831,8 +846,8 @@ BiliBiliTool 使用 Serilog 作为日志组件,所以可以参考 Serilog 的
 | 环境变量   | `Ray_Serilog__WriteTo__0__Args__outputTemplate` |
 | GitHub Secrets  | `CONSOLELOGTEMPLATE` |
 
-<a id="markdown-38-crontab相关" name="38-crontab相关"></a>
-#### 3.8 crontab相关
+<a id="markdown-373-crontab相关" name="373-crontab相关"></a>
+#### 3.7.3. crontab相关
 适用于 [方式四:docker容器化运行(推荐)](../docker/README.md),用于配置定时任务,效果与 `my_crontab` 文件相同,且优先级高于 `my_crontab`。
 
 使用例:

From bdc2d86885d98add2ee5e97295ad344251176f9e Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Wed, 24 Aug 2022 23:03:27 +0800
Subject: [PATCH 07/12] feat: add gotify for push client

---
 CHANGELOG.md                                  |  1 +
 Ray.BiliBiliTool.sln                          |  7 +++
 .../Ray.BiliBiliTool.Console.csproj           |  1 +
 src/Ray.BiliBiliTool.Console/appsettings.json | 12 ++++-
 .../GotifyApiClient.cs                        | 46 +++++++++++++++++++
 .../GotifyBatchedSink.cs                      | 39 ++++++++++++++++
 .../GotifyConfigurationExtensions.cs          | 41 +++++++++++++++++
 .../Ray.Serilog.Sinks.GotifyBatched.csproj    | 14 ++++++
 8 files changed, 160 insertions(+), 1 deletion(-)
 create mode 100644 src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyApiClient.cs
 create mode 100644 src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyBatchedSink.cs
 create mode 100644 src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyConfigurationExtensions.cs
 create mode 100644 src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/Ray.Serilog.Sinks.GotifyBatched.csproj

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0e9b4341c..cd9c57a39 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -52,3 +52,4 @@
 - 合并PR(#253、#257),更新文档(@layui0320)
 - 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
 - Feature(#65):新增TG推送配置并使用代理功能
+- Feature(#240):新增gotify推送
diff --git a/Ray.BiliBiliTool.sln b/Ray.BiliBiliTool.sln
index 203bb3b25..6c935e017 100644
--- a/Ray.BiliBiliTool.sln
+++ b/Ray.BiliBiliTool.sln
@@ -152,6 +152,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ray.Serilog.Sinks.WorkWeiXi
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ray.Serilog.Sinks.MicrosoftTeamsBatched", "src\Ray.Serilog.Sinks\Ray.Serilog.Sinks.MicrosoftTeamsBatched\Ray.Serilog.Sinks.MicrosoftTeamsBatched.csproj", "{FB9A43DE-00F0-42C4-BF92-AF61D752CCA2}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Ray.Serilog.Sinks.GotifyBatched", "src\Ray.Serilog.Sinks\Ray.Serilog.Sinks.GotifyBatched\Ray.Serilog.Sinks.GotifyBatched.csproj", "{B00FF75D-4C48-45ED-9A24-5C0D383317EE}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -238,6 +240,10 @@ Global
 		{FB9A43DE-00F0-42C4-BF92-AF61D752CCA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{FB9A43DE-00F0-42C4-BF92-AF61D752CCA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{FB9A43DE-00F0-42C4-BF92-AF61D752CCA2}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B00FF75D-4C48-45ED-9A24-5C0D383317EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B00FF75D-4C48-45ED-9A24-5C0D383317EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B00FF75D-4C48-45ED-9A24-5C0D383317EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B00FF75D-4C48-45ED-9A24-5C0D383317EE}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -277,6 +283,7 @@ Global
 		{75A9CC5C-DF92-4D72-A14C-625AA902855B} = {A93210FD-27B6-40E4-B08D-391F96CA2754}
 		{099C4E10-1114-495C-A664-63A15E77B31A} = {4BAFC980-7A73-45C3-9460-8B8CCB87939B}
 		{FB9A43DE-00F0-42C4-BF92-AF61D752CCA2} = {4BAFC980-7A73-45C3-9460-8B8CCB87939B}
+		{B00FF75D-4C48-45ED-9A24-5C0D383317EE} = {4BAFC980-7A73-45C3-9460-8B8CCB87939B}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {197319DA-1148-4A99-847C-8B270B6A29AB}
diff --git a/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj b/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
index dae6aa66d..7b01192d7 100644
--- a/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
+++ b/src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj
@@ -76,6 +76,7 @@
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.Batched\Ray.Serilog.Sinks.Batched.csproj" />
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.CoolPushBatched\Ray.Serilog.Sinks.CoolPushBatched.csproj" />
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.DingTalkBatched\Ray.Serilog.Sinks.DingTalkBatched.csproj" />
+    <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.GotifyBatched\Ray.Serilog.Sinks.GotifyBatched.csproj" />
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.MicrosoftTeamsBatched\Ray.Serilog.Sinks.MicrosoftTeamsBatched.csproj" />
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.OtherApiBatched\Ray.Serilog.Sinks.OtherApiBatched.csproj" />
     <ProjectReference Include="..\Ray.Serilog.Sinks\Ray.Serilog.Sinks.PushPlusBatched\Ray.Serilog.Sinks.PushPlusBatched.csproj" />
diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json
index 1282cff1b..20fdd02eb 100644
--- a/src/Ray.BiliBiliTool.Console/appsettings.json
+++ b/src/Ray.BiliBiliTool.Console/appsettings.json
@@ -67,7 +67,8 @@
       "Ray.Serilog.Sinks.OtherApiBatched",
       "Ray.Serilog.Sinks.PushPlusBatched",
       "Ray.Serilog.Sinks.MicrosoftTeamsBatched",
-      "Ray.Serilog.Sinks.WorkWeiXinAppBatched"
+      "Ray.Serilog.Sinks.WorkWeiXinAppBatched",
+      "Ray.Serilog.Sinks.GotifyBatched"
     ],
     "MinimumLevel": {
       "Default": "Debug",
@@ -182,6 +183,15 @@
           "toTag": "",
           "restrictedToMinimumLevel": "Information"
         }
+      },
+      //12.gotify推送
+      {
+        "Name": "GotifyBatched",
+        "Args": {
+          "host": "", //必填,如https://www.mygotify.com
+          "token": "", //必填,应用(app)的token
+          "restrictedToMinimumLevel": "Information"
+        }
       }
     ],
     "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ]
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyApiClient.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyApiClient.cs
new file mode 100644
index 000000000..9f29700f8
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyApiClient.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Text;
+using Microsoft.VisualBasic.CompilerServices;
+using Newtonsoft.Json.Linq;
+using Ray.Serilog.Sinks.Batched;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeamsBatched
+{
+    public class GotifyApiClient : PushService
+    {
+        //https://gotify.net/docs
+
+        private readonly Uri _apiUrl;
+        private readonly HttpClient _httpClient = new HttpClient();
+        private readonly string _token;
+
+        public GotifyApiClient(
+            string host,
+            string token
+            )
+        {
+            _token = token;
+            _apiUrl = new Uri($"{host}/message");
+        }
+
+        public override string ClientName => "Gotify";
+
+        protected override string NewLineStr => "\n";
+
+        public override HttpResponseMessage DoSend()
+        {
+            var json = new
+            {
+                title = Title,
+                message = Msg,
+                extras = "{\"extras\":{\"client::display\":{\"contentType\":\"text/markdown\"}}}".ToObject<JObject>()
+            }.ToJson();
+
+            var content = new StringContent(json, Encoding.UTF8, "application/json");
+            content.Headers.Add("X-Gotify-Key", _token);
+            var response = _httpClient.PostAsync(_apiUrl, content).GetAwaiter().GetResult();
+            response.Content = new StringContent("");
+            return response;
+        }
+    }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyBatchedSink.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyBatchedSink.cs
new file mode 100644
index 000000000..acf01efbb
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyBatchedSink.cs
@@ -0,0 +1,39 @@
+using Ray.Serilog.Sinks.Batched;
+using Serilog.Events;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeamsBatched
+{
+    public class GotifyBatchedSink : BatchedSink
+    {
+        private readonly string _host;
+        private readonly string _token;
+
+        public GotifyBatchedSink(
+            string host,
+            string token,
+            Predicate<LogEvent> predicate,
+            bool sendBatchesAsOneMessages,
+            string outputTemplate,
+            IFormatProvider formatProvider,
+            LogEventLevel minimumLogEventLevel
+            )
+            : base(predicate, sendBatchesAsOneMessages, outputTemplate, formatProvider, minimumLogEventLevel)
+        {
+            _host = host;
+            _token = token;
+        }
+
+        public override void Emit(LogEvent logEvent)
+        {
+            if (_host.IsNullOrEmpty() || _token.IsNullOrEmpty()) return;
+            base.Emit(logEvent);
+        }
+
+        protected override PushService PushService => new GotifyApiClient(_host, _token);
+
+        public override void Dispose()
+        {
+            //todo
+        }
+    }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyConfigurationExtensions.cs b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyConfigurationExtensions.cs
new file mode 100644
index 000000000..7d0287d1d
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/GotifyConfigurationExtensions.cs
@@ -0,0 +1,41 @@
+using Ray.Serilog.Sinks.Batched;
+using Serilog;
+using Serilog.Configuration;
+using Serilog.Events;
+
+namespace Ray.Serilog.Sinks.MicrosoftTeamsBatched
+{
+    public static class GotifyConfigurationExtensions
+    {
+        public static LoggerConfiguration GotifyBatched(
+            this LoggerSinkConfiguration loggerSinkConfiguration,
+            string host,
+            string token,
+            string containsTrigger = Constants.DefaultContainsTrigger,
+            bool sendBatchesAsOneMessages = true,
+            string outputTemplate = Constants.DefaultOutputTemplate,
+            IFormatProvider formatProvider = null,
+            LogEventLevel restrictedToMinimumLevel = LogEventLevel.Verbose
+        )
+        {
+            if (loggerSinkConfiguration == null)
+                throw new ArgumentNullException(nameof(loggerSinkConfiguration));
+            if (outputTemplate == null)
+                throw new ArgumentNullException(nameof(outputTemplate));
+
+            if (containsTrigger.IsNullOrEmpty()) containsTrigger = Constants.DefaultContainsTrigger;
+            Predicate<LogEvent> predicate = x => x.MessageTemplate.Text.Contains(containsTrigger);
+
+            return loggerSinkConfiguration.Sink(
+                new GotifyBatchedSink(
+                    host,
+                    token,
+                    predicate,
+                    sendBatchesAsOneMessages,
+                    outputTemplate,
+                    formatProvider,
+                    restrictedToMinimumLevel),
+                restrictedToMinimumLevel);
+        }
+    }
+}
diff --git a/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/Ray.Serilog.Sinks.GotifyBatched.csproj b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/Ray.Serilog.Sinks.GotifyBatched.csproj
new file mode 100644
index 000000000..55eb04647
--- /dev/null
+++ b/src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/Ray.Serilog.Sinks.GotifyBatched.csproj
@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\..\Ray.BiliBiliTool.Infrastructure\Ray.BiliBiliTool.Infrastructure.csproj" />
+    <ProjectReference Include="..\Ray.Serilog.Sinks.Batched\Ray.Serilog.Sinks.Batched.csproj" />
+  </ItemGroup>
+
+</Project>

From 35d1c987de1ff76883e3440117fbb759fcda708f Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Thu, 25 Aug 2022 02:54:45 +0800
Subject: [PATCH 08/12] feat: update docker deploy way

---
 Dockerfile                                    |  1 +
 Ray.BiliBiliTool.sln                          |  1 -
 docker/build/buildImage.cmd                   |  2 +-
 docker/crontab                                |  1 +
 docker/entry.sh                               | 25 +++++++++++++------
 docker/sample/docker-compose.yml              |  9 +++++--
 docker/sample/my_crontab                      |  2 --
 src/Ray.BiliBiliTool.Console/appsettings.json | 11 +++++---
 8 files changed, 35 insertions(+), 17 deletions(-)
 delete mode 100644 docker/sample/my_crontab

diff --git a/Dockerfile b/Dockerfile
index 11daee9d5..350b2972d 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -22,6 +22,7 @@ COPY ["src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.PushPlusBatched/Ray.Serilog.Sinks
 COPY ["src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.ServerChanBatched/Ray.Serilog.Sinks.ServerChanBatched.csproj", "src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.ServerChanBatched/"]
 COPY ["src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeamsBatched/Ray.Serilog.Sinks.MicrosoftTeamsBatched.csproj", "src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.MicrosoftTeamsBatched/"]
 COPY ["src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.WorkWeiXinAppBatched/Ray.Serilog.Sinks.WorkWeiXinAppBatched.csproj", "src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.WorkWeiXinAppBatched/"]
+COPY ["src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/Ray.Serilog.Sinks.GotifyBatched.csproj", "src/Ray.Serilog.Sinks/Ray.Serilog.Sinks.GotifyBatched/"]
 RUN dotnet restore "src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj"
 COPY . .
 WORKDIR "/code/src/Ray.BiliBiliTool.Console"
diff --git a/Ray.BiliBiliTool.sln b/Ray.BiliBiliTool.sln
index 6c935e017..274a807e1 100644
--- a/Ray.BiliBiliTool.sln
+++ b/Ray.BiliBiliTool.sln
@@ -75,7 +75,6 @@ EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "sample", "sample", "{2F1CB892-336C-4672-8A0A-FBAEB4B9EA8A}"
 	ProjectSection(SolutionItems) = preProject
 		docker\sample\docker-compose.yml = docker\sample\docker-compose.yml
-		docker\sample\my_crontab = docker\sample\my_crontab
 	EndProjectSection
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Ray.Serilog.Sinks.Batched", "src\Ray.Serilog.Sinks\Ray.Serilog.Sinks.Batched\Ray.Serilog.Sinks.Batched.csproj", "{46EF6150-5D68-46B5-AA89-4198185FAF1A}"
diff --git a/docker/build/buildImage.cmd b/docker/build/buildImage.cmd
index 40012a5fe..f4916cb54 100644
--- a/docker/build/buildImage.cmd
+++ b/docker/build/buildImage.cmd
@@ -3,6 +3,6 @@
 REM start to build
 echo Start to build docker image
 @echo on
-docker build --tag zai7lou/bilibili_tool_pro:0.0.5 --tag zai7lou/bilibili_tool_pro:latest ../..
+docker build --tag zai7lou/bilibili_tool_pro:0.2.1 --tag zai7lou/bilibili_tool_pro:latest ../..
 @echo off
 pause
diff --git a/docker/crontab b/docker/crontab
index 12d29b515..de72028a6 100644
--- a/docker/crontab
+++ b/docker/crontab
@@ -1,2 +1,3 @@
 0 15 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=Daily >> /var/log/cron.log
 0 22 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=LiveLottery >> /var/log/cron.log
+7 1 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=VipBigPoint >> /var/log/cron.log
diff --git a/docker/entry.sh b/docker/entry.sh
index c7bc8cffe..186b86c77 100644
--- a/docker/entry.sh
+++ b/docker/entry.sh
@@ -3,24 +3,35 @@ set -e
 
 # https://stackoverflow.com/questions/27771781/how-can-i-access-docker-set-environment-variables-from-a-cron-job
 echo "[step 1/4]导入环境变量"
+printenv | grep -v "no_proxy" > /etc/environment
 declare -p | grep -v "no_proxy" > /etc/cron.env
 echo "=>完成"
 
 echo "[step 2/4]配置cron定时任务"
 echo "BASH_ENV=/etc/cron.env" > /etc/cron.d/bilicron
-if ! [ -z $Ray_Crontab ]; then
-	echo "=>检测到对应的环境变量,使用其值作为配置"
-	echo $Ray_Crontab >> /etc/cron.d/bilicron
-elif [ -e "/app/custom_crontab" ]; then 
-	echo "=>检测到自定义了cron定时任务,使用自定义配置"
-	cat /app/custom_crontab >> /etc/cron.d/bilicron
-else
+if [ -z "$Ray_DailyTaskConfig__Cron$Ray_LiveLotteryTaskConfig__Cron$Ray_UnfollowBatchedTaskConfig__Cron$Ray_VipBigPointConfig__Cron" ]; then
 	echo "=>使用默认cron定时任务配置"
 	cat /app/crontab >> /etc/cron.d/bilicron
+else
+	echo "=>检测到对应的环境变量,使用其值作为Cron配置"
+	echo "$Ray_Crontab" >> /etc/cron.d/bilicron
+	if ! [ -z "$Ray_DailyTaskConfig__Cron" ]; then
+		echo "$Ray_DailyTaskConfig__Cron dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=Daily >> /var/log/cron.log" >> /etc/cron.d/bilicron
+	fi
+	if ! [ -z "$Ray_LiveLotteryTaskConfig__Cron" ]; then
+		echo "$Ray_LiveLotteryTaskConfig__Cron dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=LiveLottery >> /var/log/cron.log" >> /etc/cron.d/bilicron
+	fi
+	if ! [ -z "$Ray_UnfollowBatchedTaskConfig__Cron" ]; then
+		echo "$Ray_UnfollowBatchedTaskConfig__Cron dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=UnfollowBatched >> /var/log/cron.log" >> /etc/cron.d/bilicron
+	fi
+	if ! [ -z "$Ray_VipBigPointConfig__Cron" ]; then
+		echo "$Ray_VipBigPointConfig__Cron dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=VipBigPoint >> /var/log/cron.log" >> /etc/cron.d/bilicron
+	fi
 fi
 echo "=>完成"
 
 echo "[step 3/4]启动定时任务,开启每日定时运行"
+cat /etc/cron.d/bilicron
 chmod 0644 /etc/cron.d/bilicron
 crontab /etc/cron.d/bilicron
 touch /var/log/cron.log
diff --git a/docker/sample/docker-compose.yml b/docker/sample/docker-compose.yml
index 693b093fb..3000a8b58 100644
--- a/docker/sample/docker-compose.yml
+++ b/docker/sample/docker-compose.yml
@@ -4,10 +4,9 @@ services:
   bilibili_tool:
     image: zai7lou/bilibili_tool_pro
     container_name: bilibili_tool_pro
-    restart: always
+    # restart: always
     volumes:
       - ./Logs:/app/Logs
-      - ./my_crontab:/app/custom_crontab
     tty: true
     environment:
       - ASPNETCORE_ENVIRONMENT=Production
@@ -17,6 +16,12 @@ services:
       - Ray_BiliBiliCookies__1=
       - Ray_BiliBiliCookies__2=
 
+      # 定时任务
+      - Ray_DailyTaskConfig__Cron=
+      - Ray_LiveLotteryTaskConfig__Cron=
+      - Ray_UnfollowBatchedTaskConfig__Cron=
+      - Ray_VipBigPointConfig__Cron=
+
       # UA:
       - Ray_Security__UserAgent=
       # 开始运行前随机随眠最大分钟数:
diff --git a/docker/sample/my_crontab b/docker/sample/my_crontab
deleted file mode 100644
index 12d29b515..000000000
--- a/docker/sample/my_crontab
+++ /dev/null
@@ -1,2 +0,0 @@
-0 15 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=Daily >> /var/log/cron.log
-0 22 * * * dotnet /app/Ray.BiliBiliTool.Console.dll --runTasks=LiveLottery >> /var/log/cron.log
diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json
index 20fdd02eb..5f93234d9 100644
--- a/src/Ray.BiliBiliTool.Console/appsettings.json
+++ b/src/Ray.BiliBiliTool.Console/appsettings.json
@@ -8,6 +8,7 @@
 
   //程序自定义个性化配置
   "DailyTaskConfig": {
+    "Cron": "0 15 * * *",
     "IsWatchVideo": true, //是否观看视频
     "IsShareVideo": true, //是否分享视频
     "NumberOfCoins": 5, //每日设定的投币数 [0,5]
@@ -22,6 +23,7 @@
   },
 
   "LiveLotteryTaskConfig": {
+    "Cron": "0 22 * * *",
     "ExcludeAwardNames": "舰|船|航海|代金券|自拍|照|写真|图|提督", //根据关键字排除包含这些文字的奖品名称,多个用“|”分隔,如“照|舰|船|航海|代金券|自拍”
     "IncludeAwardNames": "", //根据关键字指定奖品名称必须包含的文字,多个用“|”分隔,如“红包|现金|块|元”
     "AutoGroupFollowings": true, //抽奖结束后是否自动将关注的主播分组到“天选时刻”分组,值域[true,false]
@@ -29,13 +31,14 @@
   },
 
   "UnfollowBatchedTaskConfig": {
+    "Cron": "0 6 1 * *",
     "GroupName": "天选时刻", //取关的分组名称
-    "Count": 1, //本次取关个数(倒序,从后往前取关)
-    "RetainUids": "108569350" //白名单(保留的UpId),多个用英文都好分隔,配置后,批量取关时不会取关配置的Up
+    "Count": 20, //本次取关个数(倒序,从后往前取关)
+    "RetainUids": "" //白名单(保留的UpId),多个用英文都好分隔,配置后,批量取关时不会取关配置的Up
   },
 
-  "ReceiveVipPrivilegeConfig": {
-    "IsEnable": true //开关 
+  "VipBigPointConfig": {
+    "Cron": "7 1 * * *"
   },
 
   //安全相关配置

From dd50bc949cf871c088ec0cc724726b4d1ca3394f Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Thu, 25 Aug 2022 11:32:47 +0800
Subject: [PATCH 09/12] feat: rebuild docker compose deploy way

---
 docker/README.md                 | 50 +++++++++++++++++++++-----------
 docker/sample/docker-compose.yml | 10 +++----
 2 files changed, 38 insertions(+), 22 deletions(-)

diff --git a/docker/README.md b/docker/README.md
index 6953c79e5..27e57f2be 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -3,15 +3,17 @@
 
 - [1. 前期工作](#1-前期工作)
     - [1.1. Docker环境](#11-docker环境)
-	- [1.2. 须知](#12-须知)
-- [2. Docker Compose版](#2-docker-compose版推荐)
+    - [1.2. 须知](#12-须知)
+- [2. Docker-Compose版(推荐)](#2-docker-compose版推荐)
+    - [2.1. 启动](#21-启动)
+    - [2.2. 修改bili下的docker-compose.yml,填入cookie](#22-修改bili下的docker-composeyml填入cookie)
+    - [2.3. 其他命令参考](#23-其他命令参考)
 - [3. Docker版](#3-docker版)
-	- [3.1. Docker启动](#31-docker启动)
-	- [3.2. 通过Watchtower手动更新容器](#32-通过watchtower手动更新容器)
+    - [3.1. Docker启动](#31-docker启动)
+    - [3.2. 使用Watchtower更新容器](#32-使用watchtower更新容器)
 - [4. 自己构建镜像(非必须)](#4-自己构建镜像非必须)
 - [5. 其他](#5-其他)
 
-
 <!-- /TOC -->
 ## 1. 前期工作
 
@@ -35,23 +37,39 @@ Window系统推荐使用Docker Desktop,官方下载安装包,一路鼠标点
 
 
 ## 2. Docker-Compose版(推荐) 
-在本地路径下,创建并进入目录 `bilibili_tool` 
 
+### 2.1. 启动
 ```
-# 下载项目里面的模板,`my_crontab`文件以及`docker-compose.yml`文件
+# 创建目录
+mkdir bili
+cd bili
 
-# 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
-# 或考虑配置`Ray_Crontab`环境变量
-wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/my_crontab
-
-# 根据 docker-compose.yaml 里面的注释编辑所需配置,`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
+# 下载
+wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/src/Ray.BiliBiliTool.Console/appsettings.json
 wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/docker-compose.yml
 
+# 启动
+docker-compose up -d
+
+# 查看启动日志
+docker logs -f bilibili_tool_pro
+```
+
+### 2.2. 修改bili下的docker-compose.yml,填入cookie
+
+根据 docker-compose.yaml 里面的注释编辑所需配置,`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
+
+保存后,重新运行下`docker-compose up -d`
+
 最终文件结构如下:
-bilibili_tool
-├── docker-compose.yml
-└── my_crontab
 
+bili
+├── appsettings.json
+└── docker-compose.yml
+
+### 2.3. 其他命令参考
+
+```
 # 启动 docker-compose
 docker-compose up -d
 
@@ -66,10 +84,8 @@ docker exec -it bilibili_tool_pro /bin/bash
 
 # 手动更新容器
 docker-compose pull && docker-compose up -d
-
 ```
 
-
 ## 3. Docker版
 
 ### 3.1. Docker启动
diff --git a/docker/sample/docker-compose.yml b/docker/sample/docker-compose.yml
index 3000a8b58..5c9cad5f8 100644
--- a/docker/sample/docker-compose.yml
+++ b/docker/sample/docker-compose.yml
@@ -17,15 +17,15 @@ services:
       - Ray_BiliBiliCookies__2=
 
       # 定时任务
-      - Ray_DailyTaskConfig__Cron=
-      - Ray_LiveLotteryTaskConfig__Cron=
-      - Ray_UnfollowBatchedTaskConfig__Cron=
-      - Ray_VipBigPointConfig__Cron=
+      - Ray_DailyTaskConfig__Cron=0 15 * * *
+      - Ray_LiveLotteryTaskConfig__Cron=0 22 * * *
+      - Ray_UnfollowBatchedTaskConfig__Cron=0 6 1 * *
+      - Ray_VipBigPointConfig__Cron=7 1 * * *
 
       # UA:
       - Ray_Security__UserAgent=
       # 开始运行前随机随眠最大分钟数:
-      - Ray_Security__RandomSleepMaxMin=
+      - Ray_Security__RandomSleepMaxMin=2
       # 调用接口间的间隔秒数:
       - Ray_Security__IntervalSecondsBetweenRequestApi=
 

From 5f010ec572aa3ecaed0628f800a4f9b71944d6cc Mon Sep 17 00:00:00 2001
From: Ray Wang <ray.wang@batechworks.com>
Date: Thu, 25 Aug 2022 18:32:53 +0800
Subject: [PATCH 10/12] feat: update docker doc

---
 docker/README.md | 50 ++++++++++++++++++++++++++----------------------
 1 file changed, 27 insertions(+), 23 deletions(-)

diff --git a/docker/README.md b/docker/README.md
index 27e57f2be..de5778d46 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -4,13 +4,14 @@
 - [1. 前期工作](#1-前期工作)
     - [1.1. Docker环境](#11-docker环境)
     - [1.2. 须知](#12-须知)
-- [2. Docker-Compose版(推荐)](#2-docker-compose版推荐)
+- [2. 方式一:Docker Compose(推荐)](#2-方式一docker-compose推荐)
     - [2.1. 启动](#21-启动)
     - [2.2. 修改bili下的docker-compose.yml,填入cookie](#22-修改bili下的docker-composeyml填入cookie)
     - [2.3. 其他命令参考](#23-其他命令参考)
-- [3. Docker版](#3-docker版)
+- [3. 方式二:Docker指令](#3-方式二docker指令)
     - [3.1. Docker启动](#31-docker启动)
-    - [3.2. 使用Watchtower更新容器](#32-使用watchtower更新容器)
+    - [3.2. 其他指令参考](#32-其他指令参考)
+    - [3.3. 使用Watchtower更新容器](#33-使用watchtower更新容器)
 - [4. 自己构建镜像(非必须)](#4-自己构建镜像非必须)
 - [5. 其他](#5-其他)
 
@@ -24,19 +25,21 @@
 Linux一键安装命令:
 `curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun`
 
-Window系统推荐使用Docker Desktop,官方下载安装包,一路鼠标点下去就能装好,运行时也有可视化页面。
+Window系统推荐使用Docker Desktop,官方下载安装包安装。
 
 安装完成后,请执行`docker --version`检查`Docker`是否安装成功,请执行`docker compose version`检查`Docker Compose`是否安装成功。
 
 ### 1.2. 须知
 
+- Docker有两种部署方式:使用`Docker Compose`或使用docker指令,选择其中一种即可
 
-每次容器启动会去跑一遍 Test 任务,用于测试 Cookie ,其他任务由设定的Cron来指定定时触发。
+- 以下章节,凡设计到下载GitHub文件的,如`wget https://raw.githubusercontent.com...`,需要有良好的互联网环境,如果是“局域网”,可以在地址前添加`https://ghproxy.com/`,比如更改为`wget https://ghproxy.com/https://raw.githubusercontent.com...`
 
-想手动运行某任务的话,[查看功能任务参数](https://github.com/RayWangQvQ/BiliBiliToolPro/tree/develop#2-功能任务说明) 请进入容器后输入命令来启动执行。
+- 每次容器启动会去跑一遍 Test 任务,用于测试 Cookie ,其他任务由设定的Cron来指定定时触发。
 
+- 想手动运行某任务的话,[查看功能任务参数](https://github.com/RayWangQvQ/BiliBiliToolPro/tree/develop#2-功能任务说明) 请进入容器后输入命令来启动执行。
 
-## 2. Docker-Compose版(推荐) 
+## 2. 方式一:Docker Compose(推荐) 
 
 ### 2.1. 启动
 ```
@@ -86,28 +89,30 @@ docker exec -it bilibili_tool_pro /bin/bash
 docker-compose pull && docker-compose up -d
 ```
 
-## 3. Docker版
+## 3. 方式二:Docker指令
 
 ### 3.1. Docker启动
-```
-# 下载项目里面的模板,`my_crontab`文件以及`appsettings.json`文件
-
-# 如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
-wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/docker/sample/my_crontab
-
-# 根据 appsettings.json 里面的注释编辑所需配置 (暂定develop分支下载路径)
-wget https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/develop/docker/sample/appsettings.json
 
-# Docker启动命令,/root/bilibili_tool/为映射目录
-docker run -d --restart always --name="bilibili_tool_pro" \
-    -v /root/bilibili_tool/logs:/app/Logs \
-    -v /root/bilibili_tool/my_crontab:/app/custom_crontab \
-    -v /root/bilibili_tool/appsettings.json:/app/appsettings.json \
+```
+# 生成并运行容器
+docker run -d --name="bilibili_tool_pro" \
+    -v /bilibili_tool/Logs:/app/Logs \
+    -e Ray_BiliBiliCookies__1="cookie" \
+    -e Ray_DailyTaskConfig__Cron="0 15 * * *" \
+    -e Ray_LiveLotteryTaskConfig__Cron="0 22 * * *" \
+    -e Ray_UnfollowBatchedTaskConfig__Cron="0 6 1 * *" \
+    -e Ray_VipBigPointConfig__Cron="7 1 * * *" \
     zai7lou/bilibili_tool_pro
 
 # 查看实时日志
 docker logs -f bilibili_tool_pro
+```
 
+其中,`cookie`需要替换为自己真实的cookie字符串
+
+### 3.2. 其他指令参考
+
+```
 # 启动容器
 docker start bilibili_tool_pro
 
@@ -119,10 +124,9 @@ docker rm bilibili_tool_pro
 
 # 进入容器
 docker exec -it bilibili_tool_pro /bin/bash
-
 ```
 
-### 3.2. 使用Watchtower更新容器
+### 3.3. 使用Watchtower更新容器
 ```
 docker run --rm \
     -v /var/run/docker.sock:/var/run/docker.sock \

From f1ab2b0b627026f03696aad1d9783f0bae1e1ba5 Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Thu, 25 Aug 2022 22:03:13 +0800
Subject: [PATCH 11/12] feat: update change log

---
 CHANGELOG.md     | 1 +
 docker/README.md | 1 +
 2 files changed, 2 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index cd9c57a39..5b88b3229 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,3 +53,4 @@
 - 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
 - Feature(#65):新增TG推送配置并使用代理功能
 - Feature(#240):新增gotify推送
+- Feature:更新、优化docker部署文档
diff --git a/docker/README.md b/docker/README.md
index de5778d46..c5e1a603a 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -42,6 +42,7 @@ Window系统推荐使用Docker Desktop,官方下载安装包安装。
 ## 2. 方式一:Docker Compose(推荐) 
 
 ### 2.1. 启动
+
 ```
 # 创建目录
 mkdir bili

From 3764f8083737b4bb1327cca0fe06642393ae7474 Mon Sep 17 00:00:00 2001
From: Ray <zai7lou@outlook.com>
Date: Thu, 25 Aug 2022 22:57:18 +0800
Subject: [PATCH 12/12] feature: update vip type to enum and check status when
 tasks

---
 CHANGELOG.md                                  |  1 +
 .../BiliBiliAgent/Dtos/UserInfo.cs            | 10 ++++-----
 .../BiliBiliAgent/Dtos/VipStatus.cs           | 13 ++++++++++++
 .../BiliBiliAgent/Dtos/VipType.cs             | 21 +++++++++++++++++++
 .../VipBigPointAppService.cs                  | 16 ++++++++------
 .../AccountDomainService.cs                   |  8 ++++---
 .../ChargeDomainService.cs                    |  4 ++--
 .../VipPrivilegeDomainService.cs              |  7 +++----
 8 files changed, 60 insertions(+), 20 deletions(-)
 create mode 100644 src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipStatus.cs
 create mode 100644 src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipType.cs

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5b88b3229..40f920e66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -53,4 +53,5 @@
 - 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
 - Feature(#65):新增TG推送配置并使用代理功能
 - Feature(#240):新增gotify推送
+- Feature(#259):大会员状态改为枚举类型,当非会员时自动跳过大积分任务
 - Feature:更新、优化docker部署文档
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/UserInfo.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/UserInfo.cs
index d80f325a9..1d7a6ea83 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/UserInfo.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/UserInfo.cs
@@ -32,9 +32,9 @@ public class UserInfo
         /// 会员状态
         /// <para>只有VipStatus为1的时候获取到VipType才是有效的</para>
         /// </summary>
-        public int VipStatus { get; set; }
+        public VipStatus VipStatus { get; set; }
 
-        public int VipType { get; set; }//todo:是否可以改为枚举
+        public VipType VipType { get; set; }
 
         /// <summary>
         /// 获取隐私处理后的用户名
@@ -62,16 +62,16 @@ public string GetFuzzyUname()
         /// <para>1:月会员</para>
         /// <para>2:年会员</para>
         /// </returns>
-        public int GetVipType()
+        public VipType GetVipType()
         {
-            if (VipStatus == 1)
+            if (VipStatus == VipStatus.Enable)
             {
                 //只有VipStatus为1的时候获取到VipType才是有效的。
                 return VipType;
             }
             else
             {
-                return 0;
+                return VipType.None;
             }
         }
     }
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipStatus.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipStatus.cs
new file mode 100644
index 000000000..2989530f1
--- /dev/null
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipStatus.cs
@@ -0,0 +1,13 @@
+using System.ComponentModel;
+
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos
+{
+    public enum VipStatus
+    {
+        [Description("无/过期")]
+        Disable = 0,
+
+        [Description("正常")]
+        Enable = 1,
+    }
+}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipType.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipType.cs
new file mode 100644
index 000000000..8a6d2d487
--- /dev/null
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipType.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos
+{
+    public enum VipType
+    {
+        [Description("无")]
+        None = 0,
+
+        [Description("月度大会员")]
+        Mensual = 1,
+
+        [Description("年度大会员")]
+        Annual = 2
+    }
+}
diff --git a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs
index c3e454faf..bd2de21c3 100644
--- a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs
+++ b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs
@@ -1,17 +1,13 @@
 using System;
 using System.Linq;
-using System.Runtime.InteropServices;
 using System.Threading.Tasks;
 using Microsoft.Extensions.Configuration;
 using Microsoft.Extensions.Logging;
-using Microsoft.Extensions.Options;
-using Ray.BiliBiliTool.Agent;
 using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
 using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask;
 using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
 using Ray.BiliBiliTool.Application.Attributes;
 using Ray.BiliBiliTool.Application.Contracts;
-using Ray.BiliBiliTool.Config.Options;
 using Ray.BiliBiliTool.DomainService.Interfaces;
 
 namespace Ray.BiliBiliTool.Application
@@ -39,7 +35,13 @@ IAccountDomainService loginDomainService
         [TaskInterceptor("大会员大积分", TaskLevel.One)]
         public override void DoTask()
         {
-            GetUserInfo();
+            var ui = GetUserInfo();
+
+            if (ui.GetVipType() == VipType.None)
+            {
+                _logger.LogInformation("当前不是大会员或已过期,跳过任务");
+                return;
+            }
 
             var re = _vipApi.GetTaskList().Result;
 
@@ -80,10 +82,12 @@ public override void DoTask()
         }
 
         [TaskInterceptor("测试Cookie")]
-        private void GetUserInfo()
+        private UserInfo GetUserInfo()
         {
             UserInfo userInfo = _loginDomainService.LoginByCookie();
             if (userInfo == null) throw new Exception("登录失败,请检查Cookie");//终止流程
+
+            return userInfo;
         }
 
         [TaskInterceptor("签到", TaskLevel.Two, false)]
diff --git a/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs b/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs
index 6f34ee5ce..fcece4462 100644
--- a/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs
+++ b/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs
@@ -61,12 +61,14 @@ public UserInfo LoginByCookie()
             //获取到UserId
             _cookie.UserId = useInfo.Mid.ToString();
 
-            _logger.LogInformation("【用户名】 {0}", useInfo.GetFuzzyUname());
-            _logger.LogInformation("【硬币余额】 {0}", useInfo.Money ?? 0);
+            _logger.LogInformation("【用户名】{0}", useInfo.GetFuzzyUname());
+            _logger.LogInformation("【会员类型】{0}", useInfo.VipType.Description());
+            _logger.LogInformation("【会员状态】{0}", useInfo.VipStatus.Description());
+            _logger.LogInformation("【硬币余额】{0}", useInfo.Money ?? 0);
 
             if (useInfo.Level_info.Current_level < 6)
             {
-                _logger.LogInformation("【距升级 Lv{0}】 {1}天(如每日做满65点经验)",
+                _logger.LogInformation("【距升级Lv{0}】{1}天(如每日做满65点经验)",
                     useInfo.Level_info.Current_level + 1,
                     (useInfo.Level_info.GetNext_expLong() - useInfo.Level_info.Current_exp) / Constants.EveryDayExp);
             }
diff --git a/src/Ray.BiliBiliTool.DomainService/ChargeDomainService.cs b/src/Ray.BiliBiliTool.DomainService/ChargeDomainService.cs
index 3e059df80..771f69736 100644
--- a/src/Ray.BiliBiliTool.DomainService/ChargeDomainService.cs
+++ b/src/Ray.BiliBiliTool.DomainService/ChargeDomainService.cs
@@ -48,8 +48,8 @@ public void Charge(UserInfo userInfo)
             }
 
             //大会员类型
-            int vipType = userInfo.GetVipType();
-            if (vipType != 2)
+            VipType vipType = userInfo.GetVipType();
+            if (vipType != VipType.Annual)
             {
                 _logger.LogInformation("不是年度大会员,跳过");
                 return;
diff --git a/src/Ray.BiliBiliTool.DomainService/VipPrivilegeDomainService.cs b/src/Ray.BiliBiliTool.DomainService/VipPrivilegeDomainService.cs
index df25e76a3..5392dc7b1 100644
--- a/src/Ray.BiliBiliTool.DomainService/VipPrivilegeDomainService.cs
+++ b/src/Ray.BiliBiliTool.DomainService/VipPrivilegeDomainService.cs
@@ -1,5 +1,4 @@
-using System;
-using Microsoft.Extensions.Logging;
+using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Options;
 using Ray.BiliBiliTool.Agent;
 using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
@@ -47,8 +46,8 @@ public bool ReceiveVipPrivilege(UserInfo userInfo)
             }
 
             //大会员类型
-            int vipType = userInfo.GetVipType();
-            if (vipType != 2)
+            VipType vipType = userInfo.GetVipType();
+            if (vipType != VipType.Annual)
             {
                 _logger.LogInformation("普通会员和月度大会员每月不赠送B币券,不需要领取权益喽");
                 return false;