diff --git a/.editorconfig b/.editorconfig
index 8616aec3e..65d1b6620 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,31 +1,260 @@
-# EditorConfig is awesome: https://EditorConfig.org
-
-# top-most EditorConfig file
-root = true
-
-# Default settings:
-# A newline ending every file
-# Use CRLF line break
-# Use 4 spaces as indentation
-[*]
-end_of_line = crlf
-trim_trailing_whitespace = true
-insert_final_newline = true
-indent_style = space
-indent_size = 4
-
-# Json config files
-[*.json]
-indent_size = 2
-
-# Yaml config files
-[*.{yml,yaml}]
-indent_size = 2
-
-# Xml project files
-[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
-indent_size = 2
-
-# Xml config files
-[*.{props,targets,config,nuspec}]
-indent_size = 2
+# EditorConfig is awesome: https://EditorConfig.org
+
+# top-most EditorConfig file
+root = true
+
+# Default settings:
+# A newline ending every file
+# Use CRLF line break
+# Use 4 spaces as indentation
+[*]
+end_of_line = lf
+trim_trailing_whitespace = true
+insert_final_newline = true
+indent_style = space
+indent_size = 4
+
+# Json config files
+[*.json]
+indent_size = 2
+
+# Yaml config files
+[*.{yml,yaml}]
+indent_size = 2
+
+# Xml project files
+[*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
+indent_size = 2
+
+# Xml config files
+[*.{props,targets,config,nuspec}]
+indent_size = 2
+
+# c# 文件
+[*.cs]
+
+#### Core EditorConfig 选项 ####
+
+# 缩进和间距
+indent_size = 4
+indent_style = space
+tab_width = 4
+
+# 新行首选项
+end_of_line = lf
+insert_final_newline = false
+
+#### .NET 编码约定 ####
+
+# 组织 Using
+dotnet_separate_import_directive_groups = false
+dotnet_sort_system_directives_first = false
+file_header_template = unset
+
+# this. 和 Me. 首选项
+dotnet_style_qualification_for_event = false
+dotnet_style_qualification_for_field = false
+dotnet_style_qualification_for_method = false
+dotnet_style_qualification_for_property = false
+
+# 语言关键字与 bcl 类型首选项
+dotnet_style_predefined_type_for_locals_parameters_members = true
+dotnet_style_predefined_type_for_member_access = true
+
+# 括号首选项
+dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
+dotnet_style_parentheses_in_other_operators = never_if_unnecessary
+dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
+
+# 修饰符首选项
+dotnet_style_require_accessibility_modifiers = for_non_interface_members
+
+# 表达式级首选项
+dotnet_style_coalesce_expression = true
+dotnet_style_collection_initializer = true
+dotnet_style_explicit_tuple_names = true
+dotnet_style_namespace_match_folder = true
+dotnet_style_null_propagation = true
+dotnet_style_object_initializer = true
+dotnet_style_operator_placement_when_wrapping = beginning_of_line
+dotnet_style_prefer_auto_properties = true
+dotnet_style_prefer_collection_expression = when_types_loosely_match
+dotnet_style_prefer_compound_assignment = true
+dotnet_style_prefer_conditional_expression_over_assignment = true
+dotnet_style_prefer_conditional_expression_over_return = true
+dotnet_style_prefer_foreach_explicit_cast_in_source = when_strongly_typed
+dotnet_style_prefer_inferred_anonymous_type_member_names = true
+dotnet_style_prefer_inferred_tuple_names = true
+dotnet_style_prefer_is_null_check_over_reference_equality_method = true
+dotnet_style_prefer_simplified_boolean_expressions = true
+dotnet_style_prefer_simplified_interpolation = true
+
+# 字段首选项
+dotnet_style_readonly_field = true
+
+# 参数首选项
+dotnet_code_quality_unused_parameters = all
+
+# 禁止显示首选项
+dotnet_remove_unnecessary_suppression_exclusions = none
+
+# 新行首选项
+dotnet_style_allow_multiple_blank_lines_experimental = true
+dotnet_style_allow_statement_immediately_after_block_experimental = true
+
+#### c# 编码约定 ####
+
+# var 首选项
+csharp_style_var_elsewhere = false
+csharp_style_var_for_built_in_types = false
+csharp_style_var_when_type_is_apparent = true
+
+# Expression-bodied 成员
+csharp_style_expression_bodied_accessors = true
+csharp_style_expression_bodied_constructors = false
+csharp_style_expression_bodied_indexers = true
+csharp_style_expression_bodied_lambdas = true
+csharp_style_expression_bodied_local_functions = false
+csharp_style_expression_bodied_methods = true
+csharp_style_expression_bodied_operators = false
+csharp_style_expression_bodied_properties = true
+
+# 模式匹配首选项
+csharp_style_pattern_matching_over_as_with_null_check = true
+csharp_style_pattern_matching_over_is_with_cast_check = true
+csharp_style_prefer_extended_property_pattern = true
+csharp_style_prefer_not_pattern = true
+csharp_style_prefer_pattern_matching = true
+csharp_style_prefer_switch_expression = true
+
+# Null 检查首选项
+csharp_style_conditional_delegate_call = true
+
+# 修饰符首选项
+csharp_prefer_static_local_function = true
+csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
+csharp_style_prefer_readonly_struct = true
+csharp_style_prefer_readonly_struct_member = true
+
+# 代码块首选项
+csharp_prefer_braces = when_multiline
+csharp_prefer_simple_using_statement = true
+csharp_style_namespace_declarations = file_scoped
+csharp_style_prefer_method_group_conversion = true
+csharp_style_prefer_primary_constructors = true
+csharp_style_prefer_top_level_statements = true
+
+# 表达式级首选项
+csharp_prefer_simple_default_expression = true
+csharp_style_deconstructed_variable_declaration = true
+csharp_style_implicit_object_creation_when_type_is_apparent = true
+csharp_style_inlined_variable_declaration = true
+csharp_style_prefer_index_operator = true
+csharp_style_prefer_local_over_anonymous_function = true
+csharp_style_prefer_null_check_over_type_check = true
+csharp_style_prefer_range_operator = true
+csharp_style_prefer_tuple_swap = true
+csharp_style_prefer_utf8_string_literals = true
+csharp_style_throw_expression = true
+csharp_style_unused_value_assignment_preference = discard_variable
+csharp_style_unused_value_expression_statement_preference = discard_variable
+
+# "using" 指令首选项
+csharp_using_directive_placement = outside_namespace
+
+# 新行首选项
+csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
+csharp_style_allow_blank_line_after_token_in_arrow_expression_clause_experimental = true
+csharp_style_allow_blank_line_after_token_in_conditional_expression_experimental = true
+csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
+csharp_style_allow_embedded_statements_on_same_line_experimental = true
+
+#### C# 格式规则 ####
+
+# 新行首选项
+csharp_new_line_before_catch = true
+csharp_new_line_before_else = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_open_brace = all
+csharp_new_line_between_query_expression_clauses = true
+
+# 缩进首选项
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents = true
+csharp_indent_case_contents_when_block = true
+csharp_indent_labels = one_less_than_current
+csharp_indent_switch_labels = true
+
+# 空格键首选项
+csharp_space_after_cast = false
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_after_comma = true
+csharp_space_after_dot = false
+csharp_space_after_keywords_in_control_flow_statements = true
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_around_declaration_statements = false
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_before_comma = false
+csharp_space_before_dot = false
+csharp_space_before_open_square_brackets = false
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_parentheses = false
+csharp_space_between_square_brackets = false
+
+# 包装首选项
+csharp_preserve_single_line_blocks = true
+csharp_preserve_single_line_statements = true
+
+#### 命名样式 ####
+
+# 命名规则
+
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+
+dotnet_naming_rule.types_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.types_should_be_pascal_case.symbols = types
+dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
+
+dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
+dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
+dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
+
+# 符号规范
+
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.interface.required_modifiers =
+
+dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
+dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.types.required_modifiers =
+
+dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
+dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
+dotnet_naming_symbols.non_field_members.required_modifiers =
+
+# 命名样式
+
+dotnet_naming_style.pascal_case.required_prefix =
+dotnet_naming_style.pascal_case.required_suffix =
+dotnet_naming_style.pascal_case.word_separator =
+dotnet_naming_style.pascal_case.capitalization = pascal_case
+
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.required_suffix =
+dotnet_naming_style.begins_with_i.word_separator =
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
diff --git a/.github/workflows/publish-image.yml b/.github/workflows/publish-image.yml
index b9716b380..a31f8c10f 100644
--- a/.github/workflows/publish-image.yml
+++ b/.github/workflows/publish-image.yml
@@ -12,7 +12,7 @@ on:
default: true
type: boolean
release:
- types: [published]
+ types: [created]
env:
DOCKERHUB_USERNAME : ${{ secrets.DOCKERHUB_USERNAME }}
diff --git a/.github/workflows/publish-release.yml b/.github/workflows/publish-release.yml
index a8fef3334..bcfae54d4 100644
--- a/.github/workflows/publish-release.yml
+++ b/.github/workflows/publish-release.yml
@@ -32,9 +32,9 @@ jobs:
- name: Extract Release Notes
id: release_notes
run: |
- content=$(grep -m1 "##" -A 1000 ./CHANGELOG.md)
+ content=$(sed -n '/^## /{p;:a;n;/^## /q;p;ba}' CHANGELOG.md)
version=$(echo "$GITHUB_REF" | sed 's/refs\/tags\///')
- echo "::set-output name=content::$content"
+ echo "::set-output name=content::$content"
echo "::set-output name=version::$version"
- name: Create Release
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c0722e0f7..fcb312047 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,9 @@
+## 2.1.0
+- Feature[#691]: 重构并优化基于qinglong的部署方式,尝试解决偶发的安装失败的问题
+- Feature[#670]: 新增针对App的AppUserAgent配置项,用于解决大会员大积分异常问题
+- Fix: 修复CICD发布脚本错误
## 2.0.5
-- Fix[#260]: 再次尝试修复大会员大积分“账号风险”异常
+- Fix[#260]: 再次尝试修复大会员大积分“账号风险”异常
## 2.0.4
- Fix: 尝试修复大会员大积分“账号风险”异常
- Feature:为agent api创建集成测试
diff --git a/common.props b/common.props
index 89ab5d059..6f3db6b1e 100644
--- a/common.props
+++ b/common.props
@@ -1,7 +1,7 @@
Ray
- 2.0.5
+ 2.1.0
$(NoWarn);CS1591;CS0436
diff --git a/docs/configuration.md b/docs/configuration.md
index 1c72fe6fe..795343a4b 100644
--- a/docs/configuration.md
+++ b/docs/configuration.md
@@ -8,8 +8,7 @@
- [1.1. 方式一:修改配置文件](#11-方式一修改配置文件)
- [1.2. 方式二:命令启动时通过命令行参数配置](#12-方式二命令启动时通过命令行参数配置)
- [1.3. 方式三:添加环境变量(推荐)](#13-方式三添加环境变量推荐)
- - [1.4. ~~方式四:托管在GitHub Actions上,使用GitHub Secrets配置~~](#14-方式四托管在github-actions上使用github-secrets配置)
- - [1.5. 方式五:托管在青龙面板上,使用面板的环境变量页或配置文件页进行配置](#15-方式五托管在青龙面板上使用面板的环境变量页或配置文件页进行配置)
+ - [1.4. 方式四:托管在青龙面板上,使用面板的环境变量页或配置文件页进行配置](#14-方式四托管在青龙面板上使用面板的环境变量页或配置文件页进行配置)
- [2. 优先级](#2-优先级)
- [3. 详细配置说明](#3-详细配置说明)
- [3.1. Cookie字符串](#31-cookie字符串)
@@ -19,7 +18,8 @@
- [3.2.3. 两次调用B站Api之间的间隔秒数](#323-两次调用b站api之间的间隔秒数)
- [3.2.4. 间隔秒数所针对的HttpMethod](#324-间隔秒数所针对的httpmethod)
- [3.2.5. 请求B站接口时头部传递的User-Agent](#325-请求b站接口时头部传递的user-agent)
- - [3.2.6. WebProxy(代理)](#326-webproxy代理)
+ - [3.2.6. App请求B站接口时头部传递的User-Agent](#326-app请求b站接口时头部传递的user-agent)
+ - [3.2.7. WebProxy(代理)](#327-webproxy代理)
- [3.3. 每日任务相关](#33-每日任务相关)
- [3.3.1. 是否开启观看视频任务](#331-是否开启观看视频任务)
- [3.3.2. 是否开启分享视频任务](#332-是否开启分享视频任务)
@@ -141,29 +141,8 @@ dotnet Ray.BiliBiliTool.Console.dll
注意区分单下划线和双下划线,linux系统使用 `export` 关键字代替 `set` 。
-
-### 1.4. ~~方式四:托管在GitHub Actions上,使用GitHub Secrets配置~~
-
-已废除,当前不支持使用`GitHub Action`直接运行应用,`GitHub Action`只用于部署
-
-
-
-~~使用GitHub Actions,可以通过添加Secret实现配置。~~
-
-~~比如,配置微信推送的SCKEY,可以添加如下Secret:~~
-
-~~Secret Name:`PUSHSCKEY`~~
-
-~~Secret Value:`123abc`~~
-
-~~这些 Secrets 会通过 workflow 里的yml脚本映射为环境变量,在应用启动时作为环境变量配置源传入程序当中,所以使用 GitHub Secrets 配置的本质是使用环境变量配置。~~
-
-![添加GitHub Secrets](imgs/git-secrets.png)
-
-
-
-
-### 1.5. 方式五:托管在青龙面板上,使用面板的环境变量页或配置文件页进行配置
+
+### 1.4. 方式四:托管在青龙面板上,使用面板的环境变量页或配置文件页进行配置
青龙面板配置,其本质还是通过环境变量进行配置,有如下两种方式。
@@ -238,7 +217,6 @@ export Ray_Serilog__WriteTo__9__Args__token="abcde"
| 值域 | [true,false] | |
| 默认值 | false | |
| 环境变量 | `Ray_Security__IsSkipDailyTask` | `set Ray_Security__IsSkipDailyTask=true` |
-| GitHub Secrets | `ISSKIPDAILYTASK` | Name:`ISSKIPDAILYTASK` Value: `true`|
#### 3.2.2. 随机睡眠的最大时长
@@ -254,7 +232,6 @@ export Ray_Serilog__WriteTo__9__Args__token="abcde"
| 值域 | 数字 |
| 默认值 | 20 |
| 环境变量 | `Ray_Security__RandomSleepMaxMin` |
-| GitHub Secrets | `RANDOMSLEEPMAXMIN`|
#### 3.2.3. 两次调用B站Api之间的间隔秒数
@@ -267,8 +244,6 @@ export Ray_Serilog__WriteTo__9__Args__token="abcde"
| 值域 | [0,+] |
| 默认值 | 20 |
| 环境变量 | `Ray_Security__IntervalSecondsBetweenRequestApi` |
-| GitHub Secrets | `INTERVALSECONDSBETWEENREQUESTAPI` |
-
#### 3.2.4. 间隔秒数所针对的HttpMethod
@@ -280,7 +255,6 @@ export Ray_Serilog__WriteTo__9__Args__token="abcde"
| 值域 | [GET,POST],多个以英文逗号分隔 |
| 默认值 | POST |
| 环境变量 | `Ray_Security__IntervalMethodTypes` |
-| GitHub Secrets | `INTERVALMETHODTYPES` |
#### 3.2.5. 请求B站接口时头部传递的User-Agent
@@ -291,15 +265,28 @@ export Ray_Serilog__WriteTo__9__Args__token="abcde"
| 值域 | 字符串,可以F12从自己的浏览器获取 |
| 默认值 | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Edg/87.0.664.41 |
| 环境变量 | `Ray_Security__UserAgent` |
-| GitHub Secrets | `USERAGENT`|
+
+获取浏览器中自己的UA的方法见下图:
+
+![获取User-Agent](imgs/get-user-agent.png)
+
+
+#### 3.2.6. App请求B站接口时头部传递的User-Agent
+
+| TITLE | CONTENT |
+| ---------- | -------------- |
+| 配置Key | `Security:UserAgentApp` |
+| 值域 | 字符串,可以F12从自己的浏览器获取 |
+| 默认值 | Mozilla/5.0 (Linux; Android 12; SM-S9080 Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 os/android model/SM-S9080 build/7760700 osVer/12 sdkInt/32 network/2 BiliApp/7760700 mobi_app/android channel/bili innerVer/7760710 c_locale/zh_CN s_locale/zh_CN disable_rcmd/0 7.76.0 os/android model/SM-S9080 mobi_app/android build/7760700 channel/bili innerVer/7760710 osVer/12 network/2 |
+| 环境变量 | `Ray_Security__UserAgentApp` |
获取浏览器中自己的UA的方法见下图:
![获取User-Agent](imgs/get-user-agent.png)
-
-#### 3.2.6. WebProxy(代理)
+
+#### 3.2.7. WebProxy(代理)
支持需要账户密码的代理。
diff --git a/docs/imgs/qinglong-run-as-bilitool.png b/docs/imgs/qinglong-run-as-bilitool.png
new file mode 100644
index 000000000..6b7508aec
Binary files /dev/null and b/docs/imgs/qinglong-run-as-bilitool.png differ
diff --git a/qinglong/DefaultTasks/bili_task_base.sh b/qinglong/DefaultTasks/bili_task_base.sh
index 0c71b0270..657c3a60c 100644
--- a/qinglong/DefaultTasks/bili_task_base.sh
+++ b/qinglong/DefaultTasks/bili_task_base.sh
@@ -2,44 +2,469 @@
# new Env("bili_base")
# cron 0 0 1 1 * bili_base.sh
-dir_shell=${QL_DIR-'/ql'}/shell
-. $dir_shell/share.sh
-. /root/.bashrc
+# Stop script on NZEC
+set -e
+# Stop script if unbound variable found (use ${var:-} if intentional)
+set -u
+# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success
+# This is causing it to fail
+set -o pipefail
-## 安装dotnet(如果未安装过)
-dotnetVersion=$(dotnet --version)
-if [[ $dotnetVersion == 6.* ]]; then
- echo "已安装dotnet,当前版本:$dotnetVersion"
-else
- echo "which dotnet: $(which dotnet)"
- echo "开始安装dotnet"
- rayInstallShell="https://ghproxy.com/https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/qinglong/ray-dotnet-install.sh"
- {
- echo "------尝试使用apk安装------"
- apk add dotnet6-sdk
- dotnet --version && echo "安装成功"
- } || {
- echo "------再尝试使用官方脚本安装------"
- curl -sSL $rayInstallShell | bash /dev/stdin
- . /root/.bashrc
- dotnet --version && echo "安装成功"
- } || {
- echo "------再尝试使用二进制包安装------"
- curl -sSL $rayInstallShell | bash /dev/stdin --no-official
- . /root/.bashrc
- dotnet --version && echo "安装成功"
- } || {
- echo "安装失败,没办法了,毁灭吧,自己解决吧:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-alpine"
- exit 1
- }
+verbose=false # 开启debug日志
+bili_repo="raywangqvq/bilibilitoolpro" # 仓库地址
+bili_branch="" # 分支名,空或_develop
+prefer_mode=${BILI_MODE:-"dotnet"} # dotnet或bilitool,需要通过环境变量配置
+github_proxy=${BILI_GITHUB_PROXY:-""} # 下载github release包时使用的代理,会拼在地址前面,需要通过环境变量配置
+
+# Use in the the functions: eval $invocation
+invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"'
+
+# standard output may be used as a return value in the functions
+# we need a way to write text on the screen in the functions so that
+# it won't interfere with the return value.
+# Exposing stream 3 as a pipe to standard output of the script itself
+exec 3>&1
+
+# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors.
+# See if stdout is a terminal
+if [ -t 1 ] && command -v tput >/dev/null; then
+ # see if it supports colors
+ ncolors=$(tput colors || echo 0)
+ if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
+ bold="$(tput bold || echo)"
+ normal="$(tput sgr0 || echo)"
+ black="$(tput setaf 0 || echo)"
+ red="$(tput setaf 1 || echo)"
+ green="$(tput setaf 2 || echo)"
+ yellow="$(tput setaf 3 || echo)"
+ blue="$(tput setaf 4 || echo)"
+ magenta="$(tput setaf 5 || echo)"
+ cyan="$(tput setaf 6 || echo)"
+ white="$(tput setaf 7 || echo)"
+ fi
fi
-bili_repo="raywangqvq_bilibilitoolpro"
+say_warning() {
+ printf "%b\n" "${yellow:-}bilitool: Warning: $1${normal:-}" >&3
+}
+
+say_err() {
+ printf "%b\n" "${red:-}bilitool: Error: $1${normal:-}" >&2
+}
+
+say() {
+ # using stream 3 (defined in the beginning) to not interfere with stdout of functions
+ # which may be used as return value
+ printf "%b\n" "${cyan:-}bilitool:${normal:-} $1" >&3
+}
+
+say_verbose() {
+ if [ "$verbose" = true ]; then
+ say "$1"
+ fi
+}
+
+QL_DIR=${QL_DIR:-"/ql"}
+QL_BRANCH=${QL_BRANCH:-"develop"}
+DefaultCronRule=${DefaultCronRule:-""}
+CpuWarn=${CpuWarn:-""}
+MemoryWarn=${MemoryWarn:-""}
+DiskWarn=${DiskWarn:-""}
+
+dir_repo=${dir_repo:-"$QL_DIR/data/repo"}
+dir_shell=$QL_DIR/shell
+. $dir_shell/env.sh
+touch /root/.bashrc && . /root/.bashrc
+
+# 目录
+say "青龙repo目录: $dir_repo"
+qinglong_bili_repo="$(echo "$bili_repo" | sed 's/\//_/g')${bili_branch}"
+qinglong_bili_repo_dir="$(find $dir_repo -type d -iname $qinglong_bili_repo | head -1)"
+say "bili仓库目录: $qinglong_bili_repo_dir"
+
+current_linux_os="debian" # 或alpine
+current_os="linux" # 或linux-musl
+machine_architecture="x64" # 或arm、arm64
+
+bilitool_installed_version=0
+
+# 以下操作仅在bilitool仓库的根bin文件下执行
+cd $qinglong_bili_repo_dir
+mkdir -p bin && cd $qinglong_bili_repo_dir/bin
+
+# 判断是否存在某指令
+machine_has() {
+ eval $invocation
+
+ command -v "$1" >/dev/null 2>&1
+ return $?
+}
+
+# 判断系统架构
+# 输出:arm、arm64、x64
+get_machine_architecture() {
+ eval $invocation
+
+ if command -v uname >/dev/null; then
+ CPUName=$(uname -m)
+ case $CPUName in
+ armv*l)
+ echo "arm"
+ return 0
+ ;;
+ aarch64 | arm64)
+ echo "arm64"
+ return 0
+ ;;
+ esac
+ fi
+
+ # Always default to 'x64'
+ echo "x64"
+ return 0
+}
+
+# 获取linux系统名称
+# 输出:debian.10、debian.11、debian.12、ubuntu.20.04、ubuntu.22.04、alpine.3.4.3...
+get_linux_platform_name() {
+ eval $invocation
+
+ if [ -e /etc/os-release ]; then
+ . /etc/os-release
+ echo "$ID${VERSION_ID:+.${VERSION_ID}}"
+ return 0
+ elif [ -e /etc/redhat-release ]; then
+ local redhatRelease=$(&1 || true) | grep -q musl
+}
+
+# 获取当前系统名称
+# 输出:linux、linux-musl、osx、freebsd
+get_current_os_name() {
+ eval $invocation
+
+ local uname=$(uname)
+ if [ "$uname" = "Darwin" ]; then
+ say_warning "当前系统:osx"
+ echo "osx"
+ return 1
+ elif [ "$uname" = "FreeBSD" ]; then
+ say_warning "当前系统:freebsd"
+ echo "freebsd"
+ return 1
+ elif [ "$uname" = "Linux" ]; then
+ local linux_platform_name=""
+ linux_platform_name="$(get_linux_platform_name)" || true
+ say "当前系统发行版本:$linux_platform_name"
+
+ if [ "$linux_platform_name" = "rhel.6" ]; then
+ echo $linux_platform_name
+ return 1
+ elif is_musl_based_distro; then
+ echo "linux-musl"
+ return 0
+ elif [ "$linux_platform_name" = "linux-musl" ]; then
+ echo "linux-musl"
+ return 0
+ else
+ echo "linux"
+ return 0
+ fi
+ fi
+
+ say_err "OS name could not be detected: UName = $uname"
+ return 1
+}
+
+# 检查操作系统
+check_os() {
+ eval $invocation
+
+ current_os="$(get_current_os_name)"
+ say "当前系统:$current_os"
+
+ machine_architecture="$(get_machine_architecture)"
+ say "当前架构:$machine_architecture"
+
+ if [ "$current_os" = "linux" ]; then
+ current_linux_os="debian" # 当前青龙只有debian和aplpine两种
+ if ! machine_has curl; then
+ say "curl未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y curl
+ fi
+ else
+ current_linux_os="alpine"
+ if ! machine_has curl; then
+ say "curl未安装,开始安装依赖..."
+ apk update
+ apk add -y curl
+ fi
+ fi
+
+ say "当前选择的运行方式:$prefer_mode"
+}
+
+# 检查安装jq
+check_jq() {
+ if [ "$current_linux_os" = "debian" ]; then
+ if ! machine_has jq; then
+ say "jq未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y jq
+ fi
+ else
+ if ! machine_has jq; then
+ say "jq未安装,开始安装依赖..."
+ apk update
+ apk add -y jq
+ fi
+ fi
+}
+
+# 检查安装unzip
+check_unzip() {
+ if [ "$current_linux_os" = "debian" ]; then
+ if ! machine_has unzip; then
+ say "unzip未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y unzip
+ fi
+ else
+ if ! machine_has unzip; then
+ say "jq未安装,开始安装依赖..."
+ apk update
+ apk add -y unzip
+ fi
+ fi
+}
+
+# 检查dotnet
+check_dotnet() {
+ eval $invocation
+
+ dotnetVersion=$(dotnet --version)
+ if [[ $dotnetVersion == 6.* ]]; then
+ say "已安装dotnet,当前版本:$dotnetVersion"
+ say "which dotnet: $(which dotnet)"
+ return 0
+ else
+ say "未安装"
+ return 1
+ fi
+}
+
+# 检查bilitool
+check_bilitool() {
+ eval $invocation
+
+ TAG_FILE="./tag.txt"
+ touch $TAG_FILE
+ local STORED_TAG=$(cat $TAG_FILE 2>/dev/null)
+
+ #如果STORED_TAG为空,则返回1
+ if [[ -z $STORED_TAG ]]; then
+ say "tag.txt为空,未安装过"
+ return 1
+ fi
+
+ say "tag.txt记录的版本:$STORED_TAG"
+
+ # 查找当前目录下是否有叫Ray.BiliBiliTool.Console的文件
+ if [ -f "./Ray.BiliBiliTool.Console" ]; then
+ say "bilitool已安装"
+ bilitool_installed_version=$STORED_TAG
+ return 0
+ else
+ say "bilitool未安装"
+ return 1
+ fi
+}
+
+# 检查环境
+check_installed() {
+ eval $invocation
+
+ if [ "$prefer_mode" == "dotnet" ]; then
+ check_dotnet
+ return $?
+ fi
+
+ if [ "$prefer_mode" == "bilitool" ]; then
+ check_bilitool
+ return $?
+ fi
+
+ return 1
+}
+
+# 使用官方脚本安装dotnet
+install_dotnet_by_script() {
+ eval $invocation
+
+ say "再尝试使用官方脚本安装"
+ curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 6.0 --no-cdn --verbose
+
+ say "添加到PATH"
+ local exportFile="/root/.bashrc"
+ touch $exportFile
+ echo '' >>$exportFile
+ echo 'export DOTNET_ROOT=$HOME/.dotnet' >>$exportFile
+ echo 'export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools' >>$exportFile
+ . $exportFile
+}
+
+# 安装dotnet环境
+install_dotnet() {
+ eval $invocation
+
+ say "开始安装dotnet"
+ say "当前系统:$current_linux_os"
+ if [[ $current_linux_os == "debian" ]]; then
+ say "使用apt安装"
+
+ if ! (curl -s -m 5 www.google.com >/dev/nul); then
+ say "机器位于墙内,切换为包源为国内镜像源"
+ cp /etc/apt/sources.list /etc/apt/sources.list.bak
+ sed -i 's/https:\/\/deb.debian.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
+ sed -i 's/http:\/\/deb.debian.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
+ apt-get update
+ fi
+ {
+ . /etc/os-release
+ curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/debian/$VERSION_ID/packages-microsoft-prod.deb
+ dpkg -i packages-microsoft-prod.deb
+ rm packages-microsoft-prod.deb
+ apt-get update && apt-get install -y dotnet-sdk-6.0
+ } || {
+ install_dotnet_by_script
+ }
+ else
+ say "使用apk安装"
+ if ! (curl -s -m 5 www.google.com >/dev/nul); then
+ say "机器位于墙内,切换为包源为国内镜像源"
+ cp /etc/apk/repositories /etc/apk/repositories.bak
+ sed -i 's/https:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apk/repositories
+ sed -i 's/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apk/repositories
+ apk update
+ fi
+ {
+ apk add dotnet6-sdk
+ } || {
+ install_dotnet_by_script
+ }
+ fi
+ dotnet --version && say "which dotnet: $(which dotnet)" && say "安装成功"
+ return $?
+}
+
+# 从github获取bilitool下载地址
+get_download_url() {
+ eval $invocation
+
+ tag=$1
+ url="${github_proxy}https://github.com/RayWangQvQ/BiliBiliToolPro/releases/download/$tag/bilibili-tool-pro-v$tag-$current_os-$machine_architecture.zip"
+ say "下载地址:$url"
+ echo $url
+ return 0
+}
+
+# 安装bilitool
+install_bilitool() {
+ eval $invocation
+
+ say "开始安装bilitool"
+ # 获取最新的release信息
+ LATEST_RELEASE=$(curl -s https://api.github.com/repos/$bili_repo/releases/latest)
+
+ # 解析最新的tag名称
+ check_jq
+ LATEST_TAG=$(echo $LATEST_RELEASE | jq -r '.tag_name')
+ say "最新版本:$LATEST_TAG"
+
+ # 读取之前存储的tag并比较
+ if [ "$LATEST_TAG" != "$bilitool_installed_version" ]; then
+ # 如果不一样,则需要更新安装
+ ASSET_URL=$(get_download_url $LATEST_TAG)
+
+ # 使用curl下载文件到当前目录下的test.zip文件
+ local zip_file_name="bilitool-$LATEST_TAG.zip"
+ curl -L -o "$zip_file_name" $ASSET_URL
+
+ # 解压
+ check_unzip
+ unzip -jo "$zip_file_name" -d ./ &&
+ rm "$zip_file_name" &&
+ rm -f appsettings.*
+
+ # 更新tag.txt文件
+ echo $LATEST_TAG >./tag.txt
+ else
+ say "已经是最新版本,无需下载。"
+ fi
+}
+
+## 安装dotnet(如果未安装过)
+install() {
+ eval $invocation
+
+ if check_installed; then
+ say "环境正常,本次无需安装"
+ return 0
+ else
+ say "开始安装环境"
+ if [ "$prefer_mode" == "dotnet" ]; then
+ install_dotnet || {
+ say_err "安装失败"
+ say_err "请根据文档自行在青龙容器中安装dotnet:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-$current_linux_os"
+ say_err "或者尝试切换运行模式为bilitool,它不需要安装dotnet:https://github.com/RayWangQvQ/BiliBiliToolPro/blob/develop/qinglong/README.md"
+ exit 1
+ }
+ fi
+
+ if [ "$prefer_mode" == "bilitool" ]; then
+ install_bilitool || {
+ say_err "安装失败,请检查日志并重试"
+ say_err "或者尝试切换运行模式为dotnet:https://github.com/RayWangQvQ/BiliBiliToolPro/blob/develop/qinglong/README.md"
+ exit 1
+ }
+ fi
+ return $?
+ fi
+}
+
+# 运行bilitool任务
+run_task() {
+ eval $invocation
+
+ local target_code=$1
+
+ export Ray_PlateformType=QingLong
+ export Ray_RunTasks=$target_code
+
+ cd $qinglong_bili_repo_dir/src/Ray.BiliBiliTool.Console
-echo -e "\nrepo目录: $dir_repo"
-bili_repo_dir="$(find $dir_repo -type d -iname $bili_repo | head -1)"
-echo -e "bili仓库目录: $bili_repo_dir\n"
+ if [ "$prefer_mode" == "dotnet" ]; then
+ dotnet run --ENVIRONMENT=Production
+ else
+ cp -f $qinglong_bili_repo_dir/bin/Ray.BiliBiliTool.Console .
+ chmod +x ./Ray.BiliBiliTool.Console && ./Ray.BiliBiliTool.Console --ENVIRONMENT=Production
+ fi
+}
-cd $bili_repo_dir
-export Ray_PlateformType=QingLong
-export DOTNET_ENVIRONMENT=Production
+check_os
+install
diff --git a/qinglong/DefaultTasks/bili_task_daily.sh b/qinglong/DefaultTasks/bili_task_daily.sh
index 9eacc6f69..fa7bd64f1 100644
--- a/qinglong/DefaultTasks/bili_task_daily.sh
+++ b/qinglong/DefaultTasks/bili_task_daily.sh
@@ -3,7 +3,5 @@
# cron 0 9 * * * bili_task_daily.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Daily && \
-dotnet run
+target_task_code="Daily"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_liveFansMedal.sh b/qinglong/DefaultTasks/bili_task_liveFansMedal.sh
index d0c46ae62..b0ea1668c 100644
--- a/qinglong/DefaultTasks/bili_task_liveFansMedal.sh
+++ b/qinglong/DefaultTasks/bili_task_liveFansMedal.sh
@@ -3,7 +3,5 @@
# cron 5 0 * * * bili_task_liveFansMedal.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=LiveFansMedal && \
-dotnet run
+target_task_code="LiveFansMedal"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_liveLottery.sh b/qinglong/DefaultTasks/bili_task_liveLottery.sh
index 4eda72904..9da3917bc 100644
--- a/qinglong/DefaultTasks/bili_task_liveLottery.sh
+++ b/qinglong/DefaultTasks/bili_task_liveLottery.sh
@@ -3,7 +3,5 @@
# cron 0 13 * * * bili_task_liveLottery.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=LiveLottery && \
-dotnet run
+target_task_code="LiveLottery"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_login.sh b/qinglong/DefaultTasks/bili_task_login.sh
index b385ddf7d..70c5f65e0 100644
--- a/qinglong/DefaultTasks/bili_task_login.sh
+++ b/qinglong/DefaultTasks/bili_task_login.sh
@@ -3,7 +3,5 @@
# cron 0 0 1 1 * bili_task_login.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Login && \
-dotnet run
+target_task_code="Login"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_test.sh b/qinglong/DefaultTasks/bili_task_test.sh
index 8ade4702d..2bbea0194 100644
--- a/qinglong/DefaultTasks/bili_task_test.sh
+++ b/qinglong/DefaultTasks/bili_task_test.sh
@@ -3,7 +3,5 @@
# cron 0 8 * * * bili_task_test.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Test && \
-dotnet run
+target_task_code="Test"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_unfollowBatched.sh b/qinglong/DefaultTasks/bili_task_unfollowBatched.sh
index 0541347e1..1ccc493ed 100644
--- a/qinglong/DefaultTasks/bili_task_unfollowBatched.sh
+++ b/qinglong/DefaultTasks/bili_task_unfollowBatched.sh
@@ -3,7 +3,5 @@
# cron 0 12 1 * * bili_task_unfollowBatched.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=UnfollowBatched && \
-dotnet run
+target_task_code="UnfollowBatched"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/bili_task_vipBigPoint.sh b/qinglong/DefaultTasks/bili_task_vipBigPoint.sh
index b7bb4782f..0470bbc03 100644
--- a/qinglong/DefaultTasks/bili_task_vipBigPoint.sh
+++ b/qinglong/DefaultTasks/bili_task_vipBigPoint.sh
@@ -3,7 +3,5 @@
# cron 7 1 * * * bili_task_vipBigPoint.sh
. bili_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=VipBigPoint && \
-dotnet run
+target_task_code="VipBigPoint"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_base.sh b/qinglong/DefaultTasks/dev/bili_dev_task_base.sh
index 5b389e88f..80c9a4642 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_base.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_base.sh
@@ -2,44 +2,469 @@
# new Env("bili_dev_task_base")
# cron 0 0 1 1 * bili_dev_task_base.sh
-dir_shell=${QL_DIR-'/ql'}/shell
-. $dir_shell/share.sh
-. /root/.bashrc
+# Stop script on NZEC
+set -e
+# Stop script if unbound variable found (use ${var:-} if intentional)
+set -u
+# By default cmd1 | cmd2 returns exit code of cmd2 regardless of cmd1 success
+# This is causing it to fail
+set -o pipefail
-## 安装dotnet(如果未安装过)
-dotnetVersion=$(dotnet --version)
-if [[ $dotnetVersion == 6.* ]]; then
- echo "已安装dotnet,当前版本:$dotnetVersion"
-else
- echo "which dotnet: $(which dotnet)"
- echo "开始安装dotnet"
- rayInstallShell="https://ghproxy.com/https://raw.githubusercontent.com/RayWangQvQ/BiliBiliToolPro/main/qinglong/ray-dotnet-install.sh"
- {
- echo "------尝试使用apk安装------"
- apk add dotnet6-sdk
- dotnet --version && echo "安装成功"
- } || {
- echo "------再尝试使用官方脚本安装------"
- curl -sSL $rayInstallShell | bash /dev/stdin
- . /root/.bashrc
- dotnet --version && echo "安装成功"
- } || {
- echo "------再尝试使用二进制包安装------"
- curl -sSL $rayInstallShell | bash /dev/stdin --no-official
- . /root/.bashrc
- dotnet --version && echo "安装成功"
- } || {
- echo "安装失败,没办法了,毁灭吧,自己解决吧:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-alpine"
- exit 1
- }
+verbose=false # 开启debug日志
+bili_repo="raywangqvq/bilibilitoolpro" # 仓库地址
+bili_branch="_develop" # 分支名,空或_develop
+prefer_mode=${BILI_MODE:-"dotnet"} # dotnet或bilitool,需要通过环境变量配置
+github_proxy=${BILI_GITHUB_PROXY:-""} # 下载github release包时使用的代理,会拼在地址前面,需要通过环境变量配置
+
+# Use in the the functions: eval $invocation
+invocation='say_verbose "Calling: ${yellow:-}${FUNCNAME[0]} ${green:-}$*${normal:-}"'
+
+# standard output may be used as a return value in the functions
+# we need a way to write text on the screen in the functions so that
+# it won't interfere with the return value.
+# Exposing stream 3 as a pipe to standard output of the script itself
+exec 3>&1
+
+# Setup some colors to use. These need to work in fairly limited shells, like the Ubuntu Docker container where there are only 8 colors.
+# See if stdout is a terminal
+if [ -t 1 ] && command -v tput >/dev/null; then
+ # see if it supports colors
+ ncolors=$(tput colors || echo 0)
+ if [ -n "$ncolors" ] && [ $ncolors -ge 8 ]; then
+ bold="$(tput bold || echo)"
+ normal="$(tput sgr0 || echo)"
+ black="$(tput setaf 0 || echo)"
+ red="$(tput setaf 1 || echo)"
+ green="$(tput setaf 2 || echo)"
+ yellow="$(tput setaf 3 || echo)"
+ blue="$(tput setaf 4 || echo)"
+ magenta="$(tput setaf 5 || echo)"
+ cyan="$(tput setaf 6 || echo)"
+ white="$(tput setaf 7 || echo)"
+ fi
fi
-bili_repo="raywangqvq_bilibilitoolpro_develop"
+say_warning() {
+ printf "%b\n" "${yellow:-}bilitool: Warning: $1${normal:-}" >&3
+}
+
+say_err() {
+ printf "%b\n" "${red:-}bilitool: Error: $1${normal:-}" >&2
+}
+
+say() {
+ # using stream 3 (defined in the beginning) to not interfere with stdout of functions
+ # which may be used as return value
+ printf "%b\n" "${cyan:-}bilitool:${normal:-} $1" >&3
+}
+
+say_verbose() {
+ if [ "$verbose" = true ]; then
+ say "$1"
+ fi
+}
+
+QL_DIR=${QL_DIR:-"/ql"}
+QL_BRANCH=${QL_BRANCH:-"develop"}
+DefaultCronRule=${DefaultCronRule:-""}
+CpuWarn=${CpuWarn:-""}
+MemoryWarn=${MemoryWarn:-""}
+DiskWarn=${DiskWarn:-""}
+
+dir_repo=${dir_repo:-"$QL_DIR/data/repo"}
+dir_shell=$QL_DIR/shell
+. $dir_shell/env.sh
+touch /root/.bashrc && . /root/.bashrc
+
+# 目录
+say "青龙repo目录: $dir_repo"
+qinglong_bili_repo="$(echo "$bili_repo" | sed 's/\//_/g')${bili_branch}"
+qinglong_bili_repo_dir="$(find $dir_repo -type d -iname $qinglong_bili_repo | head -1)"
+say "bili仓库目录: $qinglong_bili_repo_dir"
+
+current_linux_os="debian" # 或alpine
+current_os="linux" # 或linux-musl
+machine_architecture="x64" # 或arm、arm64
+
+bilitool_installed_version=0
+
+# 以下操作仅在bilitool仓库的根bin文件下执行
+cd $qinglong_bili_repo_dir
+mkdir -p bin && cd $qinglong_bili_repo_dir/bin
+
+# 判断是否存在某指令
+machine_has() {
+ eval $invocation
+
+ command -v "$1" >/dev/null 2>&1
+ return $?
+}
+
+# 判断系统架构
+# 输出:arm、arm64、x64
+get_machine_architecture() {
+ eval $invocation
+
+ if command -v uname >/dev/null; then
+ CPUName=$(uname -m)
+ case $CPUName in
+ armv*l)
+ echo "arm"
+ return 0
+ ;;
+ aarch64 | arm64)
+ echo "arm64"
+ return 0
+ ;;
+ esac
+ fi
+
+ # Always default to 'x64'
+ echo "x64"
+ return 0
+}
+
+# 获取linux系统名称
+# 输出:debian.10、debian.11、debian.12、ubuntu.20.04、ubuntu.22.04、alpine.3.4.3...
+get_linux_platform_name() {
+ eval $invocation
+
+ if [ -e /etc/os-release ]; then
+ . /etc/os-release
+ echo "$ID${VERSION_ID:+.${VERSION_ID}}"
+ return 0
+ elif [ -e /etc/redhat-release ]; then
+ local redhatRelease=$(&1 || true) | grep -q musl
+}
+
+# 获取当前系统名称
+# 输出:linux、linux-musl、osx、freebsd
+get_current_os_name() {
+ eval $invocation
+
+ local uname=$(uname)
+ if [ "$uname" = "Darwin" ]; then
+ say_warning "当前系统:osx"
+ echo "osx"
+ return 1
+ elif [ "$uname" = "FreeBSD" ]; then
+ say_warning "当前系统:freebsd"
+ echo "freebsd"
+ return 1
+ elif [ "$uname" = "Linux" ]; then
+ local linux_platform_name=""
+ linux_platform_name="$(get_linux_platform_name)" || true
+ say "当前系统发行版本:$linux_platform_name"
+
+ if [ "$linux_platform_name" = "rhel.6" ]; then
+ echo $linux_platform_name
+ return 1
+ elif is_musl_based_distro; then
+ echo "linux-musl"
+ return 0
+ elif [ "$linux_platform_name" = "linux-musl" ]; then
+ echo "linux-musl"
+ return 0
+ else
+ echo "linux"
+ return 0
+ fi
+ fi
+
+ say_err "OS name could not be detected: UName = $uname"
+ return 1
+}
+
+# 检查操作系统
+check_os() {
+ eval $invocation
+
+ current_os="$(get_current_os_name)"
+ say "当前系统:$current_os"
+
+ machine_architecture="$(get_machine_architecture)"
+ say "当前架构:$machine_architecture"
+
+ if [ "$current_os" = "linux" ]; then
+ current_linux_os="debian" # 当前青龙只有debian和aplpine两种
+ if ! machine_has curl; then
+ say "curl未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y curl
+ fi
+ else
+ current_linux_os="alpine"
+ if ! machine_has curl; then
+ say "curl未安装,开始安装依赖..."
+ apk update
+ apk add -y curl
+ fi
+ fi
+
+ say "当前选择的运行方式:$prefer_mode"
+}
+
+# 检查安装jq
+check_jq() {
+ if [ "$current_linux_os" = "debian" ]; then
+ if ! machine_has jq; then
+ say "jq未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y jq
+ fi
+ else
+ if ! machine_has jq; then
+ say "jq未安装,开始安装依赖..."
+ apk update
+ apk add -y jq
+ fi
+ fi
+}
+
+# 检查安装unzip
+check_unzip() {
+ if [ "$current_linux_os" = "debian" ]; then
+ if ! machine_has unzip; then
+ say "unzip未安装,开始安装依赖..."
+ apt-get update
+ apt-get install -y unzip
+ fi
+ else
+ if ! machine_has unzip; then
+ say "jq未安装,开始安装依赖..."
+ apk update
+ apk add -y unzip
+ fi
+ fi
+}
+
+# 检查dotnet
+check_dotnet() {
+ eval $invocation
+
+ dotnetVersion=$(dotnet --version)
+ if [[ $dotnetVersion == 6.* ]]; then
+ say "已安装dotnet,当前版本:$dotnetVersion"
+ say "which dotnet: $(which dotnet)"
+ return 0
+ else
+ say "未安装"
+ return 1
+ fi
+}
+
+# 检查bilitool
+check_bilitool() {
+ eval $invocation
+
+ TAG_FILE="./tag.txt"
+ touch $TAG_FILE
+ local STORED_TAG=$(cat $TAG_FILE 2>/dev/null)
+
+ #如果STORED_TAG为空,则返回1
+ if [[ -z $STORED_TAG ]]; then
+ say "tag.txt为空,未安装过"
+ return 1
+ fi
+
+ say "tag.txt记录的版本:$STORED_TAG"
+
+ # 查找当前目录下是否有叫Ray.BiliBiliTool.Console的文件
+ if [ -f "./Ray.BiliBiliTool.Console" ]; then
+ say "bilitool已安装"
+ bilitool_installed_version=$STORED_TAG
+ return 0
+ else
+ say "bilitool未安装"
+ return 1
+ fi
+}
+
+# 检查环境
+check_installed() {
+ eval $invocation
+
+ if [ "$prefer_mode" == "dotnet" ]; then
+ check_dotnet
+ return $?
+ fi
+
+ if [ "$prefer_mode" == "bilitool" ]; then
+ check_bilitool
+ return $?
+ fi
+
+ return 1
+}
+
+# 使用官方脚本安装dotnet
+install_dotnet_by_script() {
+ eval $invocation
+
+ say "再尝试使用官方脚本安装"
+ curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 6.0 --no-cdn --verbose
+
+ say "添加到PATH"
+ local exportFile="/root/.bashrc"
+ touch $exportFile
+ echo '' >>$exportFile
+ echo 'export DOTNET_ROOT=$HOME/.dotnet' >>$exportFile
+ echo 'export PATH=$PATH:$DOTNET_ROOT:$DOTNET_ROOT/tools' >>$exportFile
+ . $exportFile
+}
+
+# 安装dotnet环境
+install_dotnet() {
+ eval $invocation
+
+ say "开始安装dotnet"
+ say "当前系统:$current_linux_os"
+ if [[ $current_linux_os == "debian" ]]; then
+ say "使用apt安装"
+
+ if ! (curl -s -m 5 www.google.com >/dev/nul); then
+ say "机器位于墙内,切换为包源为国内镜像源"
+ cp /etc/apt/sources.list /etc/apt/sources.list.bak
+ sed -i 's/https:\/\/deb.debian.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
+ sed -i 's/http:\/\/deb.debian.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apt/sources.list
+ apt-get update
+ fi
+ {
+ . /etc/os-release
+ curl -o packages-microsoft-prod.deb https://packages.microsoft.com/config/debian/$VERSION_ID/packages-microsoft-prod.deb
+ dpkg -i packages-microsoft-prod.deb
+ rm packages-microsoft-prod.deb
+ apt-get update && apt-get install -y dotnet-sdk-6.0
+ } || {
+ install_dotnet_by_script
+ }
+ else
+ say "使用apk安装"
+ if ! (curl -s -m 5 www.google.com >/dev/nul); then
+ say "机器位于墙内,切换为包源为国内镜像源"
+ cp /etc/apk/repositories /etc/apk/repositories.bak
+ sed -i 's/https:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apk/repositories
+ sed -i 's/http:\/\/dl-cdn.alpinelinux.org/https:\/\/mirrors.ustc.edu.cn/g' /etc/apk/repositories
+ apk update
+ fi
+ {
+ apk add dotnet6-sdk
+ } || {
+ install_dotnet_by_script
+ }
+ fi
+ dotnet --version && say "which dotnet: $(which dotnet)" && say "安装成功"
+ return $?
+}
+
+# 从github获取bilitool下载地址
+get_download_url() {
+ eval $invocation
+
+ tag=$1
+ url="${github_proxy}https://github.com/RayWangQvQ/BiliBiliToolPro/releases/download/$tag/bilibili-tool-pro-v$tag-$current_os-$machine_architecture.zip"
+ say "下载地址:$url"
+ echo $url
+ return 0
+}
+
+# 安装bilitool
+install_bilitool() {
+ eval $invocation
+
+ say "开始安装bilitool"
+ # 获取最新的release信息
+ LATEST_RELEASE=$(curl -s https://api.github.com/repos/$bili_repo/releases/latest)
+
+ # 解析最新的tag名称
+ check_jq
+ LATEST_TAG=$(echo $LATEST_RELEASE | jq -r '.tag_name')
+ say "最新版本:$LATEST_TAG"
+
+ # 读取之前存储的tag并比较
+ if [ "$LATEST_TAG" != "$bilitool_installed_version" ]; then
+ # 如果不一样,则需要更新安装
+ ASSET_URL=$(get_download_url $LATEST_TAG)
+
+ # 使用curl下载文件到当前目录下的test.zip文件
+ local zip_file_name="bilitool-$LATEST_TAG.zip"
+ curl -L -o "$zip_file_name" $ASSET_URL
+
+ # 解压
+ check_unzip
+ unzip -jo "$zip_file_name" -d ./ &&
+ rm "$zip_file_name" &&
+ rm -f appsettings.*
+
+ # 更新tag.txt文件
+ echo $LATEST_TAG >./tag.txt
+ else
+ say "已经是最新版本,无需下载。"
+ fi
+}
+
+## 安装dotnet(如果未安装过)
+install() {
+ eval $invocation
+
+ if check_installed; then
+ say "环境正常,本次无需安装"
+ return 0
+ else
+ say "开始安装环境"
+ if [ "$prefer_mode" == "dotnet" ]; then
+ install_dotnet || {
+ say_err "安装失败"
+ say_err "请根据文档自行在青龙容器中安装dotnet:https://learn.microsoft.com/zh-cn/dotnet/core/install/linux-$current_linux_os"
+ say_err "或者尝试切换运行模式为bilitool,它不需要安装dotnet:https://github.com/RayWangQvQ/BiliBiliToolPro/blob/develop/qinglong/README.md"
+ exit 1
+ }
+ fi
+
+ if [ "$prefer_mode" == "bilitool" ]; then
+ install_bilitool || {
+ say_err "安装失败,请检查日志并重试"
+ say_err "或者尝试切换运行模式为dotnet:https://github.com/RayWangQvQ/BiliBiliToolPro/blob/develop/qinglong/README.md"
+ exit 1
+ }
+ fi
+ return $?
+ fi
+}
+
+# 运行bilitool任务
+run_task() {
+ eval $invocation
+
+ local target_code=$1
+
+ export Ray_PlateformType=QingLong
+ export Ray_RunTasks=$target_code
+
+ cd $qinglong_bili_repo_dir/src/Ray.BiliBiliTool.Console
-echo -e "\nrepo目录: $dir_repo"
-bili_repo_dir="$(find $dir_repo -type d -iname $bili_repo | head -1)"
-echo -e "bili仓库目录: $bili_repo_dir\n"
+ if [ "$prefer_mode" == "dotnet" ]; then
+ dotnet run --ENVIRONMENT=Production
+ else
+ cp -f $qinglong_bili_repo_dir/bin/Ray.BiliBiliTool.Console .
+ chmod +x ./Ray.BiliBiliTool.Console && ./Ray.BiliBiliTool.Console --ENVIRONMENT=Production
+ fi
+}
-cd $bili_repo_dir
-export Ray_PlateformType=QingLong
-export DOTNET_ENVIRONMENT=Production
\ No newline at end of file
+check_os
+install
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_daily.sh b/qinglong/DefaultTasks/dev/bili_dev_task_daily.sh
index 6b30dd4e5..110b9f9fa 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_daily.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_daily.sh
@@ -3,7 +3,5 @@
# cron 0 9 * * * bili_dev_task_daily.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Daily && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="Daily"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_liveFansMedal.sh b/qinglong/DefaultTasks/dev/bili_dev_task_liveFansMedal.sh
index 54d9d76e6..f569d01e3 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_liveFansMedal.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_liveFansMedal.sh
@@ -3,7 +3,5 @@
# cron 5 0 * * * bili_dev_task_liveFansMedal.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=LiveFansMedal && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="LiveFansMedal"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_liveLottery.sh b/qinglong/DefaultTasks/dev/bili_dev_task_liveLottery.sh
index eb2c20124..9287a8529 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_liveLottery.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_liveLottery.sh
@@ -3,7 +3,5 @@
# cron 0 13 * * * bili_dev_task_liveLottery.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=LiveLottery && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="LiveLottery"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_login.sh b/qinglong/DefaultTasks/dev/bili_dev_task_login.sh
index 933e05cfa..88a901e5b 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_login.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_login.sh
@@ -3,7 +3,5 @@
# cron 0 0 1 1 * bili_dev_task_login.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Login && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="Login"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_test.sh b/qinglong/DefaultTasks/dev/bili_dev_task_test.sh
index 19c6f798e..29237d5d9 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_test.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_test.sh
@@ -3,7 +3,5 @@
# cron 0 8 * * * bili_dev_task_test.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=Test && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="Test"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_unfollowBatched.sh b/qinglong/DefaultTasks/dev/bili_dev_task_unfollowBatched.sh
index 0f8311dba..0413c54e2 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_unfollowBatched.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_unfollowBatched.sh
@@ -3,7 +3,5 @@
# cron 0 12 1 * * bili_dev_task_unfollowBatched.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=UnfollowBatched && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="UnfollowBatched"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/DefaultTasks/dev/bili_dev_task_vipBigPoint.sh b/qinglong/DefaultTasks/dev/bili_dev_task_vipBigPoint.sh
index d6cc9d4de..21960394b 100644
--- a/qinglong/DefaultTasks/dev/bili_dev_task_vipBigPoint.sh
+++ b/qinglong/DefaultTasks/dev/bili_dev_task_vipBigPoint.sh
@@ -3,7 +3,5 @@
# cron 7 1 * * * bili_dev_task_vipBigPoint.sh
. bili_dev_task_base.sh
-cd ./src/Ray.BiliBiliTool.Console
-
-export Ray_RunTasks=VipBigPoint && \
-dotnet run --ENVIRONMENT=Production
+target_task_code="VipBigPoint"
+run_task "${target_task_code}"
\ No newline at end of file
diff --git a/qinglong/README.md b/qinglong/README.md
index 8e0e8896c..67b3fcdc1 100644
--- a/qinglong/README.md
+++ b/qinglong/README.md
@@ -1,6 +1,6 @@
# 在青龙中运行
-总体思路是,在青龙容器中安装 dotnet 环境,利用青龙的拉库命令,拉取本仓库源码,添加cron定时任务,定时运行相应的Task。
+思路是,在青龙容器中安装`dotnet`环境或`bilitool`的二进制包,利用青龙的拉库命令,拉取本仓库源码,添加cron定时任务,定时运行相应的Task。
开始前,请先确保你的青龙面板是运行正常的。
@@ -9,15 +9,15 @@
- [1. 步骤](#1-步骤)
- [1.1. 登录青龙面板并修改配置](#11-登录青龙面板并修改配置)
- [1.2. 在青龙面板中添加拉库定时任务](#12-在青龙面板中添加拉库定时任务)
- - [1.2.1. 订阅管理](#121-订阅管理)
- - [1.2.2. 定时任务拉库](#122-定时任务拉库)
- - [1.3. 登录](#13-登录)
+ - [1.2.1. 方式一:订阅管理](#121-方式一订阅管理)
+ - [1.2.2. 方式二:定时任务拉库](#122-方式二定时任务拉库)
+ - [1.3. 检查定时任务](#13-检查定时任务)
+ - [1.4. 登录](#14-登录)
- [2. 先行版](#2-先行版)
- - [2.1. 订阅管理](#21-订阅管理)
- - [2.2. 定时任务拉库](#22-定时任务拉库)
- [3. GitHub加速](#3-github加速)
- [4. 常见问题](#4-常见问题)
- - [4.1. Couldn't find a valid ICU package installed on the system](#41-couldnt-find-a-valid-icu-package-installed-on-the-system)
+ - [4.1. 安装dotnet失败怎么办法](#41-安装dotnet失败怎么办法)
+ - [4.2. Couldn't find a valid ICU package installed on the system](#42-couldnt-find-a-valid-icu-package-installed-on-the-system)
@@ -32,8 +32,9 @@
### 1.2. 在青龙面板中添加拉库定时任务
-两种方式:
-#### 1.2.1. 订阅管理
+两种方式,任选其一即可:
+
+#### 1.2.1. 方式一:订阅管理
```
名称:Bilibili
@@ -49,7 +50,7 @@
保存后,点击运行按钮,运行拉库。
-#### 1.2.2. 定时任务拉库
+#### 1.2.2. 方式二:定时任务拉库
青龙面板,`定时任务`页,右上角`添加任务`,填入以下信息:
```
@@ -62,11 +63,13 @@
保存成功后,找到该定时任务,点击运行按钮,运行拉库。
-如果正常,拉库成功后,同时也会自动添加bilibili相关的task任务。
+### 1.3. 检查定时任务
+
+如果正常,拉库成功后,会自动添加bilibili相关的task任务。
![qinglong-tasks.png](../docs/imgs/qinglong-tasks.png)
-### 1.3. 登录
+### 1.4. 登录
在青龙定时任务中,点击运行`bili扫码登录`任务,查看运行日志,扫描日志中的二维码进行登录。
![qinglong-login.png](../docs/imgs/qinglong-login.png)
@@ -75,7 +78,7 @@
![qinglong-env.png](../docs/imgs/qinglong-env.png)
-首次运行会自动安装dotnet环境,时间久点,之后就不需要重复安装了。
+首次运行会自动安装环境,时间可能长一点,之后就不需要重复安装了。
## 2. 先行版
@@ -83,10 +86,6 @@
想提前体验新功能的朋友可以尝试切换先行版,但同时也意味着稳定性会相应降低(其实是相当于在帮我内测测试bug了~🤨)。
-方式有两种:
-
-### 2.1. 订阅管理
-
```
分支:develop
白名单:bili_dev_task_.+\.sh
@@ -94,16 +93,40 @@
其他选项同上。
-### 2.2. 定时任务拉库
+## 3. GitHub加速
+
+拉库时,如果服务器在国内,访问GitHub速度慢,可在仓库地址前加上加速代理进行加速。
-修改拉库命令为`ql repo https://github.com/RayWangQvQ/BiliBiliToolPro.git "bili_dev_task_" "" "" "develop"`
+如:
-## 3. GitHub加速
-拉库时,如果服务器在国内,访问GitHub速度慢,可以在仓库地址前加上 `https://ghproxy.com/` 进行加速, 如:`ql repo https://ghproxy.com/https://github.com/RayWangQvQ/BiliBiliToolPro.git "bili_task_"`
+```
+https://github.moeyy.xyz/https://github.com/RayWangQvQ/BiliBiliToolPro.git
+https://ghproxy.net/https://github.com/RayWangQvQ/BiliBiliToolPro.git
+...
+```
+
+加速代理地址通常不能保证长期稳定,请自行查找使用。
## 4. 常见问题
-### 4.1. Couldn't find a valid ICU package installed on the system
+### 4.1. 安装dotnet失败怎么办法
+
+先通过日志自行排查,不行就根据微软官方文档,进入qinglong容器后,手动安装。
+
+如果还不行,那么可以切换到基于`bilitool`的二进制包运行方式,该方式不需要安装`dotnet`,方式:
+
+编辑青龙面板的`配置文件`,新增如下两行:
+
+```
+export BILI_MODE="bilitool" # bili运行模式,dotnet或bilitool
+export BILI_GITHUB_PROXY="https://github.moeyy.xyz/" # 下载二进制包时使用的加速代理,不要的话则置空
+```
+
+其中加速代理形如:`https://github.moeyy.xyz/`或`https://ghproxy.net/`,因通常不能保证长期稳定,请自行查找使用。
+
+![qinglong-login.png](../docs/imgs/qinglong-run-as-bilitool.png)
+
+### 4.2. Couldn't find a valid ICU package installed on the system
如 #266 ,需要在青龙面板的环境变量添加如下环境变量:
diff --git a/qinglong/dotnet-install.sh b/qinglong/dotnet-install.sh
index f80355e5f..096348d34 100644
--- a/qinglong/dotnet-install.sh
+++ b/qinglong/dotnet-install.sh
@@ -1314,6 +1314,7 @@ calculate_vars() {
script_name=$(basename "$0")
normalized_architecture="$(get_normalized_architecture_from_architecture "$architecture")"
say_verbose "Normalized architecture: '$normalized_architecture'."
+
normalized_os="$(get_normalized_os "$user_defined_os")"
say_verbose "Normalized OS: '$normalized_os'."
normalized_quality="$(get_normalized_quality "$quality")"
diff --git a/qinglong/ray-dotnet-install.sh b/qinglong/ray-dotnet-install.sh
index b57cf3520..1310277b2 100644
--- a/qinglong/ray-dotnet-install.sh
+++ b/qinglong/ray-dotnet-install.sh
@@ -3,29 +3,6 @@ echo -e "\n-------set up dot net env-------"
## 安装dotnet
-DOWNLOAD_X64=https://download.visualstudio.microsoft.com/download/pr/d74b9eb9-d60c-4b0d-8d53-f30a6e22b917/ef06d32d3b5206786eac8011798568aa/dotnet-sdk-6.0.405-linux-musl-x64.tar.gz
-DOWNLOAD_ARM32=https://download.visualstudio.microsoft.com/download/pr/29682aff-7321-4034-9833-29f3ea435759/cf2fd8a078d3a6c106a1254cc2887ad3/dotnet-sdk-6.0.405-linux-musl-arm.tar.gz
-DOWNLOAD_ARM64=https://download.visualstudio.microsoft.com/download/pr/207a3484-7524-4963-9c4e-dacf20ba3a66/4a3bc869dc7a93753022752aa5782989/dotnet-sdk-6.0.405-linux-musl-arm64.tar.gz
-
-get_download_url_by_machine_architecture() {
- if command -v uname >/dev/null; then
- CPUName=$(uname -m)
- case $CPUName in
- armv*l)
- echo $DOWNLOAD_ARM32
- return 0
- ;;
- aarch64 | arm64)
- echo $DOWNLOAD_ARM64
- return 0
- ;;
- esac
- fi
- # Always default to 'x64'
- echo $DOWNLOAD_X64
- return 0
-}
-
# 安装依赖
install_dependency() {
echo "安装依赖..."
@@ -38,20 +15,6 @@ install_by_offical() {
curl -sSL https://dot.net/v1/dotnet-install.sh | bash /dev/stdin --channel 6.0 --no-cdn --verbose
}
-# 通过vscode域自己下载二进制文件安装dotnet
-# https://dotnet.microsoft.com/zh-cn/download/dotnet/6.0
-install_by_binaries() {
- echo "install by binaries..."
- DOWNLOAD_URL="$(get_download_url_by_machine_architecture)"
- DOTNET_FILE=dotnet-sdk.tar.gz
-
- wget -O $DOTNET_FILE $DOWNLOAD_URL
- DOTNET_ROOT=~/.dotnet
- mkdir -p "$DOTNET_ROOT" && tar zxf "$DOTNET_FILE" -C "$DOTNET_ROOT"
-
- export PATH=$PATH:$DOTNET_ROOT
-}
-
# 创建软链接
create_soft_link() {
# echo "创建软链接..."
@@ -69,47 +32,9 @@ create_soft_link() {
args=("$@")
-# 不使用官方脚本
-no_official=false
-
-while [ $# -ne 0 ]; do
- name="$1"
- case "$name" in
- --no-official | -[Nn]o[Oo]fficial)
- no_official=true
- ;;
- -? | --? | -h | --help | -[Hh]elp)
- script_name="$(basename "$0")"
- echo ".NET Tools Installer"
- echo ""
- echo "$script_name is a simple command line interface for obtaining dotnet cli."
- echo ""
- echo " --no-official, -NoOfficial Do not use the official script, download sdk by visualstudio domain directly."
- echo " -?,--?,-h,--help,-Help Shows this help message"
- echo ""
- echo "Install Location:"
- echo " Location is chosen in following order:"
- echo " - --install-dir option"
- echo " - Environmental variable DOTNET_INSTALL_DIR"
- echo " - $HOME/.dotnet"
- exit 0
- ;;
- *)
- echo "Unknown argument \`$name\`"
- exit 1
- ;;
- esac
-
- shift
-done
-
install_dependency
-if [ "$no_official" = true ]; then
- install_by_binaries
-else
- install_by_offical
-fi
+install_by_offical
create_soft_link
diff --git a/scripts/publish.sh b/scripts/publish.sh
index 74811d8e7..99501c824 100644
--- a/scripts/publish.sh
+++ b/scripts/publish.sh
@@ -122,7 +122,7 @@ main() {
# self contained
# https://learn.microsoft.com/zh-cn/dotnet/core/rid-catalog
- array=("win-x86" "win-x64" "win-arm64" "linux-x64" "linux-musl-x64" "linux-arm64" "linux-arm" "osx-x64")
+ array=("win-x86" "win-x64" "win-arm64" "linux-x64" "linux-musl-x64" "linux-arm64" "linux-arm" "linux-musl-arm64" "osx-x64")
if [ "$runTime" != "all" ]; then
array=("$runTime")
fi
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IAccountApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IAccountApi.cs
index 42fa70eec..d0c620275 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IAccountApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IAccountApi.cs
@@ -2,17 +2,16 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+[Header("Host", "account.bilibili.com")]
+public interface IAccountApi : IBiliBiliApi
{
- [Header("Host", "account.bilibili.com")]
- public interface IAccountApi : IBiliBiliApi
- {
- ///
- /// 获取硬币余额
- ///
- ///
- [Header("Referer", "https://account.bilibili.com/account/coin")]
- [HttpGet("/site/getCoin")]
- Task> GetCoinBalanceAsync();
- }
+ ///
+ /// 获取硬币余额
+ ///
+ ///
+ [Header("Referer", "https://account.bilibili.com/account/coin")]
+ [HttpGet("/site/getCoin")]
+ Task> GetCoinBalanceAsync();
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs
index 88d993863..9ae88929d 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs
@@ -3,34 +3,44 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
-{
-
- [Header("Host", "api.bilibili.com")]
- public interface IArticleApi : IBiliBiliApi
- {
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://space.bilibili.com")]
- [HttpGet("/x/space/wbi/article")]
- Task> SearchUpArticlesByUpIdAsync([PathQuery] SearchArticlesByUpIdDto request);
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
- ///
- /// 获取专栏详情
- ///
- ///
- ///
- [HttpGet("/x/article/viewinfo?id={cvid}")]
- Task> SearchArticleInfoAsync(long cvid);
+[Header("Host", "api.bilibili.com")]
+public interface IArticleApi : IBiliBiliApi
+{
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://space.bilibili.com")]
+ [HttpGet("/x/space/wbi/article")]
+ Task> SearchUpArticlesByUpIdAsync([PathQuery] SearchArticlesByUpIdDto request);
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/web-interface/coin/add")]
- Task AddCoinForArticleAsync([FormContent] AddCoinForArticleRequest request, [Header("referer")] string refer = "https://www.bilibili.com/read/cv5806746/?from=search&spm_id_from=333.337.0.0");
+ ///
+ /// 获取专栏详情
+ ///
+ ///
+ ///
+ [HttpGet("/x/article/viewinfo?id={cvid}")]
+ Task> SearchArticleInfoAsync(long cvid);
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- [Header("Referer", "https://www.bilibili.com/read/cv{cvid}/?from=search&spm_id_from=333.337.0.0")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/article/like?id={cvid}&type=1&csrf={csrf}")]
- Task LikeAsync(long cvid, string csrf);
- }
+ ///
+ /// 为专栏文章投币
+ ///
+ ///
+ ///
+ ///
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/web-interface/coin/add")]
+ Task AddCoinForArticleAsync([FormContent] AddCoinForArticleRequest request, [Header("referer")] string refer = "https://www.bilibili.com/read/cv5806746/?from=search&spm_id_from=333.337.0.0");
+
+ ///
+ /// 为专栏文章点赞
+ ///
+ ///
+ ///
+ ///
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ [Header("Referer", "https://www.bilibili.com/read/cv{cvid}/?from=search&spm_id_from=333.337.0.0")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/article/like?id={cvid}&type=1&csrf={csrf}")]
+ Task LikeAsync(long cvid, string csrf);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IBiliBiliApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IBiliBiliApi.cs
index 35af6941b..50586ca94 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IBiliBiliApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IBiliBiliApi.cs
@@ -1,20 +1,19 @@
using Ray.BiliBiliTool.Agent.Attributes;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
-{
- [AppendHeader("Accept", "application/json, text/plain, */*", AppendHeaderType.AddIfNotExist)]
- //[Header("Accept-Encoding", "gzip, deflate, br")]
- [AppendHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", AppendHeaderType.AddIfNotExist)]
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+[AppendHeader("Accept", "application/json, text/plain, */*", AppendHeaderType.AddIfNotExist)]
+//[Header("Accept-Encoding", "gzip, deflate, br")]
+[AppendHeader("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6", AppendHeaderType.AddIfNotExist)]
- [AppendHeader("Sec-Fetch-Dest", "empty", AppendHeaderType.AddIfNotExist)]
- [AppendHeader("Sec-Fetch-Mode", "cors", AppendHeaderType.AddIfNotExist)]
- [AppendHeader("Sec-Fetch-Site", "same-site", AppendHeaderType.AddIfNotExist)]
+[AppendHeader("Sec-Fetch-Dest", "empty", AppendHeaderType.AddIfNotExist)]
+[AppendHeader("Sec-Fetch-Mode", "cors", AppendHeaderType.AddIfNotExist)]
+[AppendHeader("Sec-Fetch-Site", "same-site", AppendHeaderType.AddIfNotExist)]
- [AppendHeader("Connection", "keep-alive", AppendHeaderType.AddIfNotExist)]
+[AppendHeader("Connection", "keep-alive", AppendHeaderType.AddIfNotExist)]
- [LogFilter]
- public interface IBiliBiliApi
- {
- }
+[LogFilter]
+public interface IBiliBiliApi
+{
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IChargeApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IChargeApi.cs
index 3a788381e..7673b63d6 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IChargeApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IChargeApi.cs
@@ -4,53 +4,52 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 充电相关接口
+///
+[Header("Host", "api.bilibili.com")]
+public interface IChargeApi : IBiliBiliApi
{
///
- /// 充电相关接口
+ /// 充电
///
- [Header("Host", "api.bilibili.com")]
- public interface IChargeApi : IBiliBiliApi
- {
- ///
- /// 充电
- ///
- /// 充电电池数量(B币*10),必须在20-99990之间
- /// 充电对象用户UID
- /// 充电来源代码(空间充电:充电对象用户UID;视频充电:稿件avID)
- ///
- ///
- [HttpPost("/x/ugcpay/trade/elec/pay/quick?elec_num={elec_num}&up_mid={up_mid}&otype=up&oid={oid}&csrf={csrf}")]
- [Obsolete]
- Task> Charge(int elec_num, string up_mid, string oid, string csrf);
+ /// 充电电池数量(B币*10),必须在20-99990之间
+ /// 充电对象用户UID
+ /// 充电来源代码(空间充电:充电对象用户UID;视频充电:稿件avID)
+ ///
+ ///
+ [HttpPost("/x/ugcpay/trade/elec/pay/quick?elec_num={elec_num}&up_mid={up_mid}&otype=up&oid={oid}&csrf={csrf}")]
+ [Obsolete]
+ Task> Charge(int elec_num, string up_mid, string oid, string csrf);
- ///
- /// 充电V2
- ///
- /// B币个数
- /// 对方Id
- /// 对方来源代码(空间充电:充电对象用户UID;视频充电:稿件avID)
- /// 自己的bili_jct
- ///
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/ugcpay/web/v2/trade/elec/pay/quick")]
- Task> ChargeV2Async([FormContent] ChargeRequest request);
+ ///
+ /// 充电V2
+ ///
+ /// B币个数
+ /// 对方Id
+ /// 对方来源代码(空间充电:充电对象用户UID;视频充电:稿件avID)
+ /// 自己的bili_jct
+ ///
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/ugcpay/web/v2/trade/elec/pay/quick")]
+ Task> ChargeV2Async([FormContent] ChargeRequest request);
- ///
- /// 充电后留言
- ///
- ///
- ///
- ///
- ///
- ///
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/ugcpay/trade/elec/message")]
- Task> ChargeCommentAsync([FormContent] ChargeCommentRequest request);
+ ///
+ /// 充电后留言
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/ugcpay/trade/elec/message")]
+ Task> ChargeCommentAsync([FormContent] ChargeCommentRequest request);
- }
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IDailyTaskApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IDailyTaskApi.cs
index 9a5f1ac1b..d685a19d5 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IDailyTaskApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IDailyTaskApi.cs
@@ -3,39 +3,38 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// BiliBili每日任务相关接口
+///
+[Header("Host", "api.bilibili.com")]
+public interface IDailyTaskApi : IBiliBiliApi
{
///
- /// BiliBili每日任务相关接口
+ /// 获取每日任务的完成情况
///
- [Header("Host", "api.bilibili.com")]
- public interface IDailyTaskApi : IBiliBiliApi
- {
- ///
- /// 获取每日任务的完成情况
- ///
- ///
- [Header("Referer", "https://account.bilibili.com/account/home")]
- [Header("Origin", "https://account.bilibili.com")]
- [HttpGet("/x/member/web/exp/reward")]
- Task> GetDailyTaskRewardInfoAsync();
+ ///
+ [Header("Referer", "https://account.bilibili.com/account/home")]
+ [Header("Origin", "https://account.bilibili.com")]
+ [HttpGet("/x/member/web/exp/reward")]
+ Task> GetDailyTaskRewardInfoAsync();
- ///
- /// 获取通过投币已获取的经验值
- ///
- ///
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpGet("/x/web-interface/coin/today/exp")]
- Task> GetDonateCoinExpAsync();
+ ///
+ /// 获取通过投币已获取的经验值
+ ///
+ ///
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpGet("/x/web-interface/coin/today/exp")]
+ Task> GetDonateCoinExpAsync();
- ///
- /// 获取VIP特权
- ///
- ///
- ///
- ///
- [HttpPost("/x/vip/privilege/receive?type={type}&csrf={csrf}")]
- Task ReceiveVipPrivilegeAsync(int type, string csrf);
- }
+ ///
+ /// 获取VIP特权
+ ///
+ ///
+ ///
+ ///
+ [HttpPost("/x/vip/privilege/receive?type={type}&csrf={csrf}")]
+ Task ReceiveVipPrivilegeAsync(int type, string csrf);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IHomeApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IHomeApi.cs
index d4dea1694..9027019a6 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IHomeApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IHomeApi.cs
@@ -5,14 +5,13 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 主站首页接口API
+///
+public interface IHomeApi : IBiliBiliApi
{
- ///
- /// 主站首页接口API
- ///
- public interface IHomeApi : IBiliBiliApi
- {
- [HttpGet("")]
- Task GetHomePageAsync([Header("Cookie")] string ck);
- }
+ [HttpGet("")]
+ Task GetHomePageAsync([Header("Cookie")] string ck);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs
index 33b72cf6d..0db0ae863 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveApi.cs
@@ -5,148 +5,147 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Live;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 直播相关接口
+///
+[Header("Host", "api.live.bilibili.com")]
+
+public interface ILiveApi : IBiliBiliApi
{
///
- /// 直播相关接口
+ /// 直播签到
+ ///
+ ///
+ [Header("Referer", "https://link.bilibili.com/")]
+ [Header("Origin", "https://link.bilibili.com")]
+ [HttpGet("/xlive/web-ucenter/v1/sign/DoSign")]
+ Task> Sign();
+
+ ///
+ /// 银瓜子兑换硬币
+ ///
+ ///
+ [Header("Referer", "https://link.bilibili.com/")]
+ [Header("Origin", "https://link.bilibili.com")]
+ [Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")]
+ [HttpGet("/pay/v1/Exchange/silver2coin")]
+ [Obsolete]
+ Task ExchangeSilver2Coin();
+
+ ///
+ /// 获取银瓜子余额
+ ///
+ ///
+ [Header("Referer", "https://link.bilibili.com/")]
+ [Header("Origin", "https://link.bilibili.com")]
+ [HttpGet("/pay/v1/Exchange/getStatus")]
+ [Obsolete]
+ Task> GetExchangeSilverStatus();
+
+ ///
+ /// 银瓜子兑换硬币
+ ///
+ ///
+ ///
+ //[Header("Referer", "https://link.bilibili.com/p/center/index?visit_id=1ddo4yl01q00")]
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ [Header("Origin", "https://link.bilibili.com")]
+ [HttpPost("/xlive/revenue/v1/wallet/silver2coin")]
+ Task> Silver2Coin([FormContent] Silver2CoinRequest request);
+
+ ///
+ /// 获取直播中心钱包状态
+ ///
+ ///
+ //[Header("Referer", "https://link.bilibili.com/p/center/index?visit_id=1ddo4yl01q00")]
+ [Header("Origin", "https://link.bilibili.com")]
+ [HttpGet("/xlive/revenue/v1/wallet/getStatus")]
+ Task> GetLiveWalletStatus();
+
+ [HttpGet("/xlive/web-interface/v1/index/getWebAreaList?source_id=2")]
+ Task> GetAreaList();
+
+ ///
+ /// 获取直播列表
+ ///
+ ///
+ ///
+ ///
+ /// sort_type_124
+ ///
+ [Header("Referer", "https://live.bilibili.com/")]
+ [Header("Origin", "https://live.bilibili.com")]
+ [HttpGet("/xlive/web-interface/v1/second/getList?platform=web&parent_area_id={parentAreaId}&area_id={areaId}&sort_type={sortType}&page={page}")]
+ Task> GetList(long parentAreaId, int page, int areaId = 0, string sortType = "");
+ //todo:Cookie比nav接口多了两项:Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02、Hm_lvt_9e2a88dc69e0e55c353597501d2a4bbc
+
+ ///
+ /// 检查天选时刻抽奖
+ ///
+ ///
+ ///
+ [Header("Referer", "https://live.bilibili.com/")]
+ [Header("Origin", "https://live.bilibili.com")]
+ [HttpGet("/xlive/lottery-interface/v1/Anchor/Check?roomid={roomId}")]
+ Task> CheckTianXuan(long roomId);
+
+ ///
+ /// 参加天选时刻抽奖
+ ///
+ ///
+ ///
+ [HttpPost("/xlive/lottery-interface/v1/Anchor/Join")]
+ Task> Join([FormContent] JoinTianXuanRequest request);
+
+ ///
+ /// 获取用户的粉丝勋章
+ ///
+ /// uid
+ ///
+ [Header("Referer", "https://live.bilibili.com/")]
+ [Header("Origin", "https://live.bilibili.com")]
+ [HttpGet("/xlive/web-ucenter/user/MedalWall?target_id={userId}")]
+ Task> GetMedalWall(string userId);
+
+ ///
+ /// 佩戴粉丝勋章
+ ///
+ /// uid
+ ///
+ [Header("Referer", "https://live.bilibili.com/")]
+ [Header("Origin", "https://live.bilibili.com")]
+ [HttpPost("/xlive/app-ucenter/v1/fansMedal/wear")]
+ Task WearMedalWall([FormContent] WearMedalWallRequest request);
+
+ ///
+ /// 发送弹幕
+ ///
+ /// request
+ ///
+ [HttpPost("/msg/send")]
+ Task SendLiveDanmuku([FormContent] SendLiveDanmukuRequest request);
+
+ ///
+ /// 获取直播间信息
+ ///
+ /// roomId
+ ///
+ [HttpGet("/room/v1/Room/get_info?room_id={roomId}&from=room")]
+ Task> GetLiveRoomInfo(long roomId);
+
+ ///
+ /// 请求直播主页用于配置直播相关 Cookie
+ ///
+ [HttpGet("/news/v1/notice/recom?product=live")]
+ Task GetLiveHome();
+
+ ///
+ /// 点赞直播间
///
- [Header("Host", "api.live.bilibili.com")]
-
- public interface ILiveApi : IBiliBiliApi
- {
- ///
- /// 直播签到
- ///
- ///
- [Header("Referer", "https://link.bilibili.com/")]
- [Header("Origin", "https://link.bilibili.com")]
- [HttpGet("/xlive/web-ucenter/v1/sign/DoSign")]
- Task> Sign();
-
- ///
- /// 银瓜子兑换硬币
- ///
- ///
- [Header("Referer", "https://link.bilibili.com/")]
- [Header("Origin", "https://link.bilibili.com")]
- [Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")]
- [HttpGet("/pay/v1/Exchange/silver2coin")]
- [Obsolete]
- Task ExchangeSilver2Coin();
-
- ///
- /// 获取银瓜子余额
- ///
- ///
- [Header("Referer", "https://link.bilibili.com/")]
- [Header("Origin", "https://link.bilibili.com")]
- [HttpGet("/pay/v1/Exchange/getStatus")]
- [Obsolete]
- Task> GetExchangeSilverStatus();
-
- ///
- /// 银瓜子兑换硬币
- ///
- ///
- ///
- //[Header("Referer", "https://link.bilibili.com/p/center/index?visit_id=1ddo4yl01q00")]
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- [Header("Origin", "https://link.bilibili.com")]
- [HttpPost("/xlive/revenue/v1/wallet/silver2coin")]
- Task> Silver2Coin([FormContent] Silver2CoinRequest request);
-
- ///
- /// 获取直播中心钱包状态
- ///
- ///
- //[Header("Referer", "https://link.bilibili.com/p/center/index?visit_id=1ddo4yl01q00")]
- [Header("Origin", "https://link.bilibili.com")]
- [HttpGet("/xlive/revenue/v1/wallet/getStatus")]
- Task> GetLiveWalletStatus();
-
- [HttpGet("/xlive/web-interface/v1/index/getWebAreaList?source_id=2")]
- Task> GetAreaList();
-
- ///
- /// 获取直播列表
- ///
- ///
- ///
- ///
- /// sort_type_124
- ///
- [Header("Referer", "https://live.bilibili.com/")]
- [Header("Origin", "https://live.bilibili.com")]
- [HttpGet("/xlive/web-interface/v1/second/getList?platform=web&parent_area_id={parentAreaId}&area_id={areaId}&sort_type={sortType}&page={page}")]
- Task> GetList(long parentAreaId, int page, int areaId = 0, string sortType = "");
- //todo:Cookie比nav接口多了两项:Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02、Hm_lvt_9e2a88dc69e0e55c353597501d2a4bbc
-
- ///
- /// 检查天选时刻抽奖
- ///
- ///
- ///
- [Header("Referer", "https://live.bilibili.com/")]
- [Header("Origin", "https://live.bilibili.com")]
- [HttpGet("/xlive/lottery-interface/v1/Anchor/Check?roomid={roomId}")]
- Task> CheckTianXuan(long roomId);
-
- ///
- /// 参加天选时刻抽奖
- ///
- ///
- ///
- [HttpPost("/xlive/lottery-interface/v1/Anchor/Join")]
- Task> Join([FormContent] JoinTianXuanRequest request);
-
- ///
- /// 获取用户的粉丝勋章
- ///
- /// uid
- ///
- [Header("Referer", "https://live.bilibili.com/")]
- [Header("Origin", "https://live.bilibili.com")]
- [HttpGet("/xlive/web-ucenter/user/MedalWall?target_id={userId}")]
- Task> GetMedalWall(string userId);
-
- ///
- /// 佩戴粉丝勋章
- ///
- /// uid
- ///
- [Header("Referer", "https://live.bilibili.com/")]
- [Header("Origin", "https://live.bilibili.com")]
- [HttpPost("/xlive/app-ucenter/v1/fansMedal/wear")]
- Task WearMedalWall([FormContent] WearMedalWallRequest request);
-
- ///
- /// 发送弹幕
- ///
- /// request
- ///
- [HttpPost("/msg/send")]
- Task SendLiveDanmuku([FormContent] SendLiveDanmukuRequest request);
-
- ///
- /// 获取直播间信息
- ///
- /// roomId
- ///
- [HttpGet("/room/v1/Room/get_info?room_id={roomId}&from=room")]
- Task> GetLiveRoomInfo(long roomId);
-
- ///
- /// 请求直播主页用于配置直播相关 Cookie
- ///
- [HttpGet("/news/v1/notice/recom?product=live")]
- Task GetLiveHome();
-
- ///
- /// 点赞直播间
- ///
- [HttpPost("/xlive/web-ucenter/v1/interact/likeInteract")]
- [Header("Referer", "https://live.bilibili.com/")]
- [Header("Origin", "https://live.bilibili.com")]
- Task LikeLiveRoom([FormContent] LikeLiveRoomRequest request);
- }
+ [HttpPost("/xlive/web-ucenter/v1/interact/likeInteract")]
+ [Header("Referer", "https://live.bilibili.com/")]
+ [Header("Origin", "https://live.bilibili.com")]
+ Task LikeLiveRoom([FormContent] LikeLiveRoomRequest request);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveTraceApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveTraceApi.cs
index c5a36904c..90cb1a053 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveTraceApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/ILiveTraceApi.cs
@@ -4,19 +4,18 @@
using System.Threading.Tasks;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+[Header("Host", "live-trace.bilibili.com")]
+public interface ILiveTraceApi : IBiliBiliApi
{
- [Header("Host", "live-trace.bilibili.com")]
- public interface ILiveTraceApi : IBiliBiliApi
- {
- [HttpGet("/xlive/rdata-interface/v1/heartbeat/webHeartBeat?hb={request}&pf=web")]
- Task> WebHeartBeat(WebHeartBeatRequest request);
+ [HttpGet("/xlive/rdata-interface/v1/heartbeat/webHeartBeat?hb={request}&pf=web")]
+ Task> WebHeartBeat(WebHeartBeatRequest request);
- [HttpPost("/xlive/data-interface/v1/x25Kn/E")]
- Task> EnterRoom([FormContent] EnterRoomRequest request);
+ [HttpPost("/xlive/data-interface/v1/x25Kn/E")]
+ Task> EnterRoom([FormContent] EnterRoomRequest request);
- [HttpPost("/xlive/data-interface/v1/x25Kn/X")]
- Task> HeartBeat([FormContent] HeartBeatRequest request);
- }
+ [HttpPost("/xlive/data-interface/v1/x25Kn/X")]
+ Task> HeartBeat([FormContent] HeartBeatRequest request);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs
index 7a851b2de..e86c3c0c2 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs
@@ -3,38 +3,37 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 漫画相关接口
+///
+[Header("Origin", "https://manga.bilibili.com")]
+[Header("Host", "manga.bilibili.com")]
+public interface IMangaApi : IBiliBiliApi
{
///
- /// 漫画相关接口
+ /// 漫画签到
///
- [Header("Origin", "https://manga.bilibili.com")]
- [Header("Host", "manga.bilibili.com")]
- public interface IMangaApi : IBiliBiliApi
- {
- ///
- /// 漫画签到
- ///
- ///
- ///
- [LogFilter(false)]
- [HttpPost("/twirp/activity.v1.Activity/ClockIn?platform={platform}")]
- Task ClockIn(string platform);
+ ///
+ ///
+ [LogFilter(false)]
+ [HttpPost("/twirp/activity.v1.Activity/ClockIn?platform={platform}")]
+ Task ClockIn(string platform);
- ///
- /// 漫画阅读
- ///
- ///
- ///
- [HttpPost("/twirp/bookshelf.v1.Bookshelf/AddHistory?platform={platform}&comic_id={comic_id}&ep_id={ep_id}")]
- Task ReadManga(string platform, long comic_id, long ep_id);
+ ///
+ /// 漫画阅读
+ ///
+ ///
+ ///
+ [HttpPost("/twirp/bookshelf.v1.Bookshelf/AddHistory?platform={platform}&comic_id={comic_id}&ep_id={ep_id}")]
+ Task ReadManga(string platform, long comic_id, long ep_id);
- ///
- /// 获取会员漫画奖励
- ///
- ///
- ///
- [HttpPost("/twirp/user.v1.User/GetVipReward?reason_id={reason_id}")]
- Task> ReceiveMangaVipReward(int reason_id);
- }
+ ///
+ /// 获取会员漫画奖励
+ ///
+ ///
+ ///
+ [HttpPost("/twirp/user.v1.User/GetVipReward?reason_id={reason_id}")]
+ Task> ReceiveMangaVipReward(int reason_id);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IPassportApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IPassportApi.cs
index f016705b1..f061ee0ba 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IPassportApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IPassportApi.cs
@@ -4,19 +4,18 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Passport;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+[Header("Host", "passport.bilibili.com")]
+public interface IPassportApi : IBiliBiliApi
{
- [Header("Host", "passport.bilibili.com")]
- public interface IPassportApi : IBiliBiliApi
- {
- [HttpGet("/x/passport-login/web/qrcode/generate")]
- Task> GenerateQrCode();
+ [HttpGet("/x/passport-login/web/qrcode/generate")]
+ Task> GenerateQrCode();
- [HttpGet("/x/passport-login/web/qrcode/poll?qrcode_key={qrcode_key}&source=main_mini")]
- //Task> CheckQrCodeHasScaned(string qrcode_key);
- Task CheckQrCodeHasScaned(string qrcode_key);
+ [HttpGet("/x/passport-login/web/qrcode/poll?qrcode_key={qrcode_key}&source=main_mini")]
+ //Task> CheckQrCodeHasScaned(string qrcode_key);
+ Task CheckQrCodeHasScaned(string qrcode_key);
- [HttpGet("/x/passport-login/web/sso/list?biliCSRF={csrf}")]
- Task> GetSsoListAsync(string csrf);
- }
+ [HttpGet("/x/passport-login/web/sso/list?biliCSRF={csrf}")]
+ Task> GetSsoListAsync(string csrf);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IRelationApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IRelationApi.cs
index 6e306476d..d84b5c258 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IRelationApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IRelationApi.cs
@@ -9,103 +9,102 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Relation;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 关注相关接口
+///
+[AppendHeader("Host", "api.bilibili.com", AppendHeaderType.AddIfNotExist)]
+[AppendHeader("Referer", "https://space.bilibili.com/", AppendHeaderType.AddIfNotExist)]
+public interface IRelationApi : IBiliBiliApi
{
///
- /// 关注相关接口
+ /// 获取关注列表
///
- [AppendHeader("Host", "api.bilibili.com", AppendHeaderType.AddIfNotExist)]
- [AppendHeader("Referer", "https://space.bilibili.com/", AppendHeaderType.AddIfNotExist)]
- public interface IRelationApi : IBiliBiliApi
- {
- ///
- /// 获取关注列表
- ///
- ///
- [HttpGet("/x/relation/followings")]
- Task> GetFollowings(GetFollowingsRequest request);
+ ///
+ [HttpGet("/x/relation/followings")]
+ Task> GetFollowings(GetFollowingsRequest request);
- ///
- /// 获取特别关注列表
- ///
- ///
- [Header("Cache-Control", "no-cache")]
- [Header("Pragma", "no-cache")]
- [JsonReturn(EnsureMatchAcceptContentType = false)]
- [HttpGet("/x/relation/tag")]
- Task>> GetFollowingsByTag(GetSpecialFollowingsRequest request);
+ ///
+ /// 获取特别关注列表
+ ///
+ ///
+ [Header("Cache-Control", "no-cache")]
+ [Header("Pragma", "no-cache")]
+ [JsonReturn(EnsureMatchAcceptContentType = false)]
+ [HttpGet("/x/relation/tag")]
+ Task>> GetFollowingsByTag(GetSpecialFollowingsRequest request);
- ///
- /// 获取关注分组
- ///
- ///
- [AppendHeader("Sec-Fetch-Mode", "no-cors")]
- [AppendHeader("Sec-Fetch-Dest", "script")]
- [HttpGet("/x/relation/tags?jsonp=jsonp")]
- Task>> GetTags([AppendHeader("Referer")] string referer = RelationApiConstant.GetTagsReferer);
+ ///
+ /// 获取关注分组
+ ///
+ ///
+ [AppendHeader("Sec-Fetch-Mode", "no-cors")]
+ [AppendHeader("Sec-Fetch-Dest", "script")]
+ [HttpGet("/x/relation/tags?jsonp=jsonp")]
+ Task>> GetTags([AppendHeader("Referer")] string referer = RelationApiConstant.GetTagsReferer);
- ///
- /// 添加关注分组(tag)
- ///
- ///
- ///
- [AppendHeader("Origin", "https://space.bilibili.com")]
- [HttpPost("/x/relation/tag/create?cross_domain=true")]
- Task> CreateTag([FormContent] CreateTagRequest request,
- [AppendHeader("Referer")] string referer = RelationApiConstant.GetTagsReferer);
+ ///
+ /// 添加关注分组(tag)
+ ///
+ ///
+ ///
+ [AppendHeader("Origin", "https://space.bilibili.com")]
+ [HttpPost("/x/relation/tag/create?cross_domain=true")]
+ Task> CreateTag([FormContent] CreateTagRequest request,
+ [AppendHeader("Referer")] string referer = RelationApiConstant.GetTagsReferer);
- ///
- /// 批量拷贝关注up到某指定分组
- ///
- ///
- ///
- [AppendHeader("Origin", "https://space.bilibili.com")]
- [HttpPost("/x/relation/tags/copyUsers")]
- Task CopyUpsToGroup([FormContent] CopyUserToGroupRequest request,
- [AppendHeader("Referer")] string referer = RelationApiConstant.CopyReferer);
+ ///
+ /// 批量拷贝关注up到某指定分组
+ ///
+ ///
+ ///
+ [AppendHeader("Origin", "https://space.bilibili.com")]
+ [HttpPost("/x/relation/tags/copyUsers")]
+ Task CopyUpsToGroup([FormContent] CopyUserToGroupRequest request,
+ [AppendHeader("Referer")] string referer = RelationApiConstant.CopyReferer);
- ///
- /// 修改关系
- ///
- ///
- [AppendHeader("Origin", "https://space.bilibili.com")]
- [HttpPost("/x/relation/modify")]
- Task ModifyRelation([FormContent] ModifyRelationRequest request,
- [AppendHeader("Referer")] string referer = RelationApiConstant.ModifyReferer);
- }
+ ///
+ /// 修改关系
+ ///
+ ///
+ [AppendHeader("Origin", "https://space.bilibili.com")]
+ [HttpPost("/x/relation/modify")]
+ Task ModifyRelation([FormContent] ModifyRelationRequest request,
+ [AppendHeader("Referer")] string referer = RelationApiConstant.ModifyReferer);
+}
- public enum FollowingsOrderType
- {
- ///
- /// 最常访问频率倒序
- ///
- [DefaultValue("attention")]
- AttentionDesc,
+public enum FollowingsOrderType
+{
+ ///
+ /// 最常访问频率倒序
+ ///
+ [DefaultValue("attention")]
+ AttentionDesc,
- ///
- /// 关注时间倒序
- ///
- [DefaultValue("")]
- TimeDesc
- }
+ ///
+ /// 关注时间倒序
+ ///
+ [DefaultValue("")]
+ TimeDesc
+}
- public class RelationApiConstant
- {
- ///
- /// GetTags接口中的Referer
- /// {0}为UserId
- ///
- public const string GetTagsReferer = "https://space.bilibili.com/{0}/fans/follow";
+public class RelationApiConstant
+{
+ ///
+ /// GetTags接口中的Referer
+ /// {0}为UserId
+ ///
+ public const string GetTagsReferer = "https://space.bilibili.com/{0}/fans/follow";
- ///
- /// CopyUpsToGroup接口中的Referer
- /// {0}为UserId
- ///
- public const string CopyReferer = "https://space.bilibili.com/{0}/fans/follow?tagid=-1";
+ ///
+ /// CopyUpsToGroup接口中的Referer
+ /// {0}为UserId
+ ///
+ public const string CopyReferer = "https://space.bilibili.com/{0}/fans/follow?tagid=-1";
- ///
- /// ModifyRelation接口种的Referer
- ///
- public const string ModifyReferer = "https://space.bilibili.com/{0}/fans/follow?tagid={1}";
- }
+ ///
+ /// ModifyRelation接口种的Referer
+ ///
+ public const string ModifyReferer = "https://space.bilibili.com/{0}/fans/follow?tagid={1}";
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IUserInfoApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IUserInfoApi.cs
index 11e717f02..53c6a24d8 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IUserInfoApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IUserInfoApi.cs
@@ -4,29 +4,28 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 用户信息接口API
+///
+[Header("Referer", "https://www.bilibili.com/")]
+[Header("Origin", "https://www.bilibili.com")]
+[Header("Host", "api.bilibili.com")]
+public interface IUserInfoApi : IBiliBiliApi
{
///
- /// 用户信息接口API
+ /// 登录
///
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [Header("Host", "api.bilibili.com")]
- public interface IUserInfoApi : IBiliBiliApi
- {
- ///
- /// 登录
- ///
- ///
- [HttpGet("/x/web-interface/nav")]
- Task> LoginByCookie();
+ ///
+ [HttpGet("/x/web-interface/nav")]
+ Task> LoginByCookie();
- ///
- /// 获取用户空间信息
- ///
- /// uid
- ///
- [HttpGet("/x/space/wbi/acc/info")]
- Task> GetSpaceInfo([PathQuery] GetSpaceInfoDto request);
- }
+ ///
+ /// 获取用户空间信息
+ ///
+ /// uid
+ ///
+ [HttpGet("/x/space/wbi/acc/info")]
+ Task> GetSpaceInfo([PathQuery] GetSpaceInfoDto request);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVideoApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVideoApi.cs
index 7a21a4215..ba266805b 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVideoApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVideoApi.cs
@@ -5,120 +5,119 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Video;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 视频相关接口
+///
+[Header("Host", "api.bilibili.com")]
+public interface IVideoApi : IBiliBiliApi
{
///
- /// 视频相关接口
+ /// 分享视频
///
- [Header("Host", "api.bilibili.com")]
- public interface IVideoApi : IBiliBiliApi
- {
- ///
- /// 分享视频
- ///
- ///
- /// ck中必须要有buvid3,否则几率性-403
- ///
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/web-interface/share/add")]
- Task ShareVideo([FormContent] ShareVideoRequest request);
+ ///
+ /// ck中必须要有buvid3,否则几率性-403
+ ///
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/web-interface/share/add")]
+ Task ShareVideo([FormContent] ShareVideoRequest request);
- ///
- /// 上传视频观看进度
- /// 每15秒上报一次
- ///
- ///
- //[Header("Content-Length", "186")]
- [Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")]
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/click-interface/web/heartbeat?aid={aid}&played_time={playedTime}")]
- Task UploadVideoHeartbeat([FormContent] UploadVideoHeartbeatRequest request);
+ ///
+ /// 上传视频观看进度
+ /// 每15秒上报一次
+ ///
+ ///
+ //[Header("Content-Length", "186")]
+ [Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")]
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/click-interface/web/heartbeat?aid={aid}&played_time={playedTime}")]
+ Task UploadVideoHeartbeat([FormContent] UploadVideoHeartbeatRequest request);
- #region 投币相关
- ///
- /// 为视频投币
- ///
- ///
- ///
- ///
- ///
- ///
- [Header("Content-Type", "application/x-www-form-urlencoded")]
- //[Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpPost("/x/web-interface/coin/add")]
- Task AddCoinForVideo([FormContent] AddCoinRequest request,[Header("referer")]string refer= "https://www.bilibili.com/video/BV123456/?spm_id_from=333.1007.tianma.1-1-1.click&vd_source=80c1601a7003934e7a90709c18dfcffd");
+ #region 投币相关
+ ///
+ /// 为视频投币
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ [Header("Content-Type", "application/x-www-form-urlencoded")]
+ //[Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpPost("/x/web-interface/coin/add")]
+ Task AddCoinForVideo([FormContent] AddCoinRequest request,[Header("referer")]string refer= "https://www.bilibili.com/video/BV123456/?spm_id_from=333.1007.tianma.1-1-1.click&vd_source=80c1601a7003934e7a90709c18dfcffd");
- ///
- /// 获取当前用户对视频的投币信息
- ///
- ///
- ///
- [Header("Referer", "https://www.bilibili.com/")]
- [HttpGet("/x/web-interface/archive/coins")]
- Task> GetDonatedCoinsForVideo(GetAlreadyDonatedCoinsRequest request);
- #endregion
-
- ///
- /// 搜索指定Up的视频列表
- ///
- ///
- /// [1,100]验证不通过接口会报异常
- ///
- ///
- ///
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://space.bilibili.com")]
- //[HttpGet("/x/space/wbi/arc/search?mid={upId}&ps={pageSize}&tid=0&pn={pageNumber}&keyword={keyword}&order=pubdate&platform=web&web_location=1550101&order_avoided=true&w_rid=5df06b1c48e2be86a96e9d0f99bf06f4&wts=1684854929")]
- [HttpGet("/x/space/wbi/arc/search")]
- Task> SearchVideosByUpId([PathQuery] SearchVideosByUpIdDto request);
+ ///
+ /// 获取当前用户对视频的投币信息
+ ///
+ ///
+ ///
+ [Header("Referer", "https://www.bilibili.com/")]
+ [HttpGet("/x/web-interface/archive/coins")]
+ Task> GetDonatedCoinsForVideo(GetAlreadyDonatedCoinsRequest request);
+ #endregion
+
+ ///
+ /// 搜索指定Up的视频列表
+ ///
+ ///
+ /// [1,100]验证不通过接口会报异常
+ ///
+ ///
+ ///
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://space.bilibili.com")]
+ //[HttpGet("/x/space/wbi/arc/search?mid={upId}&ps={pageSize}&tid=0&pn={pageNumber}&keyword={keyword}&order=pubdate&platform=web&web_location=1550101&order_avoided=true&w_rid=5df06b1c48e2be86a96e9d0f99bf06f4&wts=1684854929")]
+ [HttpGet("/x/space/wbi/arc/search")]
+ Task> SearchVideosByUpId([PathQuery] SearchVideosByUpIdDto request);
- ///
- /// 通过ssid获取番剧的具体信息
- ///
- ///
- ///
- [HttpGet("/pgc/view/web/season?season_id={ssid}")]
- Task GetBangumiBySsid(long ssid);
+ ///
+ /// 通过ssid获取番剧的具体信息
+ ///
+ ///
+ ///
+ [HttpGet("/pgc/view/web/season?season_id={ssid}")]
+ Task GetBangumiBySsid(long ssid);
- }
+}
+///
+/// 不需要传递Cookie的接口
+///
+public interface IVideoWithoutCookieApi : IVideoApi
+{
///
- /// 不需要传递Cookie的接口
+ /// 获取视频详情
///
- public interface IVideoWithoutCookieApi : IVideoApi
- {
- ///
- /// 获取视频详情
- ///
- ///
- ///
- [HttpGet("/x/web-interface/view?aid={aid}")]
- Task> GetVideoDetail(string aid);
+ ///
+ ///
+ [HttpGet("/x/web-interface/view?aid={aid}")]
+ Task> GetVideoDetail(string aid);
- ///
- /// 获取某分区下X日内排行榜
- ///
- ///
- ///
- ///
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [HttpGet("/x/web-interface/ranking/region?rid={rid}&day={day}")]
- [Obsolete]
- Task>> GetRegionRankingVideos(int rid, int day);
+ ///
+ /// 获取某分区下X日内排行榜
+ ///
+ ///
+ ///
+ ///
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [HttpGet("/x/web-interface/ranking/region?rid={rid}&day={day}")]
+ [Obsolete]
+ Task>> GetRegionRankingVideos(int rid, int day);
- ///
- /// 获取排行榜
- ///
- ///
- [Header("Referer", "https://www.bilibili.com/")]
- [Header("Origin", "https://www.bilibili.com")]
- [Header("dnt", "1")]
- [HttpGet("/x/web-interface/ranking/v2?rid=0&type=all")]
- Task> GetRegionRankingVideosV2();
+ ///
+ /// 获取排行榜
+ ///
+ ///
+ [Header("Referer", "https://www.bilibili.com/")]
+ [Header("Origin", "https://www.bilibili.com")]
+ [Header("dnt", "1")]
+ [HttpGet("/x/web-interface/ranking/v2?rid=0&type=all")]
+ Task> GetRegionRankingVideosV2();
- }
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs
index 223fee0be..8199b316b 100644
--- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs
+++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs
@@ -4,71 +4,61 @@
using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask;
using WebApiClientCore.Attributes;
-namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces
+namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces;
+
+///
+/// 大会员大积分
+///
+[Header("Host", "api.bilibili.com")]
+[Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
+[LogFilter]
+public interface IVipBigPointApi
{
///
- /// 大会员大积分
+ /// 获取任务列表
///
- [Header("Host", "api.bilibili.com")]
- [Header("User-Agent", "Mozilla/5.0 (Linux; Android 12; SM-S9080 Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 os/android model/SM-S9080 build/7760700 osVer/12 sdkInt/32 network/2 BiliApp/7760700 mobi_app/android channel/bili innerVer/7760710 c_locale/zh_CN s_locale/zh_CN disable_rcmd/0 7.76.0 os/android model/SM-S9080 mobi_app/android build/7760700 channel/bili innerVer/7760710 osVer/12 network/2")]
- [LogFilter]
- public interface IVipBigPointApi
- {
- ///
- /// 获取任务列表
- ///
- ///
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpGet("/x/vip_point/task/combine")]
- Task> GetTaskListAsync();
+ ///
+ [HttpGet("/x/vip_point/task/combine")]
+ Task> GetTaskListAsync();
- ///
- /// 签到任务
- ///
- ///
- ///
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/score/task/sign")]
- Task SignAsync([FormContent] SignRequest request);
+ ///
+ /// 签到任务
+ ///
+ ///
+ ///
+ [HttpPost("/pgc/activity/score/task/sign")]
+ Task SignAsync([FormContent] SignRequest request);
- ///
- /// 领取任务
- ///
- ///
- ///
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/score/task/receive")]
- Task Receive([JsonContent] ReceiveOrCompleteTaskRequest request);
+ ///
+ /// 领取任务
+ ///
+ ///
+ ///
+ [HttpPost("/pgc/activity/score/task/receive")]
+ Task Receive([JsonContent] ReceiveOrCompleteTaskRequest request);
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/score/task/receive/v2")]
- Task ReceiveV2([FormContent] ReceiveOrCompleteTaskRequest request);
+ [HttpPost("/pgc/activity/score/task/receive/v2")]
+ Task ReceiveV2([FormContent] ReceiveOrCompleteTaskRequest request);
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/score/task/complete")]
- Task CompleteAsync([JsonContent] ReceiveOrCompleteTaskRequest request);
+ [HttpPost("/pgc/activity/score/task/complete")]
+ Task CompleteAsync([JsonContent] ReceiveOrCompleteTaskRequest request);
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/score/task/complete/v2")]
- Task CompleteV2([FormContent] ReceiveOrCompleteTaskRequest request);
+ [HttpPost("/pgc/activity/score/task/complete/v2")]
+ Task CompleteV2([FormContent] ReceiveOrCompleteTaskRequest request);
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/pgc/activity/deliver/task/complete")]
- Task ViewComplete([FormContent] ViewRequest request);
+ [HttpPost("/pgc/activity/deliver/task/complete")]
+ Task ViewComplete([FormContent] ViewRequest request);
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpGet("/x/vip/privilege/my")]
- Task> GetVouchersInfoAsync();
+ [HttpGet("/x/vip/privilege/my")]
+ Task> GetVouchersInfoAsync();
- ///
- /// 兑换大会员经验
- ///
- ///
- ///
- [Header("Referer", "https://big.bilibili.com/mobile/bigPoint/task")]
- [HttpPost("/x/vip/experience/add")]
- Task ObtainVipExperienceAsync([FormContent] VipExperienceRequest request);
- }
+ ///
+ /// 兑换大会员经验
+ ///
+ ///
+ ///
+ [HttpPost("/x/vip/experience/add")]
+ Task ObtainVipExperienceAsync([FormContent] VipExperienceRequest request);
}
diff --git a/src/Ray.BiliBiliTool.Agent/BiliHosts.cs b/src/Ray.BiliBiliTool.Agent/BiliHosts.cs
new file mode 100644
index 000000000..e70d8d275
--- /dev/null
+++ b/src/Ray.BiliBiliTool.Agent/BiliHosts.cs
@@ -0,0 +1,13 @@
+namespace Ray.BiliBiliTool.Agent;
+
+public static class BiliHosts
+{
+ public const string Api = "https://api.bilibili.com";
+ public const string Show = "https://show.bilibili.com";
+ public const string Passport = "http://passport.bilibili.com";
+ public const string LiveTrace = "https://live-trace.bilibili.com";
+ public const string Www = "https://www.bilibili.com";
+ public const string Manga = "https://manga.bilibili.com";
+ public const string Account = "https://account.bilibili.com";
+ public const string Live = "https://api.live.bilibili.com";
+}
diff --git a/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs b/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs
index 4c21ccb53..f3edeb53f 100644
--- a/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs
+++ b/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs
@@ -55,29 +55,39 @@ public static IServiceCollection AddBiliBiliClientApi(this IServiceCollection se
.AddClasses(classes => classes.AssignableTo())
.AsSelf()
.WithTransientLifetime()
- );
+ );
- //服务
+ //服务
services.AddScoped();
//bilibli
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://manga.bilibili.com");
- services.AddBiliBiliClientApi("https://account.bilibili.com");
- services.AddBiliBiliClientApi("https://api.live.bilibili.com");
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://api.bilibili.com", false);
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("http://passport.bilibili.com", false);
- services.AddBiliBiliClientApi("https://live-trace.bilibili.com");
- services.AddBiliBiliClientApi("https://www.bilibili.com", false);
-
- // 添加注入
- services.AddBiliBiliClientApi("https://api.bilibili.com");
- services.AddBiliBiliClientApi("https://show.bilibili.com");
+ Action config = (sp, c) => {
+ c.DefaultRequestHeaders.Add("User-Agent", sp.GetRequiredService>().CurrentValue.UserAgent);
+ c.DefaultRequestHeaders.Add("Cookie", sp.GetRequiredService().ToString());
+ };
+ Action configApp = (sp, c) => {
+ c.DefaultRequestHeaders.Add("User-Agent", sp.GetRequiredService>().CurrentValue.UserAgentApp);
+ c.DefaultRequestHeaders.Add("Cookie", sp.GetRequiredService().ToString());
+ };
+
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+ services.AddBiliBiliClientApi(BiliHosts.Api, config);
+
+ services.AddBiliBiliClientApi(BiliHosts.Show, config);
+ services.AddBiliBiliClientApi(BiliHosts.Passport, config);
+ services.AddBiliBiliClientApi(BiliHosts.LiveTrace,config);
+ services.AddBiliBiliClientApi(BiliHosts.Www, config);
+ services.AddBiliBiliClientApi(BiliHosts.Manga, config);
+ services.AddBiliBiliClientApi(BiliHosts.Account, config);
+ services.AddBiliBiliClientApi(BiliHosts.Live, config);
+
+ services.AddBiliBiliClientApi(BiliHosts.Api, configApp);
+
//qinglong
var qinglongHost = configuration["QL_URL"] ?? "http://localhost:5600";
@@ -89,8 +99,7 @@ public static IServiceCollection AddBiliBiliClientApi(this IServiceCollection se
})
.ConfigureHttpClient((sp, c) =>
{
- c.DefaultRequestHeaders.Add("User-Agent",
- sp.GetRequiredService>().CurrentValue.UserAgent);
+ c.DefaultRequestHeaders.Add("User-Agent", sp.GetRequiredService>().CurrentValue.UserAgent);
})
.AddPolicyHandler(GetRetryPolicy());
@@ -104,7 +113,7 @@ public static IServiceCollection AddBiliBiliClientApi(this IServiceCollection se
///
///
///
- private static IServiceCollection AddBiliBiliClientApi(this IServiceCollection services, string host, bool withCookie = true)
+ private static IServiceCollection AddBiliBiliClientApi(this IServiceCollection services, string host, Action config)
where TInterface : class
{
var uri = new Uri(host);
@@ -114,21 +123,10 @@ private static IServiceCollection AddBiliBiliClientApi(this IService
o.HttpHost = uri;
o.UseDefaultUserAgent = false;
})
- .ConfigureHttpClient((sp, c) =>
- {
- c.DefaultRequestHeaders.Add("User-Agent",
- sp.GetRequiredService>().CurrentValue.UserAgent);
- })
+ .ConfigureHttpClient(config)
.AddHttpMessageHandler()
.AddPolicyHandler(GetRetryPolicy());
- if (withCookie)
- httpClientBuilder.ConfigureHttpClient((sp, c) =>
- {
- var ck = sp.GetRequiredService();
- c.DefaultRequestHeaders.Add("Cookie", ck.ToString());
- });
-
return services;
}
diff --git a/src/Ray.BiliBiliTool.Config/Options/SecurityOptions.cs b/src/Ray.BiliBiliTool.Config/Options/SecurityOptions.cs
index 389bbb83d..912d3518e 100644
--- a/src/Ray.BiliBiliTool.Config/Options/SecurityOptions.cs
+++ b/src/Ray.BiliBiliTool.Config/Options/SecurityOptions.cs
@@ -58,6 +58,11 @@ public List GetIntervalMethods()
/// 请求B站接口时头部传递的User-Agent
///
public string UserAgent { get; set; } = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.66 Safari/537.36 Edg/87.0.664.41";
+
+ ///
+ /// App请求B站接口时头部传递的User-Agent
+ ///
+ public string UserAgentApp { get; set; } = "Mozilla/5.0 (Linux; Android 12; SM-S9080 Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 os/android model/SM-S9080 build/7760700 osVer/12 sdkInt/32 network/2 BiliApp/7760700 mobi_app/android channel/bili innerVer/7760710 c_locale/zh_CN s_locale/zh_CN disable_rcmd/0 7.76.0 os/android model/SM-S9080 mobi_app/android build/7760700 channel/bili innerVer/7760710 osVer/12 network/2";
///
/// 代理
diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json
index a32a6fb5f..9474d8d46 100644
--- a/src/Ray.BiliBiliTool.Console/appsettings.json
+++ b/src/Ray.BiliBiliTool.Console/appsettings.json
@@ -57,6 +57,7 @@
"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/124.0.0.0 Safari/537.36 Edg/124.0.0.0", //请求B站接口时头部传递的User-Agent
+ "UserAgentApp": "Mozilla/5.0 (Linux; Android 12; SM-S9080 Build/V417IR; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/91.0.4472.114 Mobile Safari/537.36 os/android model/SM-S9080 build/7760700 osVer/12 sdkInt/32 network/2 BiliApp/7760700 mobi_app/android channel/bili innerVer/7760710 c_locale/zh_CN s_locale/zh_CN disable_rcmd/0 7.76.0 os/android model/SM-S9080 mobi_app/android build/7760700 channel/bili innerVer/7760710 osVer/12 network/2", //App请求B站接口时头部传递的User-Agent
"WebProxy": "" //代理,格式为http://host:port,如果有鉴权则为user:password@http://host:port
},
diff --git a/src/Ray.BiliBiliTool.Infrastructure/Cookie/CookieStrFactory.cs b/src/Ray.BiliBiliTool.Infrastructure/Cookie/CookieStrFactory.cs
index fe27534be..3224b33e4 100644
--- a/src/Ray.BiliBiliTool.Infrastructure/Cookie/CookieStrFactory.cs
+++ b/src/Ray.BiliBiliTool.Infrastructure/Cookie/CookieStrFactory.cs
@@ -32,7 +32,11 @@ public bool Any()
public Dictionary GetCurrentCookieDic()
{
- if (!Any()) throw new Exception($"第 {CurrentNum} 个cookie不存在");
+ if (!Any())
+ {
+ return new Dictionary(); //todo
+ //throw new Exception($"第 {CurrentNum} 个cookie不存在");
+ }
return _cookieDictionary[CurrentNum];
}
diff --git a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs
index 6ef931f55..6f72ea60a 100644
--- a/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs
+++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/ArticleApiTests.cs
@@ -135,10 +135,10 @@ public async Task LikeAsync_AlreadyLike_GetResultSuccess()
var re = await _api.LikeAsync(cvid, _ck.BiliJct);
// Assert
- re.Code.Should().BeOneOf(new List
- {
- 0,
- 65006, //已赞过
+ re.Code.Should().BeOneOf(new List
+ {
+ 0,
+ 65006, //已赞过
});
}
diff --git a/test/Ray.BiliBiliTool.Agent.FunctionalTests/VipBigPointApiTest.cs b/test/Ray.BiliBiliTool.Agent.FunctionalTests/VipBigPointApiTest.cs
index a9107751d..8c2092afa 100644
--- a/test/Ray.BiliBiliTool.Agent.FunctionalTests/VipBigPointApiTest.cs
+++ b/test/Ray.BiliBiliTool.Agent.FunctionalTests/VipBigPointApiTest.cs
@@ -88,10 +88,11 @@ public async Task GetVipExperienceAsync_Normal_Success()
BiliApiResponse re = await _api.ObtainVipExperienceAsync(req);
// Assert
- re.Code.Should().BeOneOf(new List
- {
- 0,
- 69198, //用户经验已经领取
+ re.Code.Should().BeOneOf(new List
+ {
+ 0,
+ 6034005, //任务未完成
+ 69198, //用户经验已经领取
});
}