diff --git a/CHANGELOG.md b/CHANGELOG.md index fc1962371..8c8d0f943 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -119,3 +119,5 @@ ## 2.0.1 - PR[#539]:更新文档 - PR[#557]:修复直播接口权限不足问题 +## 2.0.2 +- PR[#617]:增加专栏投币功能与领取大会员经验的功能 diff --git a/common.props b/common.props index 79e7c677e..74347ebbe 100644 --- a/common.props +++ b/common.props @@ -1,7 +1,7 @@ Ray - 2.0.1 + 2.0.2 $(NoWarn);CS1591;CS0436 diff --git a/docs/runInLocal.md b/docs/runInLocal.md index 01564856f..e7d3ed0df 100644 --- a/docs/runInLocal.md +++ b/docs/runInLocal.md @@ -35,6 +35,7 @@ P.S.这里的运行环境指的是 `.NET Runtime 6.0.0` ,安装方法可详见 请下载 `win-x86-x64.zip`,此文件已自包含(self-contained)运行环境。 解压后,在应用目录打开cmd或powershell,执行`.\Ray.BiliBiliTool.Console.exe --runTasks=Login`,扫码登录。 +也可以直接双击`Ray.BiliBiliTool.Console.exe`来运行,建议使用windows自带的定时任务来执行它 ## 3. Linux: diff --git a/krew/.gitignore b/krew/.gitignore new file mode 100644 index 000000000..45f4d8132 --- /dev/null +++ b/krew/.gitignore @@ -0,0 +1,2 @@ +bin +bilipro \ No newline at end of file diff --git a/krew/Makefile b/krew/Makefile index b18791ada..23f9d3c1f 100644 --- a/krew/Makefile +++ b/krew/Makefile @@ -20,18 +20,30 @@ help: #### display help deploy: build install #### build + install +.PHONY: fmt +fmt: #### run go fmt against code + @go fmt ./... + + +.PHONY: vet +vet: #### run go vet against code + @go vet ./... + +.PHONY: update-modules +update-modules: tidy #### update go modules + +.PHONY: tidy +tidy: #### run go mod tidy + @go mod tidy + .PHONY: build build: #### build the plugin - @go vet ./... && \ - go fmt ./... && \ - echo "build on ${GOOS}/${GOARCH}" && \ - cd ${ROOT_DIR}/krew/cmd && \ - GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 go build -ldflags "-X github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/cmd.Version=${GITCOMMIT}" -o $(BIN_NAME) kubectl-bilipro.go - + @echo "build on ${GOOS}/${GOARCH}" && \ + GOOS=${GOOS} GOARCH=${GOARCH} CGO_ENABLED=0 go build -mod readonly -ldflags "-X github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/cmd.version=${GITCOMMIT}" -o bin/$(BIN_NAME) cmd/kubectl-bilipro.go .PHONY: install install: #### install the plugin - @cd ${ROOT_DIR}/krew/cmd && \ + @cd ${ROOT_DIR}/krew/bin && \ sudo install ./$(BIN_NAME) ${KUBECTL_DIR}/$(BIN_NAME) .PHONY: test diff --git a/krew/README.md b/krew/README.md index f56318963..36697df11 100644 --- a/krew/README.md +++ b/krew/README.md @@ -18,15 +18,18 @@ For example: the kubectl is installed under `/usr/bin`, then put the bilibilipro ### Deployment && Update -Command: `kubectl bilipro init --config config.yaml [optional]--login` +Prerequsites: please make sure you have the right permission to at least manage namespaces/deployments + +Command: `kubectl bilipro init --config config.yaml` Creates Deployment with the needed environments. Optional Options: -- `--image=zai7lou/bilibili_tool_pro:1.0.1` +- `--image=zai7lou/bilibili_tool_pro:2.0.1` - `--namespace=bilipro` -- `--image-pull-secret=` +- `--image-pull-secret=` +- `--login` to scan QR code to login Required Options: diff --git a/krew/cmd/kubectl-bilipro.go b/krew/cmd/kubectl-bilipro.go index f9e3ca6ea..55256366e 100644 --- a/krew/cmd/kubectl-bilipro.go +++ b/krew/cmd/kubectl-bilipro.go @@ -1,6 +1,7 @@ package main import ( + "fmt" "os" "github.com/spf13/pflag" @@ -8,7 +9,6 @@ import ( "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/cmd" helper "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/utils" "k8s.io/cli-runtime/pkg/genericclioptions" - "k8s.io/klog/v2" ) func main() { @@ -17,7 +17,7 @@ func main() { cmd := cmd.NewExecutor(genericclioptions.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}) if err := cmd.Execute(); err != nil { - klog.Error(helper.GenErrorMsg(helper.SERVER_ERROR, err.Error()).Error()) + fmt.Println(helper.GenErrorMsg(helper.SERVER_ERROR, err.Error()).Error()) os.Exit(1) } } diff --git a/krew/go.mod b/krew/go.mod index 37d7d67a8..9f7fd48fa 100644 --- a/krew/go.mod +++ b/krew/go.mod @@ -9,7 +9,6 @@ require ( k8s.io/apimachinery v0.25.4 k8s.io/cli-runtime v0.25.4 k8s.io/client-go v0.25.4 - k8s.io/klog/v2 v2.80.1 sigs.k8s.io/kustomize/api v0.12.1 sigs.k8s.io/kustomize/kyaml v0.13.9 sigs.k8s.io/yaml v1.3.0 @@ -58,10 +57,11 @@ require ( gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect + k8s.io/klog/v2 v2.80.1 // indirect k8s.io/kube-openapi v0.0.0-20221012153701-172d655c2280 // indirect k8s.io/utils v0.0.0-20221107191617-1a15be271d1d // indirect sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect ) -replace github.com/RayWangQvQ/BiliBiliToolPro/krew => ../krew +// replace github.com/RayWangQvQ/BiliBiliToolPro/krew => ../krew diff --git a/krew/pkg/cmd/delete.go b/krew/pkg/cmd/delete.go index 9acbdf5f4..a291d4e27 100644 --- a/krew/pkg/cmd/delete.go +++ b/krew/pkg/cmd/delete.go @@ -1,6 +1,7 @@ package cmd import ( + "fmt" "io" "os/exec" "strings" @@ -9,8 +10,6 @@ import ( "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/yaml" - "k8s.io/klog/v2" - "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/options" helper "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/utils" "github.com/spf13/cobra" @@ -42,9 +41,10 @@ func newDeleteCmd(out io.Writer, errOut io.Writer) *cobra.Command { err := o.run(out) if err != nil { - klog.Error(err) + fmt.Println(err) return err } + fmt.Println("bilibili tool is removed from your cluster") return nil }, } diff --git a/krew/pkg/cmd/get.go b/krew/pkg/cmd/get.go index 162538ec0..15744cb20 100644 --- a/krew/pkg/cmd/get.go +++ b/krew/pkg/cmd/get.go @@ -1,11 +1,10 @@ package cmd import ( + "fmt" "io" "os/exec" - "k8s.io/klog/v2" - "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/options" helper "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/utils" "github.com/spf13/cobra" @@ -37,7 +36,7 @@ func newGetCmd(out io.Writer, errOut io.Writer) *cobra.Command { err := o.run(out) if err != nil { - klog.Error(err) + fmt.Println(err) return err } return nil diff --git a/krew/pkg/cmd/init.go b/krew/pkg/cmd/init.go index 21a80cf51..3a1f5ccd4 100644 --- a/krew/pkg/cmd/init.go +++ b/krew/pkg/cmd/init.go @@ -7,7 +7,6 @@ import ( "os" "os/exec" "strings" - "time" corev1 "k8s.io/api/core/v1" @@ -17,8 +16,6 @@ import ( "sigs.k8s.io/kustomize/api/types" - "k8s.io/klog/v2" - "github.com/spf13/cobra" "github.com/RayWangQvQ/BiliBiliToolPro/krew/pkg/options" @@ -52,7 +49,7 @@ func newInitCmd(out io.Writer, errOut io.Writer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { err := o.run(out) if err != nil { - klog.Error(err) + fmt.Println(err) return err } return nil @@ -60,7 +57,7 @@ func newInitCmd(out io.Writer, errOut io.Writer) *cobra.Command { } f := cmd.Flags() - f.StringVarP(&o.deployOpts.Image, "image", "i", "zai7lou/bilibili_tool_pro:1.0.1", "bilibilipro image") + f.StringVarP(&o.deployOpts.Image, "image", "i", "zai7lou/bilibili_tool_pro:2.0.1", "bilibilipro image") f.StringVarP(&o.deployOpts.Namespace, "namespace", "n", "bilipro", "namespace scope for this request") f.StringVar(&o.deployOpts.ImagePullSecret, "image-pull-secret", "", "image pull secret to be used for pulling bilibilipro image") f.StringVarP(&o.deployOpts.ConfigFilePath, "config", "c", "", "the config file contanis the environment variables") @@ -94,6 +91,8 @@ func (o *initCmd) run(writer io.Writer) error { } // TODO: All about paths are a little bit tricky should give it more thoughts + + fmt.Println("Creating the kustomization file") // if the bilibili tool is deployed under system/pre-defined namespace, ignore the namespace file var resources []string // nolint: go-staticcheck if o.deployOpts.Namespace == "default" || o.deployOpts.Namespace == "kube-system" || o.deployOpts.Namespace == "kube-public" { @@ -211,6 +210,7 @@ func (o *initCmd) run(writer io.Writer) error { } } + fmt.Println("Applying the kustomization file") // do kubectl apply // make sure kubectl is under your PATH cmd := exec.Command("kubectl", "apply", "-f", "-") @@ -219,9 +219,9 @@ func (o *initCmd) run(writer io.Writer) error { return err } - // if there is login required + // if there is login required, exectue the login command as the last step if o.login { - + fmt.Println("please login...") client, _, err := helper.GetK8sClient() if err != nil { return err @@ -233,8 +233,33 @@ func (o *initCmd) run(writer io.Writer) error { return err } - // TODO: Stupid way, just sleep to wait container is ready, maybe a watch is a better option - time.Sleep(15 * time.Second) + fmt.Println("wait for the deployment to be ready") + // Wait for the deployment ready + checkCmdArgs := []string{ + "rollout", + "status", + "deployment/bilibilipro", + "-n", + o.deployOpts.Namespace, + } + checkCmd := exec.Command("kubectl", checkCmdArgs...) + + for { + if err := checkCmd.Start(); err != nil { + fmt.Printf("deployment is not ready yet, current status: %v\n", err) + continue + } + + err := checkCmd.Wait() + if err == nil { + fmt.Printf("deployment is ready\n") + break + } + fmt.Printf("deployment is not ready yet, current status: %v\n", err) + } + + fmt.Println("please scan the QR code") + // Exec the login command args := []string{ "exec", podName, diff --git a/krew/pkg/cmd/version.go b/krew/pkg/cmd/version.go index 6a7b43f30..d0c85d860 100644 --- a/krew/pkg/cmd/version.go +++ b/krew/pkg/cmd/version.go @@ -4,8 +4,6 @@ import ( "fmt" "io" - "k8s.io/klog/v2" - "github.com/spf13/cobra" ) @@ -35,7 +33,7 @@ func newVersionCmd(out io.Writer, errOut io.Writer) *cobra.Command { RunE: func(cmd *cobra.Command, args []string) error { err := o.run() if err != nil { - klog.Error(err) + fmt.Println(err) return err } return nil diff --git a/krew/pkg/resources/base/bilibiliPro/deployment.yaml b/krew/pkg/resources/base/bilibiliPro/deployment.yaml index 7ec6d1343..97b8d89a3 100644 --- a/krew/pkg/resources/base/bilibiliPro/deployment.yaml +++ b/krew/pkg/resources/base/bilibiliPro/deployment.yaml @@ -13,7 +13,7 @@ spec: spec: containers: - name: bilibilipro - image: zai7lou/bilibili_tool_pro:1.0.1 + image: zai7lou/bilibili_tool_pro:2.0.1 imagePullPolicy: IfNotPresent resources: requests: diff --git a/krew/pkg/utils/client.go b/krew/pkg/utils/client.go index 7a220867b..81f058736 100644 --- a/krew/pkg/utils/client.go +++ b/krew/pkg/utils/client.go @@ -33,6 +33,8 @@ func GetK8sClient() (*kubernetes.Clientset, *rest.Config, error) { if err != nil { return nil, nil, GenErrorMsg(SERVER_ERROR, err.Error()) } + config.QPS = float32(10.0) + config.Burst = 20 // create the clientset clientset, err := kubernetes.NewForConfig(config) diff --git a/scripts/publish.ps1 b/scripts/publish.ps1 new file mode 100644 index 000000000..e21417b8c --- /dev/null +++ b/scripts/publish.ps1 @@ -0,0 +1,16 @@ +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime win-x86 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/win-x86 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime win-x64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/win-x64 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime win-arm64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/win-arm64 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime linux-x64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/linux-x64 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime linux-musl-x64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/linux-musl-x64 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime linux-arm64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/linux-arm64 +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime linux-arm --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/linux-arm +dotnet.exe publish ../src/Ray.BiliBiliTool.Console/Ray.BiliBiliTool.Console.csproj --runtime osx-x64 --no-self-contained -c Release -p:PublishSingleFile=true -o ./bin/Publish/osx-x64 +Remove-Item ./bin/Publish/win-x86/*.pdb +Remove-Item ./bin/Publish/win-x64/*.pdb +Remove-Item ./bin/Publish/win-arm64/*.pdb +Remove-Item ./bin/Publish/linux-x64/*.pdb +Remove-Item ./bin/Publish/linux-musl-x64/*.pdb +Remove-Item ./bin/Publish/linux-arm64/*.pdb +Remove-Item ./bin/Publish/linux-arm/*.pdb +Remove-Item ./bin/Publish/osx-x64/*.pdb diff --git a/scripts/publish.sh b/scripts/publish.sh index 22ef74fcd..74811d8e7 100644 --- a/scripts/publish.sh +++ b/scripts/publish.sh @@ -62,11 +62,10 @@ publish_dotnet_dependent() { dotnet publish --configuration Release \ --self-contained false \ -p:PublishSingleFile=true \ + -p:DebugType=None \ + -p:DebugSymbols=false \ -o $outputDir - echo "clear pdb files" - rm -rf $outputDir/*.pdb - echo "zip files..." cd $publishDir zip -q -r bilibili-tool-pro-v$version-dotnet-dependent.zip ./dotnet-dependent/* @@ -90,11 +89,10 @@ publish_self_contained() { --runtime $runtime \ -p:PublishTrimmed=true \ -p:PublishSingleFile=true \ + -p:DebugType=None \ + -p:DebugSymbols=false \ -o $outputDir - echo "clear pdb files" - rm -rf $outputDir/*.pdb - echo "zip files..." cd $publishDir zip -q -r bilibili-tool-pro-v$version-$runtime.zip ./$runtime/* diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/AddCoinForArticleRequest.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/AddCoinForArticleRequest.cs new file mode 100644 index 000000000..7fd3f3e9d --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/AddCoinForArticleRequest.cs @@ -0,0 +1,22 @@ +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; + +public class AddCoinForArticleRequest +{ + public AddCoinForArticleRequest(long cvid,long mid,string csrf) + { + Aid = cvid; + Upid = mid; + Csrf = csrf; + } + + public long Aid { get; set; } + + public long Upid { get; set; } + + public int Multiply { get; set; } = 1; + + // 必须为2 + public int Avtype { get; private set; } = 2; + + public string Csrf { get; set; } +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticleInfoResponse.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticleInfoResponse.cs new file mode 100644 index 000000000..22b9b37a6 --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticleInfoResponse.cs @@ -0,0 +1,10 @@ +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; + +public class SearchArticleInfoResponse +{ + public int Like { get; set; } + + public int Coin { get; set; } + + public long Mid { get; set; } +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticlesByUpIdFullFto.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticlesByUpIdFullFto.cs new file mode 100644 index 000000000..e4cae3b9b --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchArticlesByUpIdFullFto.cs @@ -0,0 +1,19 @@ +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; + +public class SearchArticlesByUpIdDto +{ + public long Mid { get; set; } + + public int Pn { get; set; } = 1; + + public int Ps { get; set; } = 30; + + public string Sort { get; set; } = "publish_time"; +} + +public class SearchArticlesByUpIdFullDto : SearchArticlesByUpIdDto +{ + public string w_rid { get; set; } + + public long wts { get; set; } +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchUpArticlesResponse.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchUpArticlesResponse.cs new file mode 100644 index 000000000..bef59b449 --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/Article/SearchUpArticlesResponse.cs @@ -0,0 +1,18 @@ +using System.Collections.Generic; + +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; + +public class SearchUpArticlesResponse +{ + public List Articles { get; set; } + public int Count { get; set; } + +} + +public class ArticleInfo +{ + public long Id { get; set; } + + public string Title { get; set; } + +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VipExperienceRequest.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VipExperienceRequest.cs new file mode 100644 index 000000000..542e6b083 --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VipExperienceRequest.cs @@ -0,0 +1,6 @@ +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask; + +public class VipExperienceRequest +{ + public string csrf { get; set; } +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VouchersInfoResponse.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VouchersInfoResponse.cs new file mode 100644 index 000000000..ae85e0fd8 --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Dtos/VipTask/VouchersInfoResponse.cs @@ -0,0 +1,28 @@ +using System.Collections.Generic; + +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask; + +public class VouchersInfoResponse +{ + public List List { get; set; } + public bool IsShortVip { get; set; } + public bool IsFreightOpen { get; set; } + public int Level { get; set; } + public int CurExp { get; set; } + public int NextExp { get; set; } + public bool IsVip { get; set; } + public int IsSeniorMember { get; set; } + public int Format060102 { get; set; } +} + + +public class List +{ + public int Type { get; set; } + public int State { get; set; } + public int ExpireTime { get; set; } + public int VipType { get; set; } + public int NextReceiveDays { get; set; } + public int PeriodEndUnix { get; set; } +} + diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs new file mode 100644 index 000000000..2019bb33b --- /dev/null +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IArticleApi.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Video; +using WebApiClientCore.Attributes; + +namespace Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces +{ + + [Header("Host", "api.bilibili.com")] + public interface IArticleApi : IBiliBiliApi + { + [Header("Content-Type", "application/x-www-form-urlencoded")] + [Header("Origin", "https://www.bilibili.com")] + [HttpPost("/x/web-interface/coin/add")] + Task AddCoinForArticle([FormContent] AddCoinForArticleRequest request, [Header("referer")] string refer = "https://www.bilibili.com/read/cv5806746/?from=search&spm_id_from=333.337.0.0"); + + + [Header("Referer", "https://www.bilibili.com/")] + [Header("Origin", "https://space.bilibili.com")] + [HttpGet("/x/space/wbi/article")] + Task> SearchUpArticlesByUpId( + [PathQuery] SearchArticlesByUpIdFullDto request); + + /// + /// 获取专栏详情 + /// + /// + /// + [HttpGet("/x/article/viewinfo?id={cvid}")] + Task> SearchArticleInfo(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 Like(long cvid, string csrf); + + } + + +} diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs index 903d5405c..7a851b2de 100644 --- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IMangaApi.cs @@ -26,8 +26,8 @@ public interface IMangaApi : IBiliBiliApi /// /// /// - [HttpPost("/twirp/bookshelf.v1.Bookshelf/AddHistory?platform={platform}&comic_id=27355&ep_id=381662")] - Task ReadManga(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); /// /// 获取会员漫画奖励 diff --git a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs index ecc0451da..f83122d74 100644 --- a/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs +++ b/src/Ray.BiliBiliTool.Agent/BiliBiliAgent/Interfaces/IVipBigPointApi.cs @@ -31,5 +31,12 @@ public interface IVipBigPointApi [HttpPost("/pgc/activity/deliver/task/complete")] Task ViewComplete([FormContent] ViewRequest request); + + [HttpGet("/x/vip/privilege/my")] + Task> GetVouchersInfo(); + + [Header("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")] + [HttpPost("/x/vip/experience/add")] + Task GetVipExperience([FormContent] VipExperienceRequest request); } } diff --git a/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs b/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs index 64558e390..92b8831c4 100644 --- a/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs +++ b/src/Ray.BiliBiliTool.Agent/Extensions/ServiceCollectionExtension.cs @@ -73,6 +73,9 @@ public static IServiceCollection AddBiliBiliClientApi(this IServiceCollection se services.AddBiliBiliClientApi("https://live-trace.bilibili.com"); services.AddBiliBiliClientApi("https://www.bilibili.com", false); + // 添加注入 + services.AddBiliBiliClientApi("https://api.bilibili.com"); + //qinglong var qinglongHost = configuration["QL_URL"] ?? "http://localhost:5600"; services diff --git a/src/Ray.BiliBiliTool.Application.Contracts/IVipBigPointAppService.cs b/src/Ray.BiliBiliTool.Application.Contracts/IVipBigPointAppService.cs index abd10b07f..f78097ef3 100644 --- a/src/Ray.BiliBiliTool.Application.Contracts/IVipBigPointAppService.cs +++ b/src/Ray.BiliBiliTool.Application.Contracts/IVipBigPointAppService.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.ComponentModel; using System.Text; +using System.Threading.Tasks; namespace Ray.BiliBiliTool.Application.Contracts { @@ -12,5 +13,6 @@ namespace Ray.BiliBiliTool.Application.Contracts public interface IVipBigPointAppService : IAppService { + Task VipExpress(); } } diff --git a/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs b/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs index 6f82e6d59..db2ee02f9 100644 --- a/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs +++ b/src/Ray.BiliBiliTool.Application/DailyTaskAppService.cs @@ -23,6 +23,7 @@ public class DailyTaskAppService : AppService, IDailyTaskAppService private readonly ILogger _logger; private readonly IAccountDomainService _accountDomainService; private readonly IVideoDomainService _videoDomainService; + private readonly IArticleDomainService _articleDomainService; private readonly IDonateCoinDomainService _donateCoinDomainService; private readonly IMangaDomainService _mangaDomainService; private readonly ILiveDomainService _liveDomainService; @@ -41,6 +42,7 @@ public DailyTaskAppService( IOptionsMonitor> dicOptions, IAccountDomainService accountDomainService, IVideoDomainService videoDomainService, + IArticleDomainService articleDomainService, IDonateCoinDomainService donateCoinDomainService, IMangaDomainService mangaDomainService, ILiveDomainService liveDomainService, @@ -56,6 +58,7 @@ public DailyTaskAppService( _expDic = dicOptions.Get(Constants.OptionsNames.ExpDictionaryName); _accountDomainService = accountDomainService; _videoDomainService = videoDomainService; + _articleDomainService = articleDomainService; _donateCoinDomainService = donateCoinDomainService; _mangaDomainService = mangaDomainService; _liveDomainService = liveDomainService; @@ -79,7 +82,8 @@ public override async Task DoTaskAsync(CancellationToken cancellationToken) DailyTaskInfo dailyTaskInfo = await GetDailyTaskStatus(); await WatchAndShareVideo(dailyTaskInfo); - await AddCoinsForVideo(userInfo); + + await AddCoins(userInfo); //签到: await LiveSign(); @@ -91,6 +95,9 @@ public override async Task DoTaskAsync(CancellationToken cancellationToken) await ReceiveVipPrivilege(userInfo); await ReceiveMangaVipReward(userInfo); + //TODO 大会员领经验 + + await Charge(userInfo); } @@ -124,7 +131,7 @@ protected async Task SetCookiesAsync(BiliCookie biliCookie, Cancella private async Task Login() { UserInfo userInfo = await _accountDomainService.LoginByCookie(); - if (userInfo == null) throw new Exception("登录失败,请检查Cookie");//终止流程 + if (userInfo == null) throw new Exception("登录失败,请检查Cookie"); //终止流程 _expDic.TryGetValue("每日登录", out int exp); _logger.LogInformation("登录成功,经验+{exp} √", exp); @@ -153,6 +160,7 @@ private async Task WatchAndShareVideo(DailyTaskInfo dailyTaskInfo) _logger.LogInformation("已配置为关闭,跳过任务"); return; } + await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); } @@ -160,14 +168,28 @@ private async Task WatchAndShareVideo(DailyTaskInfo dailyTaskInfo) /// 投币任务 /// [TaskInterceptor("投币", rethrowWhenException: false)] - private async Task AddCoinsForVideo(UserInfo userInfo) + private async Task AddCoins(UserInfo userInfo) { if (_dailyTaskOptions.SaveCoinsWhenLv6 && userInfo.Level_info.Current_level >= 6) { _logger.LogInformation("已经为LV6大佬,开始白嫖"); return; } - await _donateCoinDomainService.AddCoinsForVideos(); + + if (_dailyTaskOptions.IsDonateCoinForArticle) + { + _logger.LogInformation("专栏投币已开启"); + + if (!await _articleDomainService.AddCoinForArticles()) + { + _logger.LogInformation("专栏投币结束,转入视频投币"); + await _donateCoinDomainService.AddCoinsForVideos(); + } + } + else + { + await _donateCoinDomainService.AddCoinsForVideos(); + } } /// diff --git a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs index fd7a8c197..7d3d038ee 100644 --- a/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs +++ b/src/Ray.BiliBiliTool.Application/VipBigPointAppService.cs @@ -4,6 +4,7 @@ using System.Threading.Tasks; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; +using Ray.BiliBiliTool.Agent; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask; using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces; @@ -19,23 +20,81 @@ public class VipBigPointAppService : AppService, IVipBigPointAppService private readonly IConfiguration _configuration; private readonly IVipBigPointApi _vipApi; private readonly IAccountDomainService _loginDomainService; + private readonly IVideoDomainService _videoDomainService; + private readonly IAccountDomainService _accountDomainService; + private readonly BiliCookie _biliCookie; public VipBigPointAppService( IConfiguration configuration, ILogger logger, IVipBigPointApi vipApi, - IAccountDomainService loginDomainService - ) + IAccountDomainService loginDomainService, + IVideoDomainService videoDomainService, + BiliCookie biliCookie, IAccountDomainService accountDomainService) { _configuration = configuration; _logger = logger; _vipApi = vipApi; _loginDomainService = loginDomainService; + _videoDomainService = videoDomainService; + _biliCookie = biliCookie; + _accountDomainService = accountDomainService; } + public async Task VipExpress() + { + _logger.LogInformation("大会员经验领取任务开始"); + var re = await _vipApi.GetVouchersInfo(); + if (re.Code == 0) + { + var state = re.Data.List.Find(x => x.Type == 9).State; + + switch (state) + { + case 2: + _logger.LogInformation("大会员经验观看任务未完成"); + _logger.LogInformation("开始观看视频"); + // 观看视频,暂时没有好办法解决,先这样使着 + DailyTaskInfo dailyTaskInfo = await _accountDomainService.GetDailyTaskStatus(); + await _videoDomainService.WatchAndShareVideo(dailyTaskInfo); + // 跳转到未兑换,执行兑换任务 + goto case 0; + + case 1: + _logger.LogInformation("大会员经验已兑换"); + break; + + case 0: + _logger.LogInformation("大会员经验未兑换"); + //兑换api + var response = await _vipApi.GetVipExperience(new VipExperienceRequest() + { + csrf = _biliCookie.BiliJct + }); + if (response.Code != 0) + { + _logger.LogInformation("大会员经验领取失败,错误信息:{message}", response.Message); + break; + } + _logger.LogInformation("领取成功,经验+10 √"); + break; + + default: + _logger.LogDebug("大会员经验领取失败,未知错误"); + break; + } + + } + + } + + [TaskInterceptor("大会员大积分", TaskLevel.One)] public override async Task DoTaskAsync(CancellationToken cancellationToken) { + await VipExpress(); + + // TODO 解决taskInfo在一个任务出错后,后续的任务均会报空引用错误 var ui = await GetUserInfo(); if (ui.GetVipType() == VipType.None) @@ -66,7 +125,7 @@ public override async Task DoTaskAsync(CancellationToken cancellationToken) taskInfo = await ViewAnimate(taskInfo); //浏览影视频道页10秒 - taskInfo = await ViewFilmChannel(taskInfo); + // taskInfo = await ViewFilmChannel(taskInfo); //浏览会员购页面10秒 taskInfo = ViewVipMall(taskInfo); @@ -76,10 +135,12 @@ public override async Task DoTaskAsync(CancellationToken cancellationToken) //领取购买任务 taskInfo = await BuyVipVideo(taskInfo); - taskInfo = await BuyVipProduct(taskInfo); + // taskInfo = await BuyVipProduct(taskInfo); taskInfo = await BuyVipMall(taskInfo); - + taskInfo.LogInfo(_logger); + + } [TaskInterceptor("测试Cookie")] diff --git a/src/Ray.BiliBiliTool.Config/Constants.cs b/src/Ray.BiliBiliTool.Config/Constants.cs index 870682bbe..cc6448cd8 100644 --- a/src/Ray.BiliBiliTool.Config/Constants.cs +++ b/src/Ray.BiliBiliTool.Config/Constants.cs @@ -1,5 +1,4 @@ - -using System.Collections; +using System.Collections; using System.Collections.Generic; using System.Linq; @@ -35,26 +34,30 @@ public static class OptionsNames /// public static Dictionary GetExpDic() { - var dic = new Dictionary() + Dictionary dic = new() { {"每日登录", "5"}, {"每日观看视频", "5"}, {"每日分享视频", "5"}, {"每日投币", "10"} }; + + string buildKey(string key) => $"{OptionsNames.ExpDictionaryName}:{key}"; + return dic.Select(x => - new KeyValuePair($"{OptionsNames.ExpDictionaryName}:{x.Key}", x.Value)) + new KeyValuePair(buildKey(x.Key), x.Value)) .ToDictionary(k => k.Key, v => v.Value); } /// - /// 投币接口的data.code返回以下这些状态码,则可以继续尝试投币 - /// 如返回除这些之外的状态码,则终止投币流程,不进行无意义的尝试(比如返回-101:账号未登录;-102:账号被封停;-111:csrf校验失败等) + /// 投币接口的data.code返回以下这些状态码,则可以继续尝试投币 + /// 如返回除这些之外的状态码,则终止投币流程,不进行无意义的尝试 + /// (比如返回-101:账号未登录;-102:账号被封停;-111:csrf校验失败等) /// /// public static Dictionary GetDonateCoinCanContinueStatusDic() { - var dic = new Dictionary() + Dictionary dic = new() { {"0", "成功"}, {"-400", "请求错误"}, @@ -64,8 +67,11 @@ public static Dictionary GetDonateCoinCanContinueStatusDic() {"34004", "投币间隔太短"}, {"34005", "超过投币上限"} }; + + string buildKey(string key) => $"{OptionsNames.DonateCoinCanContinueStatusDictionaryName}:{key}"; + return dic.Select(x => - new KeyValuePair($"{OptionsNames.DonateCoinCanContinueStatusDictionaryName}:{x.Key}", x.Value)) + new KeyValuePair(buildKey(x.Key), x.Value)) .ToDictionary(k => k.Key, v => v.Value) ; } @@ -81,6 +87,7 @@ public static Dictionary GetCommandLineMappingsDic() {"--randomSleep","Security:RandomSleepMaxMin"}, {"--numberOfCoins", "DailyTaskConfig:NumberOfCoins"}, + {"--numberOfProtectedCoins", "DailyTaskConfig:NumberOfProtectedCoins"}, {"--saveCoinsWhenLv6", "DailyTaskConfig:SaveCoinsWhenLv6"}, {"--selectLike", "DailyTaskConfig:SelectLike"}, {"--supportUpIds", "DailyTaskConfig:SupportUpIds"}, diff --git a/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationProvider.cs b/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationProvider.cs index e6aaa0064..61dec6a96 100644 --- a/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationProvider.cs +++ b/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationProvider.cs @@ -8,7 +8,7 @@ namespace Ray.BiliBiliTool.Config { /// - /// 自定义的排除空值的环境变量提供者 + /// 自定义的排除空值的环境变量提供者 /// (使用GitHub Actions的脚本传入环境变量,空值会保留,所以这里自己写了一个用来替换掉默认的) /// public class EnvironmentVariablesExcludeEmptyConfigurationProvider : EnvironmentVariablesConfigurationProvider @@ -19,7 +19,10 @@ public class EnvironmentVariablesExcludeEmptyConfigurationProvider : Environment private readonly Func, bool> _removeNullValue; private readonly Func, bool> _fifter; - public EnvironmentVariablesExcludeEmptyConfigurationProvider(string prefix = null, bool removeKeyPrefix = true) : base(prefix) + public EnvironmentVariablesExcludeEmptyConfigurationProvider( + string prefix = null, + bool removeKeyPrefix = true) + : base(prefix) { _removeKeyPrefix = removeKeyPrefix; _prefix = prefix ?? string.Empty; @@ -46,7 +49,8 @@ public override void Load() /// private string NormalizeKey(string key) { - if(_removeKeyPrefix) key = RemoveKeyPrefix(key); + if (_removeKeyPrefix) + key = RemoveKeyPrefix(key); key = ReplaceKeyDelimiter(key); return key; } diff --git a/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationSource.cs b/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationSource.cs index fea853940..4d553edfc 100644 --- a/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationSource.cs +++ b/src/Ray.BiliBiliTool.Config/EnvironmentVariablesExcludeEmptyConfigurationSource.cs @@ -1,15 +1,10 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Configuration.EnvironmentVariables; namespace Ray.BiliBiliTool.Config { /// - /// 自定义的排除空值的环境变量配置源 + /// 自定义的排除空值的环境变量配置源 /// (用于取待默认的) /// public class EnvironmentVariablesExcludeEmptyConfigurationSource : IConfigurationSource diff --git a/src/Ray.BiliBiliTool.Config/Options/DailyTaskOptions.cs b/src/Ray.BiliBiliTool.Config/Options/DailyTaskOptions.cs index da828c8e7..810562797 100644 --- a/src/Ray.BiliBiliTool.Config/Options/DailyTaskOptions.cs +++ b/src/Ray.BiliBiliTool.Config/Options/DailyTaskOptions.cs @@ -18,17 +18,26 @@ public class DailyTaskOptions /// public bool IsShareVideo { get; set; } + /// + /// 是否开启专栏投币模式 + /// + public bool IsDonateCoinForArticle { get; set; } + /// /// 每日设定的投币数 [0,5] /// public int NumberOfCoins { get; set; } = 5; + /// + /// 要保留的硬币数量 [0,int_max] + /// + public int NumberOfProtectedCoins { get; set; } = 0; + /// /// 达到六级后是否开始白嫖 /// public bool SaveCoinsWhenLv6 { get; set; } = false; - /// /// 投币时是否点赞[false,true] /// @@ -50,6 +59,7 @@ public class DailyTaskOptions public string AutoChargeUpId { get; set; } private string _chargeComment; + /// /// 充电后留言 /// @@ -77,16 +87,26 @@ public string ChargeComment /// public string DevicePlatform { get; set; } = "android"; + /// + /// 自定义漫画阅读 comic_id + /// + public long CustomComicId { get; set; } = 27355; + + /// + /// 自定义漫画阅读 ep_id + /// + public long CustomEpId { get; set; } = 381662; public List SupportUpIdList { get { - var re = new List(); - if (string.IsNullOrWhiteSpace(SupportUpIds) | SupportUpIds == "-1") return re; + List re = new(); + if (string.IsNullOrWhiteSpace(SupportUpIds) | SupportUpIds == "-1") + return re; - var array = SupportUpIds.Split(','); - foreach (var item in array) + string[] array = SupportUpIds.Split(','); + foreach (string item in array) { if (long.TryParse(item.Trim(), out long upId)) re.Add(upId); diff --git a/src/Ray.BiliBiliTool.Console/BiliBiliToolHostedService.cs b/src/Ray.BiliBiliTool.Console/BiliBiliToolHostedService.cs index 5bbd4e513..40741ed87 100644 --- a/src/Ray.BiliBiliTool.Console/BiliBiliToolHostedService.cs +++ b/src/Ray.BiliBiliTool.Console/BiliBiliToolHostedService.cs @@ -45,25 +45,25 @@ IHostApplicationLifetime applicationLifetime public async Task StartAsync(CancellationToken cancellationToken) { - var isNotifySingle = _configuration.GetSection("Notification:IsSingleAccountSingleNotify").Get(); + bool isNotifySingle = _configuration.GetSection("Notification:IsSingleAccountSingleNotify").Get(); try { _logger.LogInformation("BiliBiliToolPro 开始运行...{newLine}", Environment.NewLine); - var pass = await PreCheckAsync(cancellationToken); - if (!pass) return; + bool pass = await PreCheckAsync(cancellationToken); + if (!pass) + return; await RandomSleepAsync(cancellationToken); - var tasks = await ReadTargetTasksAsync(cancellationToken); + string[] tasks = await ReadTargetTasksAsync(cancellationToken); _logger.LogInformation("【目标任务】{tasks}", string.Join(",", tasks)); if (tasks.Contains("Login")) { await DoTasksAsync(tasks, cancellationToken); } - else { for (int i = 0; i < _cookieStrFactory.Count; i++) @@ -78,7 +78,7 @@ public async Task StartAsync(CancellationToken cancellationToken) { LogAppInfo(); - var accountName = _cookieStrFactory.Count > 1 ? $"账号【{_cookieStrFactory.CurrentNum}】" : ""; + string accountName = _cookieStrFactory.Count > 1 ? $"账号【{_cookieStrFactory.CurrentNum}】" : ""; _logger.LogInformation("·开始推送·{task}·{user}", $"{_configuration["RunTasks"]}任务", accountName); } } @@ -134,7 +134,8 @@ private Task PreCheckAsync(CancellationToken cancellationToken) private async Task RandomSleepAsync(CancellationToken cancellationToken) { - if (_configuration["RunTasks"].Contains("Login") || _configuration["RunTasks"].Contains("Test")) return; + if (_configuration["RunTasks"].Contains("Login") || _configuration["RunTasks"].Contains("Test")) + return; if (_securityOptions.RandomSleepMaxMin > 0) { @@ -144,9 +145,14 @@ private async Task RandomSleepAsync(CancellationToken cancellationToken) } } + /// + /// 读取目标任务 + /// + /// + /// private Task ReadTargetTasksAsync(CancellationToken cancellationToken) { - var tasks = _configuration["RunTasks"] + string[] tasks = _configuration["RunTasks"] .Split("&", options: StringSplitOptions.RemoveEmptyEntries); if (tasks.Any()) { @@ -159,11 +165,11 @@ private Task ReadTargetTasksAsync(CancellationToken cancellationToken) while (true) { - var index = System.Console.ReadLine(); - var suc = int.TryParse(index, out int num); + string index = System.Console.ReadLine(); + bool suc = int.TryParse(index, out int num); if (suc) { - var code = TaskTypeFactory.GetCodeByIndex(num); + string code = TaskTypeFactory.GetCodeByIndex(num); _configuration["RunTasks"] = code; return Task.FromResult(new string[] { code }); } @@ -174,17 +180,17 @@ private Task ReadTargetTasksAsync(CancellationToken cancellationToken) private async Task DoTasksAsync(string[] tasks, CancellationToken cancellationToken) { - using var scope = _serviceProvider.CreateScope(); - foreach (var task in tasks) + using IServiceScope scope = _serviceProvider.CreateScope(); + foreach (string task in tasks) { - var type = TaskTypeFactory.Create(task); + Type type = TaskTypeFactory.Create(task); if (type == null) { _logger.LogWarning("任务不存在:{task}", task); continue; } - var appService = (IAppService)scope.ServiceProvider.GetRequiredService(type); + IAppService appService = (IAppService)scope.ServiceProvider.GetRequiredService(type); await appService?.DoTaskAsync(cancellationToken); } } diff --git a/src/Ray.BiliBiliTool.Console/Program.cs b/src/Ray.BiliBiliTool.Console/Program.cs index 7dc7ce0a1..0e3da4a4a 100644 --- a/src/Ray.BiliBiliTool.Console/Program.cs +++ b/src/Ray.BiliBiliTool.Console/Program.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.IO; using System.Reflection; using System.Threading.Tasks; using Microsoft.Extensions.Configuration; @@ -56,7 +54,8 @@ internal static IHostBuilder CreateHostBuilder(string[] args) //hostBuilder.UseContentRoot(Directory.GetCurrentDirectory()); - //承载系统自身的配置: + #region 承载系统自身的配置 + hostBuilder.ConfigureHostConfiguration(hostConfigurationBuilder => { hostConfigurationBuilder.AddEnvironmentVariables(prefix: "DOTNET_"); @@ -67,22 +66,26 @@ internal static IHostBuilder CreateHostBuilder(string[] args) } }); - //应用配置: + #endregion 承载系统自身的配置 + + #region 应用配置 + hostBuilder.ConfigureAppConfiguration((hostBuilderContext, configurationBuilder) => { Global.HostingEnvironment = hostBuilderContext.HostingEnvironment; IHostEnvironment env = hostBuilderContext.HostingEnvironment; //json文件: + string envName = hostBuilderContext.HostingEnvironment.EnvironmentName; configurationBuilder.AddJsonFile("appsettings.json", true, true) - .AddJsonFile($"appsettings.{hostBuilderContext.HostingEnvironment.EnvironmentName}.json", true, true) + .AddJsonFile($"appsettings.{envName}.json", true, true) ; //用户机密: if (env.IsDevelopment() && env.ApplicationName?.Length > 0) { //var appAssembly = Assembly.Load(new AssemblyName(env.ApplicationName)); - var appAssembly = Assembly.GetAssembly(typeof(Program)); + Assembly appAssembly = Assembly.GetAssembly(typeof(Program)); configurationBuilder.AddUserSecrets(appAssembly, optional: true, reloadOnChange: true); } @@ -104,16 +107,23 @@ internal static IHostBuilder CreateHostBuilder(string[] args) configurationBuilder.AddInMemoryCollection(Config.Constants.GetDonateCoinCanContinueStatusDic()); }); - //日志: + #endregion 应用配置 + + #region 日志 + hostBuilder.ConfigureLogging((hostBuilderContext, loggingBuilder) => { Log.Logger = new LoggerConfiguration() .ReadFrom.Configuration(hostBuilderContext.Configuration) .CreateLogger(); SelfLog.Enable(x => System.Console.WriteLine(x ?? "")); - }).UseSerilog(); + }) + .UseSerilog(); + + #endregion 日志 + + #region DI容器 - //DI容器: hostBuilder.ConfigureServices((hostContext, services) => { Global.ConfigurationRoot = (IConfigurationRoot)hostContext.Configuration; @@ -126,9 +136,14 @@ internal static IHostBuilder CreateHostBuilder(string[] args) services.AddAppServices(); }); + #endregion DI容器 + return hostBuilder; } + /// + /// 输出本工具启动logo + /// private static void PrintLogo() { System.Console.WriteLine(@" ____ ____ _ _____ _ "); diff --git a/src/Ray.BiliBiliTool.Console/appsettings.json b/src/Ray.BiliBiliTool.Console/appsettings.json index 89740733a..d92fc1e05 100644 --- a/src/Ray.BiliBiliTool.Console/appsettings.json +++ b/src/Ray.BiliBiliTool.Console/appsettings.json @@ -6,7 +6,9 @@ "Cron": "0 15 * * *", "IsWatchVideo": true, //是否观看视频 "IsShareVideo": true, //是否分享视频 + "IsDonateCoinForArticle": false, "NumberOfCoins": 5, //每日设定的投币数 [0,5] + "NumberOfProtectedCoins": 0, // 要保留的硬币数量 [0,int_max],0 为不保留,int_max 通常取 (2^31)-1 "SaveCoinsWhenLv6": false, //达到六级后是否开始白嫖[false,true] "SelectLike": true, //投币时是否同时点赞[false,true] "SupportUpIds": "", //优先选择支持的up主Id集合,多个以英文逗号分隔,如:"123,456"。配置后会优先从指定的up主下挑选视频进行观看、分享和投币,不配置或配置为-1则表示没有特别支持的up,会从关注和排行耪中随机获取支持视频 @@ -15,7 +17,9 @@ "ChargeComment": "", //充电后留言 "DayOfReceiveVipPrivilege": 1, //每月几号自动领取会员权益的[-1,31],-1表示不指定,默认每月1号;0表示不自动领取 "DayOfExchangeSilver2Coin": 0, //每月几号执行银瓜子兑换硬币[-1,31],-1表示不指定,默认每月最后一天;-2表示每天;0表示不进行兑换 - "DevicePlatform": "android" //执行客户端操作时的平台 [ios,android] + "DevicePlatform": "android", //执行客户端操作时的平台 [ios,android] + "CustomComicId": 27355, //自定义漫画阅读 comic_id,若不清楚含义请勿修改 + "CustomEpId": 381662 //自定义漫画阅读 ep_id,若不清楚含义请勿修改 }, "LiveLotteryTaskConfig": { diff --git a/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs b/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs index efa7f6e68..e6d12dae5 100644 --- a/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/AccountDomainService.cs @@ -25,6 +25,7 @@ public class AccountDomainService : IAccountDomainService private readonly IRelationApi _relationApi; private readonly UnfollowBatchedTaskOptions _unfollowBatchedTaskOptions; private readonly BiliCookie _cookie; + private readonly DailyTaskOptions _dailyTaskOptions; public AccountDomainService( ILogger logger, @@ -32,14 +33,15 @@ public AccountDomainService( BiliCookie cookie, IUserInfoApi userInfoApi, IRelationApi relationApi, - IOptionsMonitor unfollowBatchedTaskOptions - ) + IOptionsMonitor unfollowBatchedTaskOptions, + IOptionsMonitor dailyTaskOptions) { _logger = logger; _dailyTaskApi = dailyTaskApi; _cookie = cookie; _userInfoApi = userInfoApi; _relationApi = relationApi; + _dailyTaskOptions = dailyTaskOptions.CurrentValue; _unfollowBatchedTaskOptions = unfollowBatchedTaskOptions.CurrentValue; } @@ -66,9 +68,9 @@ public async Task LoginByCookie() if (useInfo.Level_info.Current_level < 6) { - _logger.LogInformation("【距升级Lv{0}】{1}天(如每日做满65点经验)", + _logger.LogInformation("【距升级Lv{0}】预计{1}天", useInfo.Level_info.Current_level + 1, - (useInfo.Level_info.GetNext_expLong() - useInfo.Level_info.Current_exp) / Constants.EveryDayExp); + CalculateUpgradeTime(useInfo)); } else { @@ -216,5 +218,42 @@ private async Task GetTag(string groupName) TagDto tag = tagList.FirstOrDefault(x => x.Name == groupName); return tag; } + + /// + /// 计算升级时间 + /// + /// + /// 升级时间 + public int CalculateUpgradeTime(UserInfo useInfo) + { + double availableCoins = decimal.ToDouble(useInfo.Money ?? 0) - _dailyTaskOptions.NumberOfProtectedCoins; + long needExp = useInfo.Level_info.GetNext_expLong() - useInfo.Level_info.Current_exp; + int needDay; + + if (availableCoins < 0) + needDay = (int)((double)needExp / 25 + _dailyTaskOptions.NumberOfProtectedCoins - Math.Abs(availableCoins)); + + switch (_dailyTaskOptions.NumberOfCoins) + { + case 0: + needDay = (int)(needExp / 15); + break; + case 1: + needDay = (int)(needExp / 25); + break; + default: + int dailyExpAvailable = 15 + _dailyTaskOptions.NumberOfCoins * 10; + double needFrontDay = availableCoins / (_dailyTaskOptions.NumberOfCoins - 1); + + if ((double)needExp / dailyExpAvailable > needFrontDay) + needDay = (int)(needFrontDay + (needExp - dailyExpAvailable * needFrontDay) / 25); + else + needDay= (int)(needExp / dailyExpAvailable ); + break; + } + + return needDay; + } + } } diff --git a/src/Ray.BiliBiliTool.DomainService/ArticleDomainService.cs b/src/Ray.BiliBiliTool.DomainService/ArticleDomainService.cs new file mode 100644 index 000000000..bda778dba --- /dev/null +++ b/src/Ray.BiliBiliTool.DomainService/ArticleDomainService.cs @@ -0,0 +1,395 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Security.Cryptography; +using System.Threading.Tasks; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Options; +using Polly; +using Ray.BiliBiliTool.Agent; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.Article; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces; +using Ray.BiliBiliTool.Config.Options; +using Ray.BiliBiliTool.DomainService.Interfaces; + +namespace Ray.BiliBiliTool.DomainService; + +public class ArticleDomainService : IArticleDomainService +{ + private readonly IArticleApi _articleApi; + private readonly BiliCookie _biliCookie; + private readonly ILogger _logger; + private readonly DailyTaskOptions _dailyTaskOptions; + private readonly ICoinDomainService _coinDomainService; + private readonly IAccountApi _accountApi; + private readonly IWbiDomainService _wbiDomainService; + + + /// + /// up的专栏总数缓存 + /// + private readonly Dictionary _upArticleCountDicCatch = new(); + + /// + /// 已对投币数量缓存 + /// + private readonly Dictionary _alreadyDonatedCoinCountCatch = new(); + + public ArticleDomainService( + IArticleApi articleApi, + BiliCookie biliCookie, + ILogger logger, + IOptionsMonitor dailyTaskOptions, + ICoinDomainService coinDomainService, + IAccountApi accountApi, IWbiDomainService wbiDomainService) + { + _articleApi = articleApi; + _biliCookie = biliCookie; + _logger = logger; + _coinDomainService = coinDomainService; + _accountApi = accountApi; + _wbiDomainService = wbiDomainService; + _dailyTaskOptions = dailyTaskOptions.CurrentValue; + } + + + + public async Task LikeArticle(long cvid) + { + await _articleApi.Like(cvid, _biliCookie.BiliJct); + } + + /// + /// 投币专栏任务 + /// + /// + public async Task AddCoinForArticles() + { + + var donateCoinsCounts = await CalculateDonateCoinsCounts(); + + if (donateCoinsCounts == 0) + { + // 没有可投的币相当于投币任务全部完成 + return true; + } + + + int success = 0; + int tryCount = 10; + + for (int i = 0; i <= tryCount && success < donateCoinsCounts; i++) + { + _logger.LogDebug("开始尝试第{num}次", i); + + var upId = GetUpFromConfigUps(); + var cvid = await GetRandomArticleFromUp(upId); + if (upId == 0 || cvid == 0) + { + _logger.LogInformation("未添加支持的Up主,任务跳过"); + return false; + } + + if (await AddCoinForArticle(cvid, upId)) + { + // 点赞 + if (_dailyTaskOptions.SelectLike) + { + await LikeArticle(cvid); + _logger.LogInformation("文章点赞成功"); + } + success++; + } + + + } + + if (success == donateCoinsCounts) + _logger.LogInformation("专栏投币任务完成"); + else + { + _logger.LogInformation("投币尝试超过10次,已终止"); + return false; + } + + + _logger.LogInformation("【硬币余额】{coin}", (await _accountApi.GetCoinBalance()).Data.Money ?? 0); + + return true; + } + + + /// + /// 给某一篇专栏投币 + /// + /// 文章cvid + /// 文章作者mid + /// 投币是否成功(false 投币失败,true 投币成功) + public async Task AddCoinForArticle(long cvid, long mid) + { + BiliApiResponse result; + try + { + var refer = $"https://www.bilibili.com/read/cv{cvid}/?from=search&spm_id_from=333.337.0.0"; + result = await _articleApi.AddCoinForArticle(new AddCoinForArticleRequest(cvid, mid, _biliCookie.BiliJct), + refer); + } + catch (Exception) + { + return false; + } + + if (result.Code == 0) + { + _logger.LogInformation("投币成功,经验+10 √"); + return true; + } + else + { + _logger.LogError("投币错误 {message}", result.Message); + return false; + } + } + + + #region private + + /// + /// 从某个up主中随机挑选一个专栏 + /// + /// + /// 专栏的cvid + private async Task GetRandomArticleFromUp(long mid) + { + if (!_upArticleCountDicCatch.TryGetValue(mid, out int articleCount)) + { + articleCount = await GetArticleCountOfUp(mid); + _upArticleCountDicCatch.Add(mid, articleCount); + } + + // 专栏数为0时 + if (articleCount == 0) + { + return 0; + } + + var req = new SearchArticlesByUpIdDto() + { + Mid = mid, + Ps = 1, + Pn = new Random().Next(1, articleCount + 1) + }; + var w_ridDto = await _wbiDomainService.GetWridAsync(req); + + var fullDto = new SearchArticlesByUpIdFullDto() + { + Mid = mid, + Ps = req.Ps, + Pn = req.Pn, + w_rid = w_ridDto.w_rid, + wts = w_ridDto.wts + }; + + BiliApiResponse re = await _articleApi.SearchUpArticlesByUpId(fullDto); + + if (re.Code != 0) + { + throw new Exception(re.Message); + } + + ArticleInfo articleInfo = re.Data.Articles.FirstOrDefault(); + + _logger.LogDebug("获取到的专栏{cvid}({title})", articleInfo.Id, articleInfo.Title); + + // 检查是否可投 + if (!await IsCanDonate(articleInfo.Id)) + { + return 0; + } + + return articleInfo.Id; + } + + + // TODO 转变为异步代码 + /// + /// 从支持UP主列表中随机挑选一位 + /// + /// 被挑选up主的mid + private long GetUpFromConfigUps() + { + if (_dailyTaskOptions.SupportUpIdList == null || _dailyTaskOptions.SupportUpIdList.Count == 0) + { + return 0; + } + + try + { + long randomUpId = + _dailyTaskOptions.SupportUpIdList[new Random().Next(0, _dailyTaskOptions.SupportUpIdList.Count)]; + + if (randomUpId is 0 or long.MinValue) return 0; + + if (randomUpId.ToString() == _biliCookie.UserId) + { + _logger.LogDebug("不能为自己投币"); + return 0; + } + _logger.LogDebug("挑选出的up主为{UpId}",randomUpId); + return randomUpId; + } + catch (Exception e) + { + _logger.LogWarning("异常:{msg}", e); + } + + return 0; + } + + /// + /// 获取Up主专栏总数 + /// + /// up主mid + /// 专栏总数 + /// + private async Task GetArticleCountOfUp(long mid) + { + var req = new SearchArticlesByUpIdDto() + { + Mid = mid + }; + + var w_ridDto = await _wbiDomainService.GetWridAsync(req); + + var fullDto = new SearchArticlesByUpIdFullDto() + { + Mid = mid, + w_rid = w_ridDto.w_rid, + wts = w_ridDto.wts + }; + + BiliApiResponse re = await _articleApi.SearchUpArticlesByUpId(fullDto); + + if (re.Code != 0) + { + throw new Exception(re.Message); + } + + return re.Data.Count; + } + + /// + /// 计算所需要投的硬币数量 + /// + /// 硬币数量 + private async Task CalculateDonateCoinsCounts() + { + int needCoins = await GetNeedDonateCoinCounts(); + + int protectedCoins = _dailyTaskOptions.NumberOfProtectedCoins; + if (needCoins <= 0) return 0; + + //投币前硬币余额 + decimal coinBalance = await _coinDomainService.GetCoinBalance(); + _logger.LogInformation("【投币前余额】 : {coinBalance}", coinBalance); + _ = int.TryParse(decimal.Truncate(coinBalance - protectedCoins).ToString(), out int unprotectedCoins); + + if (coinBalance <= 0) + { + _logger.LogInformation("因硬币余额不足,今日暂不执行投币任务"); + return 0; + } + + if (coinBalance <= protectedCoins) + { + _logger.LogInformation("因硬币余额达到或低于保留值,今日暂不执行投币任务"); + return 0; + } + + //余额小于目标投币数,按余额投 + if (coinBalance < needCoins) + { + _ = int.TryParse(decimal.Truncate(coinBalance).ToString(), out needCoins); + _logger.LogInformation("因硬币余额不足,目标投币数调整为: {needCoins}", needCoins); + return needCoins; + } + + //投币后余额小于等于保护值,按保护值允许投 + if (coinBalance - needCoins <= protectedCoins) + { + //排除需投等于保护后可投数量相等时的情况 + if (unprotectedCoins != needCoins) + { + needCoins = unprotectedCoins; + _logger.LogInformation("因硬币余额投币后将达到或低于保留值,目标投币数调整为: {needCoins}", needCoins); + return needCoins; + } + } + + return needCoins; + } + + private async Task GetNeedDonateCoinCounts() + { + int configCoins = _dailyTaskOptions.NumberOfCoins; + + if (configCoins <= 0) + { + _logger.LogInformation("已配置为跳过投币任务"); + return configCoins; + } + + //已投的硬币 + int alreadyCoins = await _coinDomainService.GetDonatedCoins(); + + int targetCoins = configCoins; + + _logger.LogInformation("【今日已投】{already}枚", alreadyCoins); + _logger.LogInformation("【目标欲投】{already}枚", targetCoins); + + if (targetCoins > alreadyCoins) + { + int needCoins = targetCoins - alreadyCoins; + _logger.LogInformation("【还需再投】{need}枚", needCoins); + return needCoins; + } + + _logger.LogInformation("已完成投币任务,不需要再投啦~"); + return 0; + } + + + private async Task IsCanDonate(long cvid) + { + try + { + if (_alreadyDonatedCoinCountCatch.Any(x => x.Key == cvid.ToString())) + { + _logger.LogDebug("重复专栏,丢弃处理"); + return false; + } + + if (!_alreadyDonatedCoinCountCatch.TryGetValue(cvid.ToString(), out int multiply)) + { + multiply = (await _articleApi.SearchArticleInfo(cvid)).Data.Coin; + _alreadyDonatedCoinCountCatch.TryAdd(cvid.ToString(), multiply); + } + + // 在网页端我测试时只能投一枚硬币,暂时设置最多投一枚 + if (multiply >= 1) + { + return false; + } + + return true; + } + catch (Exception e) + { + _logger.LogWarning("异常:{mag}", e); + return false; + } + } + + #endregion +} diff --git a/src/Ray.BiliBiliTool.DomainService/DonateCoinDomainService.cs b/src/Ray.BiliBiliTool.DomainService/DonateCoinDomainService.cs index 387afb54c..c989c595f 100644 --- a/src/Ray.BiliBiliTool.DomainService/DonateCoinDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/DonateCoinDomainService.cs @@ -70,11 +70,13 @@ IVideoApi videoApi public async Task AddCoinsForVideos() { int needCoins = await GetNeedDonateCoinNum(); + int protectedCoins = _dailyTaskOptions.NumberOfProtectedCoins; if (needCoins <= 0) return; //投币前硬币余额 decimal coinBalance = await _coinDomainService.GetCoinBalance(); _logger.LogInformation("【投币前余额】 : {coinBalance}", coinBalance); + _ = int.TryParse(decimal.Truncate(coinBalance - protectedCoins).ToString(), out int unprotectedCoins); if (coinBalance <= 0) { @@ -82,6 +84,12 @@ public async Task AddCoinsForVideos() return; } + if (coinBalance <= protectedCoins) + { + _logger.LogInformation("因硬币余额达到或低于保留值,今日暂不执行投币任务"); + return; + } + //余额小于目标投币数,按余额投 if (coinBalance < needCoins) { @@ -89,6 +97,17 @@ public async Task AddCoinsForVideos() _logger.LogInformation("因硬币余额不足,目标投币数调整为: {needCoins}", needCoins); } + //投币后余额小于等于保护值,按保护值允许投 + if (coinBalance - needCoins <= protectedCoins) + { + //排除需投等于保护后可投数量相等时的情况 + if (unprotectedCoins != needCoins) + { + needCoins = unprotectedCoins; + _logger.LogInformation("因硬币余额投币后将达到或低于保留值,目标投币数调整为: {needCoins}", needCoins); + } + } + int success = 0; int tryCount = 10; for (int i = 1; i <= tryCount && success < needCoins; i++) @@ -105,7 +124,7 @@ public async Task AddCoinsForVideos() } if (success == needCoins) - _logger.LogInformation("投币任务完成"); + _logger.LogInformation("视频投币任务完成"); else _logger.LogInformation("投币尝试超过10次,已终止"); @@ -400,7 +419,7 @@ private async Task IsCanDonate(string aid) //已经投满2个币的,不能再投 if (!await IsDonatedLessThenLimitCoinsForVideo(aid)) { - _logger.LogDebug("超出单个视频投币数量限制,丢弃处理", aid); + _logger.LogDebug("超出单个视频投币数量限制,丢弃处理"); return false; } diff --git a/src/Ray.BiliBiliTool.DomainService/Interfaces/IAccountDomainService.cs b/src/Ray.BiliBiliTool.DomainService/Interfaces/IAccountDomainService.cs index b599bd78c..83d03da69 100644 --- a/src/Ray.BiliBiliTool.DomainService/Interfaces/IAccountDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/Interfaces/IAccountDomainService.cs @@ -24,5 +24,12 @@ public interface IAccountDomainService : IDomainService /// 批量取关 /// Task UnfollowBatched(); + + /// + /// 计算升级时间 + /// + /// + /// 升级时间 + int CalculateUpgradeTime(UserInfo useInfo); } } diff --git a/src/Ray.BiliBiliTool.DomainService/Interfaces/IArticleDomainService.cs b/src/Ray.BiliBiliTool.DomainService/Interfaces/IArticleDomainService.cs new file mode 100644 index 000000000..f5a2f6d77 --- /dev/null +++ b/src/Ray.BiliBiliTool.DomainService/Interfaces/IArticleDomainService.cs @@ -0,0 +1,12 @@ +using System.Threading.Tasks; + +namespace Ray.BiliBiliTool.DomainService.Interfaces; + +public interface IArticleDomainService : IDomainService +{ + Task AddCoinForArticle(long cvid, long mid); + + Task AddCoinForArticles(); + + Task LikeArticle(long cvid); +} diff --git a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs index 71e9fe23f..6cf387596 100644 --- a/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/LiveDomainService.cs @@ -614,6 +614,14 @@ private async Task> GetFansMedalInfoList() continue; } + // 用以排除有牌子无直播间的up主 + if (spaceInfo.Data.Live_room is null) + { + _logger.LogInformation("【主播】{name} 直播间id获取失败,已跳过",medal.Target_name); + continue; + } + + var roomId = spaceInfo.Data.Live_room.Roomid; // 获取直播间详细信息 diff --git a/src/Ray.BiliBiliTool.DomainService/MangaDomainService.cs b/src/Ray.BiliBiliTool.DomainService/MangaDomainService.cs index 4459f4625..7d175a108 100644 --- a/src/Ray.BiliBiliTool.DomainService/MangaDomainService.cs +++ b/src/Ray.BiliBiliTool.DomainService/MangaDomainService.cs @@ -62,11 +62,12 @@ public async Task MangaSign() /// public async Task MangaRead() { - BiliApiResponse response = await _mangaApi.ReadManga(_dailyTaskOptions.DevicePlatform); + if ( _dailyTaskOptions.CustomComicId <= 0 ) return; + BiliApiResponse response = await _mangaApi.ReadManga(_dailyTaskOptions.DevicePlatform, _dailyTaskOptions.CustomComicId, _dailyTaskOptions.CustomEpId); if (response.Code == 0) { - _logger.LogInformation("【漫画阅读】成功, 阅读漫画为:堀与宫村"); + _logger.LogInformation("【漫画阅读】成功"); } else { diff --git a/test/AppServiceTest/VipServiceTest.cs b/test/AppServiceTest/VipServiceTest.cs new file mode 100644 index 000000000..f50bafe0d --- /dev/null +++ b/test/AppServiceTest/VipServiceTest.cs @@ -0,0 +1,21 @@ +using Microsoft.Extensions.DependencyInjection; +using Ray.BiliBiliTool.Application.Contracts; +using Ray.BiliBiliTool.Infrastructure; + +namespace AppServiceTest; + +public class VipServiceTest +{ + public VipServiceTest() + { + Program.CreateHost(new[] { "--ENVIRONMENT=Development" }); + } + + [Fact] + public async Task VipExpressTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + var appService = scope.ServiceProvider.GetRequiredService(); + await appService.VipExpress(); + } +} diff --git a/test/BiliAgentTest/VipApiTest.cs b/test/BiliAgentTest/VipApiTest.cs new file mode 100644 index 000000000..3e540a0a2 --- /dev/null +++ b/test/BiliAgentTest/VipApiTest.cs @@ -0,0 +1,59 @@ +using System.Threading.Tasks; +using Xunit; +using Microsoft.Extensions.DependencyInjection; +using Ray.BiliBiliTool.Agent; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos.VipTask; +using Ray.BiliBiliTool.Console; +using Ray.BiliBiliTool.Infrastructure; +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Interfaces; +using Xunit.Abstractions; +namespace BiliAgentTest; + +public class VipApiTest +{ + private readonly ITestOutputHelper _output; + public VipApiTest(ITestOutputHelper output) + { + _output = output; + Program.CreateHost(new[] { "--ENVIRONMENT=Development" }); + } + + [Fact] + public async Task VipInfoTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + + var ck = scope.ServiceProvider.GetRequiredService(); + var api = scope.ServiceProvider.GetRequiredService(); + + var re = await api.GetVouchersInfo(); + if (re.Code == 0) + { + var info = re.Data.List.Find(x => x.Type == 9); + if (info != null) + { + _output.WriteLine(info.State.ToString()); + } + else + { + _output.WriteLine("error"); + } + } + } + + + [Fact] + public async Task GetVipExperienceTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + + var ck = scope.ServiceProvider.GetRequiredService(); + var api = scope.ServiceProvider.GetRequiredService(); + var re = await api.GetVipExperience(new VipExperienceRequest() + { + csrf = ck.BiliJct + }); + + _output.WriteLine(re.Message); + } +} diff --git a/test/DomainServiceTest/ArticleDomainServiceTest.cs b/test/DomainServiceTest/ArticleDomainServiceTest.cs new file mode 100644 index 000000000..6f9d268e4 --- /dev/null +++ b/test/DomainServiceTest/ArticleDomainServiceTest.cs @@ -0,0 +1,47 @@ +using Xunit.Abstractions; + +namespace DomainServiceTest; + +public class ArticleDomainServiceTest +{ + private readonly ITestOutputHelper _output; + public ArticleDomainServiceTest(ITestOutputHelper output) + { + _output = output; + Program.CreateHost(new[] { "--ENVIRONMENT=Development" }); + } + + [Fact] + public async Task LikeArticleTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + var config = Global.ConfigurationRoot; + var domainService = scope.ServiceProvider.GetRequiredService(); + await domainService.LikeArticle(5806746); + } + + + [Fact] + public async Task AddCoinForArticleTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + var config = Global.ConfigurationRoot; + var domainService = scope.ServiceProvider.GetRequiredService(); + + // 测试用的专栏:https://www.bilibili.com/read/cv5806746/?from=search&spm_id_from=333.337.0.0 + + await domainService.AddCoinForArticle(5806746, 486980924); + } + + + [Fact] + public async Task AddCoinForArticlesTest() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + var config = Global.ConfigurationRoot; + var domainService = scope.ServiceProvider.GetRequiredService(); + await domainService.AddCoinForArticles(); + } + + +} diff --git a/test/DomainServiceTest/CalculateUpgradeTimeTest.cs b/test/DomainServiceTest/CalculateUpgradeTimeTest.cs new file mode 100644 index 000000000..b9b70df03 --- /dev/null +++ b/test/DomainServiceTest/CalculateUpgradeTimeTest.cs @@ -0,0 +1,48 @@ +using Ray.BiliBiliTool.Agent.BiliBiliAgent.Dtos; + +namespace DomainServiceTest; + +public class CalculateUpgradeTimeTest +{ + public CalculateUpgradeTimeTest() + { + Program.CreateHost(new[] { "--ENVIRONMENT=Development" }); + } + + [Fact] + public void TestCalculateUpgradeTime() + { + using var scope = Global.ServiceProviderRoot.CreateScope(); + var accountDomainService = scope.ServiceProvider.GetRequiredService(); + int needDay = accountDomainService.CalculateUpgradeTime(new UserInfo() + { + Money = 7, + Level_info = new LevelInfo() + { + Current_level = 5, + Current_exp = 100, + Next_exp = 200 + } + }); + int needDay2 = accountDomainService.CalculateUpgradeTime(new UserInfo() + { + Money = 7, + Level_info = new LevelInfo() + { + Current_level = 5, + Current_exp = 1000, + Next_exp = 2000 + } + }); + + Assert.Equal(1,needDay); + Assert.Equal(37,needDay2); + + } +} + + + + + +