├── .env ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── review.yml │ ├── gh-pages.yml │ └── build.yml ├── docs ├── checkin.png ├── example-logs.png ├── example-token.png └── example-notify.png ├── .goreleaser.yml ├── SECURITY.md ├── go.mod ├── LICENSE ├── _config.yml ├── act ├── notify.go ├── act.go └── api.go ├── .gitignore ├── TRACKING.md ├── README.md ├── README_TH.md ├── CODE_OF_CONDUCT.md ├── main.go └── go.sum /.env: -------------------------------------------------------------------------------- 1 | DEBUG=debug -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: dvgamerr 2 | custom: https://sponsor.touno.io/ 3 | -------------------------------------------------------------------------------- /docs/checkin.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvgamerr-app/go-hoyolab/HEAD/docs/checkin.png -------------------------------------------------------------------------------- /docs/example-logs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvgamerr-app/go-hoyolab/HEAD/docs/example-logs.png -------------------------------------------------------------------------------- /docs/example-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvgamerr-app/go-hoyolab/HEAD/docs/example-token.png -------------------------------------------------------------------------------- /docs/example-notify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dvgamerr-app/go-hoyolab/HEAD/docs/example-notify.png -------------------------------------------------------------------------------- /.goreleaser.yml: -------------------------------------------------------------------------------- 1 | project_name: hoyolab 2 | builds: 3 | - binary: hoyolab 4 | env: 5 | - CGO_ENABLED=0 6 | goos: 7 | - darwin 8 | - linux 9 | - freebsd 10 | - windows 11 | goarch: 12 | - amd64 13 | - arm 14 | - arm64 15 | ignore: 16 | - 17 | goos: windows 18 | goarch: arm64 19 | release: 20 | name_template: "{{.ProjectName}}-v{{.Version}}" 21 | 22 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Expected behavior** 14 | A clear and concise description of what you expected to happen. 15 | 16 | **Screenshots** 17 | If applicable, add screenshots to help explain your problem. 18 | 19 | **Additional context** 20 | Add any other context about the problem here. 21 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Supported Versions 4 | 5 | Use this section to tell people about which versions of your project are 6 | currently being supported with security updates. 7 | 8 | | Version | Supported | 9 | | ------- | ------------------ | 10 | | 1.19.x | :white_check_mark: | 11 | | < 1.18.x | :x: | 12 | 13 | ## Reporting a Vulnerability 14 | 15 | Use this section to tell people how to report a vulnerability. 16 | 17 | Tell them where to go, how often they can expect to get an update on a 18 | reported vulnerability, what to expect if the vulnerability is accepted or 19 | declined, etc. 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module hoyolab 2 | 3 | go 1.22 4 | 5 | require ( 6 | github.com/dvgamerr/go-kooky v0.0.0-20231105181842-7b8f8dbebe84 7 | github.com/go-resty/resty/v2 v2.11.0 8 | gopkg.in/yaml.v2 v2.4.0 9 | ) 10 | 11 | require github.com/stretchr/testify v1.9.0 // indirect 12 | 13 | require ( 14 | github.com/go-sqlite/sqlite3 v0.0.0-20180313105335-53dd8e640ee7 // indirect 15 | github.com/godbus/dbus/v5 v5.1.0 // indirect 16 | github.com/gonuts/binary v0.2.0 // indirect 17 | github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 // indirect 18 | github.com/tmilewski/goenv v1.0.0 19 | github.com/zalando/go-keyring v0.2.3 // indirect 20 | golang.org/x/crypto v0.31.0 // indirect 21 | golang.org/x/net v0.21.0 // indirect 22 | golang.org/x/sys v0.28.0 // indirect 23 | ) 24 | -------------------------------------------------------------------------------- /.github/workflows/review.yml: -------------------------------------------------------------------------------- 1 | # Dependency Review Action 2 | # 3 | # This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. 4 | # 5 | # Source repository: https://github.com/actions/dependency-review-action 6 | # Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement 7 | name: 'Dependency Review' 8 | on: [pull_request] 9 | 10 | permissions: 11 | contents: read 12 | 13 | jobs: 14 | dependency-review: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - name: 'Checkout Repository' 18 | uses: actions/checkout@v3 19 | - name: 'Dependency Review' 20 | uses: actions/dependency-review-action@v2 21 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Kananek Thongkam 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | title: go-Hoyolab 2 | repo: dvgamerr-app/go-hoyolab 3 | version: v1.0 4 | author: 5 | username: dvgamerr 6 | name: Kananek T. 7 | website: https://dvgamerr.app/ 8 | 9 | description: > 10 | Hoyolab Automatic Daily Check-in Hoyoverse Game. 11 | You only need to run it once, then it will continue 12 | 13 | # Build settings 14 | cronitor_token: a08df15d735c0c7518246129767fd319 15 | 16 | baseurl: /go-hoyolab 17 | remote_theme: dvgamerr-app/minima-lite 18 | 19 | plugins: 20 | - jekyll-feed 21 | - jekyll-seo-tag 22 | 23 | minima: 24 | date_format: "%-d %b %Y" 25 | social_links: 26 | - { platform: devto, user_url: "https://dev.to/dvgamerr" } 27 | - { platform: facebook, user_url: "https://www.facebook.com/dvgamerr" } 28 | - { platform: x, user_url: "https://x.com/dvgamerr" } 29 | - { platform: youtube, user_url: "https://www.youtube.com/channel/UCbMNge3pQHkb3avJvUj4hLA" } 30 | youtube_username: 31 | 32 | # If you want to link only specific pages in your header, uncomment this and add the path to the pages in 33 | # order as they should show up. 34 | # 35 | # header_pages: 36 | # - about.md 37 | -------------------------------------------------------------------------------- /act/notify.go: -------------------------------------------------------------------------------- 1 | package act 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | 7 | "github.com/go-resty/resty/v2" 8 | ) 9 | 10 | func (hoyo *Hoyolab) NotifyMessage(message string) error { 11 | if message == "" { 12 | return nil 13 | } 14 | 15 | if hoyo.Notify.LINENotify != "" { 16 | raw, err := resty.New().R(). 17 | SetHeaders(map[string]string{"Authorization": fmt.Sprintf("Bearer %s", hoyo.Notify.LINENotify)}). 18 | SetFormData(map[string]string{"message": message}). 19 | Post("https://notify-api.line.me/api/notify") 20 | if err != nil { 21 | return fmt.Errorf("line::%+v", err) 22 | } 23 | if raw.StatusCode() != 200 { 24 | return fmt.Errorf("line::%s", raw.Status()) 25 | } 26 | log.Println("LINENotify Message Sending...") 27 | } 28 | 29 | if hoyo.Notify.Discord != "" { 30 | raw, err := resty.New().R(). 31 | SetFormData(map[string]string{"content": message}). 32 | Post(hoyo.Notify.Discord) 33 | if err != nil { 34 | return fmt.Errorf("Discord::%+v", err) 35 | } 36 | if raw.StatusCode() != 200 { 37 | return fmt.Errorf("Discord::%s", raw.Status()) 38 | } 39 | log.Println("Discord Message Sending...") 40 | } 41 | 42 | return nil 43 | } 44 | -------------------------------------------------------------------------------- /.github/workflows/gh-pages.yml: -------------------------------------------------------------------------------- 1 | # Sample workflow for building and deploying a Jekyll site to GitHub Pages 2 | name: Deploy GitHub Pages 3 | 4 | on: 5 | # Runs on pushes targeting the default branch 6 | push: 7 | branches: ["main"] 8 | 9 | # Allows you to run this workflow manually from the Actions tab 10 | workflow_dispatch: 11 | 12 | # Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages 13 | permissions: 14 | contents: read 15 | pages: write 16 | id-token: write 17 | 18 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. 19 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. 20 | concurrency: 21 | group: "pages" 22 | cancel-in-progress: false 23 | 24 | jobs: 25 | # Build job 26 | build: 27 | runs-on: ubuntu-latest 28 | steps: 29 | - name: Checkout 30 | uses: actions/checkout@v4 31 | - name: Setup Pages 32 | uses: actions/configure-pages@v4 33 | - name: Build with Jekyll 34 | uses: actions/jekyll-build-pages@v1 35 | with: 36 | source: ./ 37 | destination: ./_site 38 | - name: Upload artifact 39 | uses: actions/upload-pages-artifact@v3 40 | 41 | # Deployment job 42 | deploy: 43 | environment: 44 | name: github-pages 45 | url: ${{ steps.deployment.outputs.page_url }} 46 | runs-on: ubuntu-latest 47 | needs: build 48 | steps: 49 | - name: Deploy to GitHub Pages 50 | id: deployment 51 | uses: actions/deploy-pages@v4 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # File created using '.gitignore Generator' for Visual Studio Code: https://bit.ly/vscode-gig 2 | # Created by https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,go 3 | # Edit at https://www.toptal.com/developers/gitignore?templates=windows,visualstudiocode,go 4 | 5 | ### Go ### 6 | # If you prefer the allow list template instead of the deny list, see community template: 7 | # https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore 8 | # 9 | # Binaries for programs and plugins 10 | *.exe 11 | *.exe~ 12 | *.dll 13 | *.so 14 | *.dylib 15 | 16 | # Test binary, built with `go test -c` 17 | *.test 18 | 19 | # Output of the go coverage tool, specifically when used with LiteIDE 20 | *.out 21 | 22 | # Dependency directories (remove the comment below to include it) 23 | # vendor/ 24 | 25 | # Go workspace file 26 | go.work 27 | 28 | ### Go Patch ### 29 | /vendor/ 30 | /Godeps/ 31 | 32 | ### VisualStudioCode ### 33 | .vscode/* 34 | !.vscode/settings.json 35 | !.vscode/tasks.json 36 | !.vscode/launch.json 37 | !.vscode/extensions.json 38 | !.vscode/*.code-snippets 39 | 40 | # Local History for Visual Studio Code 41 | .history/ 42 | 43 | # Built Visual Studio Code Extensions 44 | *.vsix 45 | 46 | ### VisualStudioCode Patch ### 47 | # Ignore all local history of files 48 | .history 49 | .ionide 50 | 51 | ### Windows ### 52 | # Windows thumbnail cache files 53 | Thumbs.db 54 | Thumbs.db:encryptable 55 | ehthumbs.db 56 | ehthumbs_vista.db 57 | 58 | # Dump file 59 | *.stackdump 60 | 61 | # Folder config file 62 | [Dd]esktop.ini 63 | 64 | # Recycle Bin used on file shares 65 | $RECYCLE.BIN/ 66 | 67 | # Windows Installer files 68 | *.cab 69 | *.msi 70 | *.msix 71 | *.msm 72 | *.msp 73 | 74 | # Windows shortcuts 75 | *.lnk 76 | 77 | # End of https://www.toptal.com/developers/gitignore/api/windows,visualstudiocode,go 78 | 79 | # Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option) 80 | 81 | hoyolab.yaml 82 | hoyolab-x64-v0.1-windows-amd64.zip 83 | *.log -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Go 2 | 3 | on: 4 | push: 5 | branches: [ "main" ] 6 | tags: 7 | - "v*" 8 | paths: 9 | - "**.go" 10 | - "**.mod" 11 | - "**.sum" 12 | - "!.github/workflows/build.yml" 13 | pull_request: 14 | jobs: 15 | build: 16 | # strategy: 17 | # matrix: 18 | # go-version: [1.19] 19 | # os: [macos-latest, ubuntu-latest, windows-latest] 20 | # runs-on: ${{ matrix.os }} 21 | runs-on: ubuntu-latest 22 | permissions: write-all 23 | env: 24 | CGO_ENABLED: "0" 25 | steps: 26 | - uses: actions/checkout@v3 27 | 28 | - name: Set up Golang 29 | uses: actions/setup-go@v3 30 | with: 31 | go-version: 1.19 32 | # go-version: ${{ matrix.go-version }} 33 | 34 | - name: Caches 35 | uses: actions/cache@v3 36 | with: 37 | path: | 38 | ~/.cache/go-build 39 | ~/go/pkg/mod 40 | key: ubuntu-golang-${{ hashFiles('**/go.sum') }} 41 | restore-keys: | 42 | ubuntu-golang- 43 | # key: ${{ runner.os }}-golang-${{ hashFiles('**/go.sum') }} 44 | # restore-keys: | 45 | # ${{ runner.os }}-golang- 46 | - name: Recheck Compiler 47 | if: contains(github.event_name, 'pull_request') 48 | run: | 49 | mkdir -p ./bin 50 | go build -o ./bin/hoyolab . 51 | 52 | - name: Releaser 53 | if: success() && !contains(github.ref, 'main') && !contains(github.event_name, 'pull_request') 54 | uses: goreleaser/goreleaser-action@v4 55 | with: 56 | distribution: goreleaser 57 | version: latest 58 | args: release --clean 59 | env: 60 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 61 | # - name: Build 62 | # if: success() 63 | # run: | 64 | # mkdir -p ./bin 65 | # go build -o ./bin/hoyolab . 66 | # cp README.md ./bin/README.md 67 | 68 | # - name: Upload Artifact 69 | # uses: actions/upload-artifact@v3 70 | # with: 71 | # name: hoyolab-${{ matrix.os }}.tar 72 | # path: bin 73 | # retention-days: 3 74 | 75 | # - name: Zip 76 | # if: success() 77 | # uses: vimtor/action-zip@v1 78 | # with: 79 | # files: hoyolab-* README.md 80 | # dest: ./hoyolab-${{ github.ref_name }}-${{ matrix.os }}.zip 81 | 82 | # - name: Create Release 83 | # if: success() && !contains(github.ref, 'main') && !contains(github.event_name, 'pull_request') 84 | # id: create_release 85 | # uses: actions/create-release@v1 86 | # env: 87 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 88 | # with: 89 | # tag_name: ${{ github.ref }} 90 | # release_name: Hoyolab ${{ github.ref_name }} 91 | # draft: true 92 | 93 | # - name: Upload Release 94 | # if: success() && !contains(github.ref, 'main') && !contains(github.event_name, 'pull_request') 95 | # uses: actions/upload-release-asset@v1 96 | # env: 97 | # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 98 | # with: 99 | # upload_url: ${{ steps.create_release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, 100 | # asset_path: ./hoyolab.zip 101 | # asset_name: hoyolab-${{ github.ref_name }}-${{ matrix.name }}.zip 102 | # asset_content_type: application/zip -------------------------------------------------------------------------------- /act/act.go: -------------------------------------------------------------------------------- 1 | package act 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "net/url" 7 | "os" 8 | 9 | "github.com/go-resty/resty/v2" 10 | "github.com/tmilewski/goenv" 11 | "gopkg.in/yaml.v2" 12 | ) 13 | 14 | type DailyAPI struct { 15 | Endpoint string `yaml:"endpoint"` 16 | Domain string `yaml:"domain"` 17 | Award string `yaml:"award"` 18 | Info string `yaml:"info"` 19 | Sign string `yaml:"sign"` 20 | } 21 | 22 | type DailyHoyolab struct { 23 | Label string `yaml:"label"` 24 | ActID string `yaml:"act_id"` 25 | API DailyAPI `yaml:"api"` 26 | Lang string `yaml:"lang"` 27 | Referer string `yaml:"referer"` 28 | UserAgent string `yaml:"user-agent,omitempty"` 29 | CookieJar []*http.Cookie `yaml:"cookie,omitempty"` 30 | } 31 | 32 | type BrowserProfile struct { 33 | Browser string `yaml:"browser"` 34 | Name []string `yaml:"name"` 35 | UserAgent string `yaml:"userAgent"` 36 | } 37 | 38 | type LineNotify struct { 39 | Token string `yaml:"token,omitempty"` 40 | // current 41 | LINENotify string `yaml:"line-notify"` 42 | Discord string `yaml:"discord-webhook"` 43 | Mini bool `yaml:"mini"` 44 | } 45 | 46 | type Hoyolab struct { 47 | Client *resty.Client `yaml:"client,omitempty"` 48 | Notify LineNotify `yaml:"notify"` 49 | Delay int32 `yaml:"delay"` 50 | Browser []BrowserProfile `yaml:"profile"` 51 | Daily []*DailyHoyolab `yaml:"config"` 52 | } 53 | 54 | const DEBUG string = "DEBUG" 55 | 56 | var IsDebug bool = false 57 | var IsDev bool = false 58 | 59 | func init() { 60 | err := goenv.Load() 61 | if err != nil { 62 | log.Println(err) 63 | } 64 | IsDev = os.Getenv(DEBUG) != "" 65 | IsDebug = os.Getenv(DEBUG) != "" && os.Getenv(DEBUG) != "production" 66 | } 67 | 68 | func (hoyo *Hoyolab) WriteHoyoConfig(configPath string) { 69 | hoyo.Client = nil 70 | raw, err := yaml.Marshal(hoyo) 71 | if err != nil { 72 | log.Fatalf("yaml Marshal::%s", err) 73 | } 74 | err = os.WriteFile(configPath, raw, 0644) 75 | if err != nil { 76 | log.Fatalf("yaml Write::%s", err) 77 | } 78 | } 79 | 80 | func (hoyo *Hoyolab) ReadHoyoConfig(configPath string) error { 81 | raw, err := os.ReadFile(configPath) 82 | if err != nil { 83 | log.Println("Default configuration created.") 84 | hoyo.WriteHoyoConfig(configPath) 85 | return nil 86 | } 87 | 88 | var readHoyo *Hoyolab 89 | err = yaml.Unmarshal(raw, &readHoyo) 90 | if err != nil { 91 | log.Println("Default configuration created.") 92 | return err 93 | } else { 94 | log.Println("Readed configuration .") 95 | hoyo.Notify = readHoyo.Notify 96 | if readHoyo.Notify.Token != "" { 97 | hoyo.Notify.LINENotify = readHoyo.Notify.Token 98 | hoyo.Notify.Token = "" 99 | } 100 | hoyo.Delay = readHoyo.Delay 101 | hoyo.Browser = readHoyo.Browser 102 | hoyo.Daily = readHoyo.Daily 103 | } 104 | hoyo.WriteHoyoConfig(configPath) 105 | return nil 106 | } 107 | 108 | func (hoyo *Hoyolab) IsCookieToken(cookies http.CookieJar) bool { 109 | for _, act := range hoyo.Daily { 110 | uri, _ := url.Parse(act.API.Domain) 111 | act.SetCookie(cookies.Cookies(uri)) 112 | if !act.IsCookieLogin() { 113 | act.CookieJar = nil 114 | return false 115 | } 116 | } 117 | return true 118 | } 119 | 120 | func (e *DailyHoyolab) SetCookie(rs []*http.Cookie) { 121 | e.CookieJar = rs 122 | } 123 | 124 | func (e *DailyHoyolab) IsCookieLogin() bool { 125 | for _, jar := range e.CookieJar { 126 | if jar.Name == "ltoken" || jar.Name == "ltoken_v2" { 127 | return true 128 | } 129 | } 130 | return false 131 | } 132 | -------------------------------------------------------------------------------- /TRACKING.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | https://api-os-takumi.mihoyo.com/common/gacha_record/api/getGachaLog?authkey_ver=1&sign_type=2&lang=th&authkey=XXX&game_biz=hkrpg_global 4 | https://starrailstation.com/api/v1/warp?authkey_ver=1&sign_type=2®ion_type=os&authkey=XXX&gacha_type=1&end_id=0&sync_upstream=1 5 | 6 | {"identity_hash":"88d7ecea","compat_ver":1,"code":200,"next_id":"1683303000000930399","result":[{"uid":"1683472200001760299","id":1009,"rarity":4,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001760199","id":20011,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001760099","id":20003,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759999","id":20015,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759899","id":20016,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759799","id":20007,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759699","id":20011,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759599","id":20005,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759499","id":20004,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683472200001759399","id":21017,"rarity":4,"gacha":1001,"gacha_type":1,"timestamp":1683474763000},{"uid":"1683303000000931299","id":20016,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000931199","id":20018,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000931099","id":20015,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930999","id":1002,"rarity":4,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930899","id":1107,"rarity":5,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930799","id":20002,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930699","id":20008,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930599","id":20009,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930499","id":20007,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000},{"uid":"1683303000000930399","id":20010,"rarity":3,"gacha":1001,"gacha_type":1,"timestamp":1683303768000}]} 7 | 8 | 9 | https://starrailstation.com/api/v1/warp?authkey_ver=1&sign_type=2®ion_type=os&authkey=XXX&gacha_type=1&end_id=1683303000000930399&sync_upstream=1 10 | 11 | ----------- 12 | 13 | https://starrailstation.com/api/v1/warp?authkey_ver=1&sign_type=2®ion_type=os&authkey=XXX&gacha_type=12&end_id=1683169800001487599&sync_upstream=1 14 | 15 | 16 | {"identity_hash":"88d7ecea","compat_ver":1,"code":200,"next_id":-1,"result":[{"uid":"1683169800001481299","id":21007,"rarity":4,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001481199","id":20016,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001481099","id":21001,"rarity":4,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480999","id":20017,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480899","id":20002,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480799","id":20011,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480699","id":20008,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480599","id":20004,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480499","id":20012,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000},{"uid":"1683169800001480399","id":20006,"rarity":3,"gacha":3003,"gacha_type":12,"timestamp":1683172473000}]} 17 | 18 | gacha_type=1 19 | gacha_type=2 20 | gacha_type=11 21 | gacha_type=12 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
23 | 24 |  25 | 26 |  27 | 28 | 29 | ## Features 30 | - [x] update new version from github automatic. 31 | - [x] Claims checkin daily with chrome browser only. 32 | - [x] Multiple chrome profiles for multiple game accounts. 33 | - [X] command line `hoyolab` support all os. 34 | - [x] Line Notify support after checkin. 35 | 36 |  37 | 38 |  39 | 40 | - [x] Discord Notify support after checkin. 41 | 42 |  43 | 44 | 45 |  46 | 47 | - [x] Genshin Impact claims support. 48 | - [x] Honkai StarRail claims support. 49 | - [x] Honkai Impact 3 claims support. 50 | 51 | ### Todo 52 | - [ ] Zenless Zone Zero claims support. 53 | - [ ] docker container support. 54 | - [ ] support session with all browser. 55 | - [ ] install schedule task with windows-os automatic. 56 | 57 | --- 58 | 59 | ## How to use 60 | 1. Open chrome browser open [https://www.hoyolab.com/home](https://www.hoyolab.com/home) 61 | 2. Login user genshin account for daily cliams. 62 | 3. run `hoyolab.exe`. 63 | 4. If found Error please craete issues in [https://github.com/dvgamerr-app/go-hoyolab/issues](https://github.com/dvgamerr-app/go-hoyolab/issues) 64 | 5. If Notify message after CheckIn use [LINE-Notify](https://notify-bot.line.me/my/) 65 | 6. log in that and `Generate token` in below page after that copy token paste in `hoyolab.yaml` in `notify.token` at `XXXXXX` same image: 66 | 67 |  68 | 69 | 7. If you don't play some game add `#` in first char in line scope, e.g. i don;t play honkai impact 70 | 71 |  72 | 73 | 74 | 75 | ### Windows 76 | ### Solution If Turn On computer 24*7 77 | - use `Task Scheduler` and `Create Basic Task` 78 | - select `Daily` next time at `5 am`. 79 | - after click Next select `Start a program`, Next and browse `hoyolab.exe` 80 | 81 | ### Solution If starup computer 82 | - create shortcut from `hoyolab.exe` 83 | - copy shortcut to `C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup` 84 | 85 | ### MaOcOS & Linux 86 | - use `crontab` for automatic run. 87 | 88 | ## Prerequisites 89 | - Have login to mihoyo's website at chrome browser (A login for a year is enough) 90 | 91 | ## If you need help You can join Discord. 92 | 93 | [](https://discord.gg/QDccF497Mw) 94 | -------------------------------------------------------------------------------- /README_TH.md: -------------------------------------------------------------------------------- 1 | 23 | 24 | 25 | 26 |  27 | 28 |  29 | 30 | ## Features 31 | - [x] ปล่อย version ใหม่ผ่าน github actions. 32 | - [x] เริ่มต้นใช้งานได้แค่ chrome เท่านั้น. 33 | - [x] สามารถใช้กับ chrome หลายโปรไฟล์ เพื่อใช้กับหลาย login ID ได้. 34 | - [X] สามารถรัน `hoyolab` ได้ทุก os. 35 | - [x] แจ้งเตือนผ่าน Line Notify. 36 | 37 |  38 | 39 |  40 | 41 | - [x] แจ้งเตือนผ่าน discord webhook. 42 | 43 |  44 | 45 | 46 |  47 | 48 | - [x] รับรองเกม Genshin Impact. 49 | - [x] รับรองเกม Honkai StarRail. 50 | - [x] รับรองเกม Honkai Impact 3. 51 | 52 | ### ที่จะทำต่อ 53 | - [ ] รองรับ Zenless Zone Zero. 54 | - [ ] docker container support. 55 | - [ ] support session with all browser. 56 | - [ ] install schedule task with windows-os automatic. 57 | 58 | --- 59 | 60 | ## วิธีใช้ 61 | 1. เปิด chrome ขึ้นมาแล้วเข้าเว็บ [https://www.hoyolab.com/home](https://www.hoyolab.com/home) 62 | 2. เข้าใช้งาน ด้วย account ของ hoyoverse ที่ต้องการจะรับรางวัน. 63 | 3. เปิดโปรแกรม `hoyolab.exe` ขึ้นมา เสร็จ. 64 | 4. ถ้าพบ error แจ้งได้ที่ [https://github.com/dvgamerr/go-hoyolab/issues](https://github.com/dvgamerr/go-hoyolab/issues) 65 | 5. ถ้าต้องการ ใช้แจ่้งเตือนให้เข้่าไปที่ [LINE-Notify](https://notify-bot.line.me/my/) 66 | 6. เข้าใข้งานแล้ว กด `Generate token` จะได้ token มาแล้ว copy มาวางไว้ใน `hoyolab.yaml` ที่ `notify.token` แทนที่ `XXXXXX` ตามรูป: 67 | 68 |  69 | 70 | 7.ถ้าเกมไหน ไม่ได้เล่นให้ลบ หรือ `#` เพื่อปิดไปได้เลยตามรูป 71 | 72 |  73 | 74 | 75 | 76 | ### Windows 77 | ### สำหรับเครื่องที่เปิดเครื่อง 24 ชม ให้สร้าง Task Schedule ตามนี้ (แนะนำให้ใช้ profile อื่นเพื่อแทน profile หลัก) 78 | - เปิด `Task Scheduler` คลิก `Create Basic Task` 79 | - เลือก `Daily` แล้วกด next เลือกเวลาเป็น `5 am`. 80 | - หลังจากกด Next ให้เลือก `Start a program`, กด next และเลือก browse ไปหาไฟล์ `hoyolab.exe` ในเครื่อง 81 | 82 | ### สำหรับเครื่องที่เปิด-ปิดทุกๆ วัน 83 | - สร้าง shortcut จากไฟล์ `hoyolab.exe` 84 | - แล้ว copy ไปวางไว้ที่ `C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup` 85 | - ทุกวันที่เปิดเครื่องมันจะ checkin ให้ ตลอด 86 | 87 | ### MaOcOS & Linux 88 | - ใช้ `crontab` ได้เลย ง่ายกว่าเยอะ. 89 | 90 | ## Prerequisites 91 | - เข้าสู่ระบบเว็บไซต์ของ mihoyo ด้วยเบราว์เซอร์ Chrome 92 | 93 | ## หากคุณต้องการความช่วยเหลือ คุณสามารถเข้าร่วม Discord ได้ 94 | #### (อย่าเที่ยวพิมพ์ @everyone แล้ว โวยวายเป็นเด็กๆ อธิบายดีๆ เด๋วมาตอบ) 95 | 96 | [](https://discord.gg/QDccF497Mw) 97 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | kananek.dev@touno.io. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /act/api.go: -------------------------------------------------------------------------------- 1 | package act 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | "log" 7 | "net/url" 8 | "reflect" 9 | "time" 10 | 11 | "github.com/go-resty/resty/v2" 12 | ) 13 | 14 | type ActAPI struct { 15 | RetCode int32 `json:"retcode"` 16 | Message string `json:"message"` 17 | Data any `json:"data,omitempty"` 18 | } 19 | 20 | type ActAward struct { 21 | Month int16 `json:"month"` 22 | Awards []ActAwardItem `json:"awards"` 23 | Biz string `json:"biz"` 24 | Resign bool `json:"resign"` 25 | ExtraAward struct { 26 | HasExtraAward bool `json:"has_extra_award"` 27 | StartTime string `json:"start_time"` 28 | EndTime string `json:"end_time"` 29 | List []any `json:"list"` 30 | StartTimestamp string `json:"start_timestamp"` 31 | EndTimestamp string `json:"end_timestamp"` 32 | } `json:"short_extra_award"` 33 | } 34 | 35 | type ActAwardItem struct { 36 | Icon string `json:"icon"` 37 | Name string `json:"name"` 38 | Count int32 `json:"cnt"` 39 | } 40 | 41 | type ActInfo struct { 42 | TotalSignDay int32 `json:"total_sign_day"` 43 | Today string `json:"today"` 44 | IsSign bool `json:"is_sign"` 45 | FirstBind bool `json:"first_bind"` 46 | IsSub bool `json:"is_sub"` 47 | Region string `json:"region"` 48 | MonthLastDay bool `json:"month_last_day"` 49 | } 50 | 51 | type ActSign map[string]any 52 | 53 | type ActUser struct { 54 | UserInfo ActUserInfo `json:"user_info"` 55 | } 56 | 57 | type ActUserInfo struct { 58 | UID string `json:"uid"` 59 | NickName string `json:"nickname"` 60 | } 61 | 62 | // var json jsoniter.API = jsoniter.ConfigCompatibleWithStandardLibrary 63 | 64 | func (e *DailyHoyolab) generateHeaders() map[string]string { 65 | uri, _ := url.Parse(e.Referer) 66 | return map[string]string{ 67 | "Accept": "application/json, text/plain, */*", 68 | "Accept-Encoding": "gzip, deflate, br", 69 | "Accept-Language": "en-US,en;q=0.9,th;q=0.8", 70 | "Connection": "keep-alive", 71 | "Content-Type": "application/json;charset=UTF-8", 72 | "Referer": fmt.Sprintf("%s://%s", uri.Scheme, uri.Host), 73 | "Origin": fmt.Sprintf("%s://%s", uri.Scheme, uri.Host), 74 | "User-Agent": e.UserAgent, 75 | "Sec-Ch-Ua": `"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"`, 76 | "Sec-Ch-Ua-Mobile": `?0`, 77 | "Sec-Ch-Ua-Platform": `"Windows"`, 78 | "Sec-Fetch-Mode": `cors`, 79 | "Sec-Fetch-Site": `same-site`, 80 | "Sec-Fetch-Dest": `empty`, 81 | } 82 | } 83 | 84 | func (hoyo *Hoyolab) ActRequest(act *DailyHoyolab) *resty.Request { 85 | // delay request 150ms default. 86 | time.Sleep(time.Duration(hoyo.Delay) * time.Millisecond) 87 | 88 | return hoyo.Client.R(). 89 | SetCookies(act.CookieJar). 90 | SetHeaders(act.generateHeaders()). 91 | SetQueryParams(map[string]string{"lang": act.Lang, "act_id": act.ActID}) 92 | } 93 | 94 | func actResponse[T any](raw *resty.Response, actData *T) error { 95 | var res ActAPI 96 | if err := json.Unmarshal(raw.Body(), &res); err != nil { 97 | return fmt.Errorf("res::%s", "Unmarshal: ActAPI") 98 | } 99 | 100 | if res.RetCode != 0 { 101 | return fmt.Errorf(" %s", res.Message) 102 | } 103 | 104 | data, err := json.Marshal(res.Data) 105 | if err != nil { 106 | return fmt.Errorf("res::Marshal: %v", reflect.TypeOf(actData)) 107 | } 108 | 109 | if err := json.Unmarshal(data, actData); err != nil { 110 | return fmt.Errorf("res::Unmarshal: %v", reflect.TypeOf(actData)) 111 | } 112 | 113 | return nil 114 | } 115 | 116 | func (e *DailyHoyolab) GetMonthAward(hoyo *Hoyolab) (*ActAward, error) { 117 | raw, err := hoyo.ActRequest(e).Get(fmt.Sprintf("%s%s", e.API.Endpoint, e.API.Award)) 118 | if err != nil { 119 | return nil, fmt.Errorf("api::%+v", err) 120 | } 121 | if raw.StatusCode() != 200 { 122 | return nil, fmt.Errorf("api::%s", raw.Status()) 123 | } 124 | 125 | var res ActAward 126 | if err := actResponse(raw, &res); err != nil { 127 | return nil, fmt.Errorf("api::%+v", err) 128 | } 129 | 130 | if IsDebug { 131 | log.Printf("%s::%+v\n", e.Label, map[string]any{ 132 | "Month": res.Month, 133 | "Biz": res.Biz, 134 | "Resign": res.Resign, 135 | "ExtraAward": res.ExtraAward, 136 | }) 137 | } 138 | return &res, nil 139 | } 140 | 141 | func (e *DailyHoyolab) GetAccountUserInfo(hoyo *Hoyolab) (*ActUser, error) { 142 | // https://bbs-api-os.hoyolab.com/community/painter/wapi/user/full?t=1683734340156 143 | raw, err := hoyo.ActRequest(e). 144 | SetQueryParams(map[string]string{"t": fmt.Sprint(time.Now().Unix() * 1000)}). 145 | SetBody(map[string]string{"act_id": e.ActID}). 146 | Get("https://bbs-api-os.hoyolab.com/community/painter/wapi/user/full") 147 | if err != nil { 148 | return nil, fmt.Errorf("api::%+v", err) 149 | } 150 | if raw.StatusCode() != 200 { 151 | return nil, fmt.Errorf("api::%s", raw.Status()) 152 | } 153 | 154 | var res ActUser 155 | if err := actResponse(raw, &res); err != nil { 156 | return nil, fmt.Errorf("api::%+v", err) 157 | } 158 | 159 | if IsDebug { 160 | log.Printf("%s::%+v\n", e.Label, res) 161 | } 162 | return &res, nil 163 | } 164 | 165 | func (e *DailyHoyolab) GetCheckInInfo(hoyo *Hoyolab) (*ActInfo, error) { 166 | raw, err := hoyo.ActRequest(e).Get(fmt.Sprintf("%s%s", e.API.Endpoint, e.API.Info)) 167 | if err != nil { 168 | return nil, fmt.Errorf("api::%+v", err) 169 | } 170 | if raw.StatusCode() != 200 { 171 | return nil, fmt.Errorf("api::%s", raw.Status()) 172 | } 173 | 174 | var res ActInfo 175 | if err := actResponse(raw, &res); err != nil { 176 | return nil, fmt.Errorf("api::%+v", err) 177 | } 178 | 179 | if IsDebug { 180 | log.Printf("%s::%+v\n", e.Label, res) 181 | } 182 | return &res, nil 183 | } 184 | 185 | type ActSignRisk map[string]any 186 | 187 | func (e *DailyHoyolab) DailySignIn(hoyo *Hoyolab) (bool, error) { 188 | time.Sleep(1 * time.Second) 189 | raw, err := hoyo.ActRequest(e).SetBody(map[string]string{"act_id": e.ActID}).Post(fmt.Sprintf("%s%s", e.API.Endpoint, e.API.Sign)) 190 | if err != nil { 191 | return false, fmt.Errorf("api::%+v", err) 192 | } 193 | if raw.StatusCode() != 200 { 194 | return false, fmt.Errorf("api::%s", raw.Status()) 195 | } 196 | 197 | var res ActSign 198 | if err := actResponse(raw, &res); err != nil { 199 | return false, fmt.Errorf("api::%+v", err) 200 | } 201 | 202 | if IsDebug { 203 | log.Printf("%s::%+v\n", e.Label, res) 204 | } 205 | 206 | if res["gt_result"] != nil { 207 | risk := res["gt_result"].(map[string]any) 208 | if risk["risk_code"].(float64) > 0 { 209 | return true, nil 210 | } 211 | } 212 | return false, nil 213 | } 214 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "log" 6 | "net/http" 7 | "os" 8 | "path" 9 | "path/filepath" 10 | "sort" 11 | "strings" 12 | 13 | "hoyolab/act" 14 | 15 | "github.com/dvgamerr/go-kooky" 16 | "github.com/dvgamerr/go-kooky/browser/chrome" 17 | "github.com/go-resty/resty/v2" 18 | "github.com/tmilewski/goenv" 19 | ) 20 | 21 | // at *day 1* your got [GSI]asdasd x1, [HSR]asdasd x1, [HI3]asdasd x1 22 | var configExt string = "yaml" 23 | var logExt string = "log" 24 | var configPath string = "" 25 | var logPath string = "" 26 | var logfile *os.File 27 | 28 | func init() { 29 | err := goenv.Load() 30 | if err != nil { 31 | log.Println(err) 32 | } 33 | IsDev := os.Getenv(act.DEBUG) != "" 34 | 35 | execFilename, err := os.Executable() 36 | if err != nil { 37 | log.Fatal(err) 38 | } 39 | baseFilename := strings.ReplaceAll(filepath.Base(execFilename), filepath.Ext(execFilename), "") 40 | dirname := filepath.Dir(execFilename) 41 | 42 | if IsDev { 43 | dirname, err = os.Getwd() 44 | if err != nil { 45 | log.Fatal(err) 46 | } 47 | } 48 | 49 | configPath = path.Join(dirname, fmt.Sprintf("%s.%s", baseFilename, configExt)) 50 | logPath = path.Join(dirname, fmt.Sprintf("%s.%s", baseFilename, logExt)) 51 | 52 | log.SetFlags(log.Lshortfile | log.Ltime) 53 | if !IsDev { 54 | log.SetFlags(log.Ldate | log.Ltime) 55 | f, err := os.OpenFile(logPath, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) 56 | if err != nil { 57 | log.Fatal(err) 58 | } 59 | log.SetOutput(f) 60 | } 61 | } 62 | 63 | func main() { 64 | if logfile != nil { 65 | defer logfile.Close() 66 | } 67 | 68 | hoyo := GenerateDefaultConfig() 69 | if err := hoyo.ReadHoyoConfig(configPath); err != nil { 70 | log.Fatal(err) 71 | } 72 | 73 | cookieStore := kooky.FindAllCookieStores() 74 | log.Printf("Browser total %d sessions", len(cookieStore)) 75 | 76 | var notifyMessage []string 77 | for _, store := range cookieStore { 78 | if _, err := os.Stat(store.FilePath()); os.IsNotExist(err) { 79 | continue 80 | } 81 | 82 | for _, profile := range hoyo.Browser { 83 | if len(profile.Name) > 0 && (store.Browser() != profile.Browser || !ContainsStrings(profile.Name, store.Profile())) { 84 | continue 85 | } 86 | log.Printf(`Profile %s::"%s"`, store.Browser(), store.Profile()) 87 | 88 | cookies, err := chrome.CookieJar(store.FilePath()) 89 | if err != nil { 90 | log.Println(err) 91 | continue 92 | } 93 | 94 | if !hoyo.IsCookieToken(cookies) { 95 | log.Println("Session is empty, please login hoyolab.com.") 96 | continue 97 | } 98 | 99 | var resAcc *act.ActUser 100 | hoyo.Client = resty.New() 101 | 102 | var getDaySign int32 = -1 103 | var getAward []string = []string{} 104 | for i := 0; i < len(hoyo.Daily); i++ { 105 | act := hoyo.Daily[i] 106 | act.UserAgent = profile.UserAgent 107 | 108 | if resAcc == nil { 109 | resAcc, err = act.GetAccountUserInfo(hoyo) 110 | if err != nil { 111 | log.Printf("%s::GetUserInfo : %v", act.Label, err) 112 | continue 113 | } 114 | log.Printf("%s::GetUserInfo : Hi, '%s'", act.Label, resAcc.UserInfo.NickName) 115 | } 116 | 117 | resAward, err := act.GetMonthAward(hoyo) 118 | if err != nil { 119 | log.Printf("%s::GetMonthAward : %v", act.Label, err) 120 | continue 121 | } 122 | 123 | resInfo, err := act.GetCheckInInfo(hoyo) 124 | if err != nil { 125 | log.Printf("%s::GetCheckInInfo :%v", act.Label, err) 126 | continue 127 | } 128 | 129 | log.Printf("%s::GetCheckInInfo : Checked in for %d days", act.Label, resInfo.TotalSignDay) 130 | if resInfo.IsSign { 131 | log.Printf("%s::DailySignIn : Claimed %s", act.Label, resInfo.Today) 132 | continue 133 | } 134 | 135 | isRisk, err := act.DailySignIn(hoyo) 136 | if err != nil { 137 | log.Printf("%s::DailySignIn : %v", act.Label, err) 138 | continue 139 | } 140 | if getDaySign < 0 { 141 | getDaySign = resInfo.TotalSignDay + 1 142 | } 143 | 144 | award := resAward.Awards[resInfo.TotalSignDay+1] 145 | log.Printf("%s::GetMonthAward : Today's received %s x%d", act.Label, award.Name, award.Count) 146 | 147 | if hoyo.Notify.Mini { 148 | if isRisk { 149 | getAward = append(getAward, fmt.Sprintf("Challenge captcha (%s)", act.Label)) 150 | } else { 151 | getAward = append(getAward, fmt.Sprintf("*%s x%d* (%s)", award.Name, award.Count, act.Label)) 152 | } 153 | } else { 154 | if isRisk { 155 | getAward = append(getAward, fmt.Sprintf("*[%s]* at day %d challenge captcha", act.Label, resInfo.TotalSignDay+1)) 156 | } else { 157 | getAward = append(getAward, fmt.Sprintf("*[%s]* at day %d received %s x%d", act.Label, resInfo.TotalSignDay+1, award.Name, award.Count)) 158 | } 159 | } 160 | } 161 | if len(getAward) > 0 { 162 | if len(hoyo.Browser) > 1 { 163 | notifyMessage = append(notifyMessage, "\n") 164 | } 165 | 166 | if hoyo.Notify.Mini { 167 | notifyMessage = append(notifyMessage, fmt.Sprintf("%s, at day %d your got %s", resAcc.UserInfo.NickName, getDaySign, strings.Join(getAward, ", "))) 168 | } else { 169 | notifyMessage = append(notifyMessage, fmt.Sprintf("\nHi, %s Checked in for %d days.\n%s", resAcc.UserInfo.NickName, 1, strings.Join(getAward, "\n"))) 170 | } 171 | } 172 | } 173 | } 174 | 175 | if err := hoyo.NotifyMessage(strings.Join(notifyMessage, "\n")); err != nil { 176 | log.Printf("NotifyMessage : %v", err) 177 | } 178 | } 179 | 180 | func ContainsStrings(a []string, x string) bool { 181 | sort.Strings(a) 182 | for _, v := range a { 183 | if v == x { 184 | return true 185 | } 186 | } 187 | return false 188 | } 189 | 190 | func GenerateDefaultConfig() *act.Hoyolab { 191 | // Genshin Impact 192 | var apiGenshinImpact = &act.DailyHoyolab{ 193 | CookieJar: []*http.Cookie{}, 194 | Label: "GSI", 195 | ActID: "e202102251931481", 196 | API: act.DailyAPI{ 197 | Endpoint: "https://sg-hk4e-api.hoyolab.com", 198 | Domain: "https://hoyolab.com", 199 | Award: "/event/sol/home", 200 | Info: "/event/sol/info", 201 | Sign: "/event/sol/sign", 202 | }, 203 | Lang: "en-us", 204 | Referer: "https://act.hoyolab.com/ys/event/signin-sea-v3/index.html", 205 | } 206 | 207 | // Honkai StarRail 208 | var apiHonkaiStarRail = &act.DailyHoyolab{ 209 | CookieJar: []*http.Cookie{}, 210 | Label: "HSR", 211 | ActID: "e202303301540311", 212 | API: act.DailyAPI{ 213 | Endpoint: "https://sg-public-api.hoyolab.com", 214 | Domain: "https://hoyolab.com", 215 | Award: "/event/luna/os/home", 216 | Info: "/event/luna/os/info", 217 | Sign: "/event/luna/os/sign", 218 | }, 219 | Lang: "en-us", 220 | Referer: "https://act.hoyolab.com/bbs/event/signin/hkrpg/index.html", 221 | } 222 | 223 | // Honkai Impact 3 224 | var apiHonkaiImpact = &act.DailyHoyolab{ 225 | CookieJar: []*http.Cookie{}, 226 | Label: "HI3", 227 | ActID: "e202110291205111", 228 | API: act.DailyAPI{ 229 | Endpoint: "https://sg-public-api.hoyolab.com", 230 | Domain: "https://hoyolab.com", 231 | Award: "/event/mani/home", 232 | Sign: "/event/mani/sign", 233 | Info: "/event/mani/info", 234 | }, 235 | Lang: "en-us", 236 | Referer: "https://act.hoyolab.com/bbs/event/signin-bh3/index.html", 237 | } 238 | return &act.Hoyolab{ 239 | Notify: act.LineNotify{ 240 | LINENotify: "", 241 | Discord: "", 242 | Mini: true, 243 | }, 244 | 245 | Delay: 150, 246 | Browser: []act.BrowserProfile{ 247 | { 248 | Browser: "chrome", 249 | Name: []string{}, 250 | UserAgent: "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36", 251 | }, 252 | }, 253 | Daily: []*act.DailyHoyolab{ 254 | apiGenshinImpact, 255 | apiHonkaiStarRail, 256 | apiHonkaiImpact, 257 | }, 258 | } 259 | } 260 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/Velocidex/json v0.0.0-20220224052537-92f3c0326e5a h1:AeXPUzhU0yhID/v5JJEIkjaE85ASe+Vh4Kuv1RSLL+4= 2 | github.com/Velocidex/json v0.0.0-20220224052537-92f3c0326e5a/go.mod h1:ukJBuruT9b24pdgZwWDvOaCYHeS03B7oQPCUWh25bwM= 3 | github.com/Velocidex/ordereddict v0.0.0-20230909174157-2aa49cc5d11d h1:fn372EqKyazBxYUP5HPpBi3jId4MXuppEypEALGfvEk= 4 | github.com/Velocidex/ordereddict v0.0.0-20230909174157-2aa49cc5d11d/go.mod h1:+MqO5UMBemyFSm+yRXslbpFTwPUDhFHUf7HPV92twg4= 5 | github.com/Velocidex/yaml/v2 v2.2.8 h1:GUrSy4SBJ6RjGt43k6MeBKtw2z/27gh4A3hfFmFY3No= 6 | github.com/Velocidex/yaml/v2 v2.2.8/go.mod h1:PlXIg/Pxmoja48C1vMHo7C5pauAZvLq/UEPOQ3DsjS4= 7 | github.com/bobesa/go-domain-util v0.0.0-20190911083921-4033b5f7dd89 h1:2pkAuIM8OF1fy4ToFpMnI4oE+VeUNRbGrpSLKshK0oQ= 8 | github.com/bobesa/go-domain-util v0.0.0-20190911083921-4033b5f7dd89/go.mod h1:/09nEjna1UMoasyyQDhOrIn8hi2v2kiJglPWed1idck= 9 | github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= 10 | github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/dvgamerr/go-kooky v0.0.0-20231105181842-7b8f8dbebe84 h1:bTzkRQmGqgZSljGhYRac5tQd3EgAsolPH3BOl46pGkk= 12 | github.com/dvgamerr/go-kooky v0.0.0-20231105181842-7b8f8dbebe84/go.mod h1:KFjjTKZwRNFrj4Du73V5qg5Qo19ZJQOVLe9p3YV++Ko= 13 | github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A= 14 | github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8= 15 | github.com/go-resty/resty/v2 v2.11.0 h1:i7jMfNOJYMp69lq7qozJP+bjgzfAzeOhuGlyDrqxT/8= 16 | github.com/go-resty/resty/v2 v2.11.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A= 17 | github.com/go-sqlite/sqlite3 v0.0.0-20180313105335-53dd8e640ee7 h1:ow5vK9Q/DSKkxbEIJHBST6g+buBDwdaDIyk1dGGwpQo= 18 | github.com/go-sqlite/sqlite3 v0.0.0-20180313105335-53dd8e640ee7/go.mod h1:JxSQ+SvsjFb+p8Y+bn+GhTkiMfKVGBD0fq43ms2xw04= 19 | github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= 20 | github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= 21 | github.com/gonuts/binary v0.2.0 h1:caITwMWAoQWlL0RNvv2lTU/AHqAJlVuu6nZmNgfbKW4= 22 | github.com/gonuts/binary v0.2.0/go.mod h1:kM+CtBrCGDSKdv8WXTuCUsw+loiy8f/QEI8YCCC0M/E= 23 | github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6 h1:IsMZxCuZqKuao2vNdfD82fjjgPLfyHLpR41Z88viRWs= 24 | github.com/keybase/go-keychain v0.0.0-20231219164618-57a3676c3af6/go.mod h1:3VeWNIJaW+O5xpRQbPp0Ybqu1vJd/pm7s2F473HRrkw= 25 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 26 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 27 | github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 28 | github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= 29 | github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= 30 | github.com/tmilewski/goenv v1.0.0 h1:4xpKGHo7W3bfBi3rjzK30JPDiwmmVf2tHAy+NZI6a1A= 31 | github.com/tmilewski/goenv v1.0.0/go.mod h1:cSJaYLC0V+xraoBwU1P+rjz/M1LXB4GEU5RHmoYjxy0= 32 | github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= 33 | github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= 34 | github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= 35 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= 36 | golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 37 | golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= 38 | golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U= 39 | golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk= 40 | golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= 41 | golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= 42 | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= 43 | golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= 44 | golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= 45 | golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= 46 | golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= 47 | golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= 48 | golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= 49 | golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= 50 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 51 | golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 52 | golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 53 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= 54 | golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 55 | golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 56 | golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 57 | golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 58 | golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 59 | golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 60 | golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 61 | golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= 62 | golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 63 | golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= 64 | golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= 65 | golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= 66 | golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= 67 | golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= 68 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 69 | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= 70 | golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= 71 | golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= 72 | golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= 73 | golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= 74 | golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= 75 | golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= 76 | golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= 77 | golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= 78 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 79 | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= 80 | golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= 81 | golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= 82 | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= 83 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= 84 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 85 | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= 86 | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= 87 | gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= 88 | gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 89 | www.velocidex.com/golang/go-ese v0.2.0 h1:8/hzEMupfqEF0oMi1/EzsMN1xLN0GBFcB3GqxqRnb9s= 90 | www.velocidex.com/golang/go-ese v0.2.0/go.mod h1:6fC9T6UGLbM7icuA0ugomU5HbFC5XA5I30zlWtZT8YE= 91 | --------------------------------------------------------------------------------