diff --git a/CHANGELOG.md b/CHANGELOG.md
index c5aecfbd1..40f920e66 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -48,3 +48,10 @@
 - 【#197】合并PR,新增了阅读漫画功能到每日任务中(@ChanceLuo)
 ## 0.2.0
 - 新增大会员大积分任务
+## 0.2.1
+- 合并PR(#253、#257),更新文档(@layui0320)
+- 合并PR(#256),重构docker运行是cron构建方式,并优化读取环境变量的方式(@syrinka)
+- Feature(#65):新增TG推送配置并使用代理功能
+- Feature(#240):新增gotify推送
+- Feature(#259):大会员状态改为枚举类型,当非会员时自动跳过大积分任务
+- Feature:更新、优化docker部署文档
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/README.md b/README.md
index 982927150..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 仓库后,在**devlop 分支**进行编码开发,完成后**提交 pr 到 devlop 分支**,并标注解决的 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/Ray.BiliBiliTool.sln b/Ray.BiliBiliTool.sln
index 203bb3b25..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}"
@@ -152,6 +151,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 +239,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 +282,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/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>
diff --git a/docker/README.md b/docker/README.md
index 4731bb7d8..c5e1a603a 100644
--- a/docker/README.md
+++ b/docker/README.md
@@ -2,72 +2,153 @@
 <!-- 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推荐)
+    - [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. 其他指令参考](#32-其他指令参考)
+    - [3.3. 使用Watchtower更新容器](#33-使用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,官方下载安装包,一路鼠标点下去就能装好,运行时也有可视化页面。
+Linux一键安装命令:
+`curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun`
 
-安装完成后,请执行`docker --version`检查`docker`是否安装成功,请执行`docker compose version`检查`docker compose`是否安装成功。
+Window系统推荐使用Docker Desktop,官方下载安装包安装。
 
-### 1.2. 良好的网络
+安装完成后,请执行`docker --version`检查`Docker`是否安装成功,请执行`docker compose version`检查`Docker Compose`是否安装成功。
 
-第一次运行,可能时间比较长,因为本地没有镜像缓存,第二次之后构建速度就很快了。
+### 1.2. 须知
 
-## 2. 生成容器并运行
+- Docker有两种部署方式:使用`Docker Compose`或使用docker指令,选择其中一种即可
 
-推荐使用 docker-compose 来运行容器,步骤如下:
+- 以下章节,凡设计到下载GitHub文件的,如`wget https://raw.githubusercontent.com...`,需要有良好的互联网环境,如果是“局域网”,可以在地址前添加`https://ghproxy.com/`,比如更改为`wget https://ghproxy.com/https://raw.githubusercontent.com...`
 
-### 2.1. 本地创建文件
-在本地任意文件夹下,创建一个目录 `bilibili_tool` ,在其下新建`docker-compose.yml`文件和`my_crontab`文件,文件结构如下:
+- 每次容器启动会去跑一遍 Test 任务,用于测试 Cookie ,其他任务由设定的Cron来指定定时触发。
+
+- 想手动运行某任务的话,[查看功能任务参数](https://github.com/RayWangQvQ/BiliBiliToolPro/tree/develop#2-功能任务说明) 请进入容器后输入命令来启动执行。
+
+## 2. 方式一:Docker Compose(推荐) 
+
+### 2.1. 启动
+
+```
+# 创建目录
+mkdir bili
+cd bili
+
+# 下载
+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`
+
+最终文件结构如下:
+
+bili
+├── appsettings.json
+└── docker-compose.yml
+
+### 2.3. 其他命令参考
+
+```
+# 启动 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
+```
+
+## 3. 方式二:Docker指令
+
+### 3.1. Docker启动
 
 ```
-bilibili_tool
-├── docker-compose.yml
-└── my_crontab
+# 生成并运行容器
+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
 ```
 
-### 2.2. 编辑文件内容,填入相关配置
-`docker-compose.yml`的文件内容请拷贝 [默认docker-compose.yml](../docker/sample/docker-compose.yml) 内容。`environment` 下可以通过环境变量自由添加自定义配置,其中Cookie是必填的,所以请至少填入Cookie并保存。
+其中,`cookie`需要替换为自己真实的cookie字符串
 
-`my_crontab`的文件内容请拷贝 [默认my_crontab](../docker/sample/my_crontab) 内容,注意末尾有个换行不要丢了。
+### 3.2. 其他指令参考
 
-### 2.3. 启动并运行容器
-在当前目录(有docker-compose.yml的目录)执行启动容器命令:`docker compose up -d`。
+```
+# 启动容器
+docker start bilibili_tool_pro
 
-提示成功的话,即表示容器启动成功。
+# 停止容器
+docker stop bilibili_tool_pro
 
-可以进入容器查看详细运行日志,Desktop 通过点击相应容器名就能进入,可以很清晰的看到日志和容器信息;linux 的话请使用相应的docker命令查看,另外当前目录也会生成 Logs 日志文件。
+# 删除容器
+docker rm bilibili_tool_pro
 
-每次容器启动会去跑一遍 Test 任务,用于测试 Cookie 。其他任务由设定的cron来指定定时触发,如需修改定时运行时间,请修改`my_crontab`中的cron表达式,然后再次执行启动容器命令。
+# 进入容器
+docker exec -it bilibili_tool_pro /bin/bash
+```
 
-想手动运行某任务的话,请进入容器后输入相应命令来启动执行。
+### 3.3. 使用Watchtower更新容器
+```
+docker run --rm \
+    -v /var/run/docker.sock:/var/run/docker.sock \
+    containrrr/watchtower \
+    --run-once --cleanup \
+    bilibili_tool_pro
+```
 
-## 3. 自己构建镜像(非必须)
+## 4. 自己构建镜像(非必须)
 
 目前我提供和维护的镜像:`[zai7lou/bilibili_tool_pro](https://hub.docker.com/repository/docker/zai7lou/bilibili_tool_pro)`;
 
 如果有需要(大部分都不需要),可以使用源码自己构建镜像,如下:
 
-在有Dockerfile的目录运行
+在有项目的Dockerfile的目录运行
 
 `docker build -t TARGET_NAME .`
 
  `TARGET_NAME`为镜像名称和版本,可以自己起个名字
 
-## 4. 其他
+## 5. 其他
 
 代码编译和发布环境: mcr.microsoft.com/dotnet/sdk:6.0
 
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 a4d9edc8d..186b86c77 100644
--- a/docker/entry.sh
+++ b/docker/entry.sh
@@ -4,20 +4,34 @@ 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 "=>检测到自定义了cron定时任务,使用自定义配置"
-	cp /app/custom_crontab /etc/cron.d/bilicron
-else
+echo "BASH_ENV=/etc/cron.env" > /etc/cron.d/bilicron
+if [ -z "$Ray_DailyTaskConfig__Cron$Ray_LiveLotteryTaskConfig__Cron$Ray_UnfollowBatchedTaskConfig__Cron$Ray_VipBigPointConfig__Cron" ]; then
 	echo "=>使用默认cron定时任务配置"
-	cp /app/crontab /etc/cron.d/bilicron
+	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/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
+}
diff --git a/docker/sample/docker-compose.yml b/docker/sample/docker-compose.yml
index 693b093fb..5c9cad5f8 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,10 +16,16 @@ services:
       - Ray_BiliBiliCookies__1=
       - Ray_BiliBiliCookies__2=
 
+      # 定时任务
+      - 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=
 
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/docs/configuration.md b/docs/configuration.md
index 09a81d50f..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,6 +71,7 @@
     - [3.7. 日志相关](#37-日志相关)
         - [3.7.1. Console日志输出等级](#371-console日志输出等级)
         - [3.7.2. Console日志输出样式](#372-console日志输出样式)
+        - [3.7.3. crontab相关](#373-crontab相关)
 
 <!-- /TOC -->
 
@@ -557,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. 企业微信机器人
 
@@ -642,6 +658,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 +669,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 +846,21 @@ BiliBiliTool 使用 Serilog 作为日志组件,所以可以参考 Serilog 的
 | 环境变量   | `Ray_Serilog__WriteTo__0__Args__outputTemplate` |
 | GitHub Secrets  | `CONSOLELOGTEMPLATE` |
 
+<a id="markdown-373-crontab相关" name="373-crontab相关"></a>
+#### 3.7.3. 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` |
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.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 a32cb5712..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 * * *"
   },
 
   //安全相关配置
@@ -67,7 +70,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",
@@ -104,7 +108,8 @@
         "Args": {
           "botToken": "",
           "chatId": "",
-          "restrictedToMinimumLevel": "Information"
+          "restrictedToMinimumLevel": "Information",
+          "proxy": "" //代理,user:password@host:port
         }
       },
       //4.企业微信机器人(https://work.weixin.qq.com/api/doc/90000/90136/91770)
@@ -181,6 +186,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.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;
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>
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);
         }
     }
 }