From f1b24741dc69fac593c1edc00700912c0765afcc Mon Sep 17 00:00:00 2001 From: Kazuhiro MUSASHI Date: Sun, 11 Aug 2024 14:16:21 +0900 Subject: [PATCH] initial commit --- .drone.yml | 35 +++++++++ .gitignore | 4 + .goreleaser.yml | 77 ++++++++++++++++++ Dockerfile | 9 +++ LICENSE | 21 +++++ README.md | 98 +++++++++++++++++++++++ cmd/breaktable.go | 85 ++++++++++++++++++++ cmd/collect.go | 64 +++++++++++++++ cmd/log.go | 42 ++++++++++ cmd/login.go | 31 ++++++++ cmd/portfolio.go | 112 ++++++++++++++++++++++++++ cmd/root.go | 96 +++++++++++++++++++++++ go.mod | 41 ++++++++++ go.sum | 135 ++++++++++++++++++++++++++++++++ internal/lib/browser/browser.go | 54 +++++++++++++ main.go | 28 +++++++ 16 files changed, 932 insertions(+) create mode 100644 .drone.yml create mode 100644 .gitignore create mode 100644 .goreleaser.yml create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 README.md create mode 100644 cmd/breaktable.go create mode 100644 cmd/collect.go create mode 100644 cmd/log.go create mode 100644 cmd/login.go create mode 100644 cmd/portfolio.go create mode 100644 cmd/root.go create mode 100644 go.mod create mode 100644 go.sum create mode 100644 internal/lib/browser/browser.go create mode 100644 main.go diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..c4c4e09 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,35 @@ +kind: pipeline +name: default + +steps: + - name: fetch + image: docker:git + commands: + - git fetch --tags + + - name: build + image: cimg/go + + volumes: + - name: dockersock + path: /var/run/docker.sock + + environment: + GITEA_TOKEN: + from_secret: gitea_token + + commands: + - sudo chmod 666 /var/run/docker.sock + - curl -sL https://git.io/goreleaser -o /tmp/goreleaser-download + - chmod +x /tmp/goreleaser-download + - sudo chown -R circleci:circleci . + - /tmp/goreleaser-download release --rm-dist + +trigger: + event: + - tag + +volumes: +- name: dockersock + host: + path: /var/run/docker.sock diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7e03a67 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +.envrc +ssl/ +.assets/ +vendor/ diff --git a/.goreleaser.yml b/.goreleaser.yml new file mode 100644 index 0000000..63c0b1e --- /dev/null +++ b/.goreleaser.yml @@ -0,0 +1,77 @@ +env: + - CGO_ENABLED=0 + +before: + hooks: + # you may remove this if you don't use vgo + - sudo apt install rpm + - go mod download + +builds: + - + flags: + - -trimpath + goos: + - linux + - windows + goarch: + - amd64 + +archives: + - + format: zip + +snapshot: + name_template: "{{ .Tag }}-next" + +changelog: + sort: asc + filters: + exclude: + - '^docs:' + - '^test:' + +nfpms: + - + file_name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" + + # Default is empty. + vendor: Kazuhiro MUSASHI + + # Your app's homepage. + # Default is empty. + #homepage: https://example.com/ + + # Your app's maintainer (probably you). + # Default is empty. + maintainer: Kazuhiro Musashi + + # Formats to be generated: + formats: + - deb + - rpm + +release: + gitea: + owner: kazu634 + name: moneyforward + + disable: false + +gitea_urls: + api: https://gitea.kazu634.com/api/v1/ + download: https://gitea.kazu634.com + +dockers: + - + image_templates: + - reg.kazu634.com/kazu634/{{ .ProjectName }}:{{ .Tag }} + - reg.kazu634.com/kazu634/{{ .ProjectName }}:latest + + goos: linux + goarch: amd64 + + dockerfile: Dockerfile + + push_flags: + - --tls-verify=false diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3c911c8 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,9 @@ +FROM alpine:latest + +RUN apk add --no-cache libc6-compat tzdata && \ + cp /usr/share/zoneinfo/Asia/Tokyo /etc/localtime && \ + apk del tzdata + +ADD ./moneyforward /usr/local/bin/moneyforward + +CMD ["/usr/local/bin/moneyforward"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2bdd37f --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..be01833 --- /dev/null +++ b/README.md @@ -0,0 +1,98 @@ +# Moneyforward CLI +Chromeを起動して、[マネーフォワード ME](https://moneyforward.com/)を操作するためのツールです。 + + +## ツールでできること +以下のことができます。 + +1. 金融機関からのデータを一括更新する (`./moneyforward collect`) +2. 家計簿から当月もしくは前月の収入・支出詳細をHTMLで取得する (`./moneyforward breaktable`) +3. 資産から資産の内訳をテキスト形式で取得する (`./moneyforward portfolio`) + + +## ユーザー名・パスワードの指定方法 +ユーザー名・パスワードを指定し、コマンドを実行する必要があります。指定方法は複数あります。 + +1. コマンドのフラグとして指定する方法 +2. 環境変数で指定する方法 +3. 設定ファイルで指定する方法 + +### コマンドのフラグとして指定する方法 +コマンドのフラグとして指定する場合は、以下のようにします。 + +```bash +$ ./moneyforward --user foo --password P@ssw0rd +``` + +### 環境変数で指定する方法 +環境変数で指定する場合には、以下のようにします。 + +```bash +$ export MONEYFORWARD_USER="foo" +$ export MONEYFORWARD_PASSWORD="P@ssw0rd" +$ ./moneyforward +``` + +### 設定ファイルで指定する方法 +設定ファイルの中で指定する場合には、以下のようにします。デフォルトでは、`${HOME}/.moneyforward.yaml`を参照します。 + +```bash +$ cat ~/.moneyforward.yaml +user: "foo" +password: "P@ssw0rd" + +$ ./moneyforward +``` + +## tasks +Here are tasks to be executed by `xc` command. + +### Initial Steps +Conduct initial steps. + +```bash +rm go.* +go mod init gitea.kazu634.com/kazu634/$(basename $PWD) +``` + +### Use Cobra +Invoke `cobra-cli init`. + +```bash +which cobra-cli > /dev/null +if [ $? -ne 0 ]; then + echo Install cobra-cli first. Execute "go install github.com/spf13/cobra-cli@latest". + exit 1 +fi + +cobra-cli init +``` + +### Install Go Modules +Install `go` modules to the local directory. In short, execute `go mod vendor`. + +```bash +go mod tidy +go mod vendor +``` + +### Generate .drone.yml +Generate example `.drone.yml` to the local directory. + +```bash +cat .assets/.drone.yml | sed -e "s/__DIR__/$(basename ${PWD})/g" | tee .drone.yml +``` + +### Generate Dockerfile +Generate example `Dockerfile` to the local directory. + +```bash +cat .assets/Dockerfile | sed -e "s/__DIR__/$(basename ${PWD})/g" | tee Dockerfile +``` + +### Generate .goreleaser.yml +Generate example `.goreleaser.yml` to the local directory. + +```bash +cat .assets/.goreleaser.yml | sed -e "s/__DIR__/$(basename ${PWD})/g" | tee .goreleaser.yml +``` diff --git a/cmd/breaktable.go b/cmd/breaktable.go new file mode 100644 index 0000000..c6bd17c --- /dev/null +++ b/cmd/breaktable.go @@ -0,0 +1,85 @@ +/* +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cmd + +import ( + "fmt" + "log" + "os" + "time" + + "gitea.kazu634.com/kazu634/moneyforward/internal/lib/browser" + "github.com/spf13/cobra" +) + +// breaktableCmd represents the breaktable command +var breaktableCmd = &cobra.Command{ + Use: "breaktable", + Short: "A subcommand to fetch the current month account breaktable data", + Long: `A subcommand to fetch the current month account breaktable data`, + Run: func(cmd *cobra.Command, args []string) { + logInfo("Launching a browser...") + browser := browser.Launch() + defer browser.Close() + + browser = login(browser) + + logInfo("navigating to the current month account breaktable page...") + browser.Click("a[href^='/cf']") + + condPrev, err := cmd.Flags().GetBool("previous") + if err != nil { + logInfo("Something wrong has happened.") + os.Exit(1) + } + + if condPrev { + logInfo("Navigating to the previous month account breaktable page...") + browser.Click("#calendar > div.row.span12.monthController > div > div.offset2.span1 > span > span > span.fc-button-content") + + logInfo("Waiting for 10 seconds...") + time.Sleep(10 * time.Second) + } + + logInfo("Fetching the raw table data...") + fmt.Println(browser.GetElmHTML("#ttl_genyokinbreak_table")) + + logInfo("Finished.") + }, +} + +func init() { + rootCmd.AddCommand(breaktableCmd) + + filter := logInit() + log.SetOutput(filter) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // breaktableCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + breaktableCmd.Flags().BoolP("previous", "p", false, "Fetch the previous month's breaktable") +} diff --git a/cmd/collect.go b/cmd/collect.go new file mode 100644 index 0000000..6b436dd --- /dev/null +++ b/cmd/collect.go @@ -0,0 +1,64 @@ +/* +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cmd + +import ( + "gitea.kazu634.com/kazu634/moneyforward/internal/lib/browser" + "github.com/spf13/cobra" +) + +// collectCmd represents the collect command +var collectCmd = &cobra.Command{ + Use: "collect", + Short: "A subcommand to request Moneyforward to collect the latest info", + Long: `A subcommand to request Moneyforward to collect the latest info`, + Run: func(cmd *cobra.Command, args []string) { + logInfo("Launching a browser...") + browser := browser.Launch() + defer browser.Close() + + browser = login(browser) + + logInfo("Navigating to Accounts page...") + browser.Click("a[href^='/accounts") + + logInfo("Update all account info...") + browser.Click("#registration-table > p.aggregation-queue-all > a") + + logInfo("Update Suica info...") + browser.Click("#js-recorrect-form-s-FpVbZXL6vqNgBK-mz8cw > input") + }, +} + +func init() { + rootCmd.AddCommand(collectCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // collectCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // collectCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/log.go b/cmd/log.go new file mode 100644 index 0000000..f8c4f03 --- /dev/null +++ b/cmd/log.go @@ -0,0 +1,42 @@ +package cmd + +import ( + "fmt" + "log" + "os" + + "github.com/hashicorp/logutils" +) + +func logInit() *logutils.LevelFilter { + level, notEmpty := os.LookupEnv("EnvLog") + if !notEmpty { + level = "INFO" + } + + return &logutils.LevelFilter{ + Levels: []logutils.LogLevel{"DEBUG", "INFO", "WARN", "ERROR"}, + MinLevel: logutils.LogLevel(level), + Writer: os.Stderr, + } +} + +func logDebug(msg string) { + target := fmt.Sprintf("[DEBUG] %s", msg) + log.Println(target) +} + +func logInfo(msg string) { + target := fmt.Sprintf("[INFO] %s", msg) + log.Println(target) +} + +func logWarn(msg string) { + target := fmt.Sprintf("[WARN] %s", msg) + log.Println(target) +} + +func logError(msg string) { + target := fmt.Sprintf("[ERROR] %s", msg) + log.Println(target) +} diff --git a/cmd/login.go b/cmd/login.go new file mode 100644 index 0000000..1f0bd1f --- /dev/null +++ b/cmd/login.go @@ -0,0 +1,31 @@ +package cmd + +import ( + "log" + + "gitea.kazu634.com/kazu634/moneyforward/internal/lib/browser" + "github.com/spf13/viper" +) + +func init() { + filter := logInit() + log.SetOutput(filter) +} + +func login(browser *browser.Browser) *browser.Browser { + logInfo("Navigating to https://moneyforward.com/me") + browser.Navigate("https://moneyforward.com/me") + + logInfo("Navigating to sign-in page") + browser.Click("a[href^='/sign_in']") + + logInfo("Input Email address") + browser.Input("input[type=email]", viper.Get("user").(string)) + browser.Click("#submitto") + + logInfo("Input password") + browser.Input("input[name='mfid_user[password]']", viper.Get("password").(string)) + browser.Click("#submitto") + + return browser +} diff --git a/cmd/portfolio.go b/cmd/portfolio.go new file mode 100644 index 0000000..0366b54 --- /dev/null +++ b/cmd/portfolio.go @@ -0,0 +1,112 @@ +/* +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cmd + +import ( + "fmt" + "log" + "strconv" + "strings" + "time" + + "gitea.kazu634.com/kazu634/moneyforward/internal/lib/browser" + "github.com/PuerkitoBio/goquery" + "github.com/spf13/cobra" +) + +const ( + colBank int = iota + colStock + colFund + colReceivables + colMiles +) + +const AmountCol = 1 + +func convInt(target string) int { + tmp := strings.ReplaceAll(target, ",", "") + tmp = strings.ReplaceAll(tmp, "円", "") + + result, _ := strconv.Atoi(tmp) + + return result +} + +// portfolioCmd represents the portfolio command +var portfolioCmd = &cobra.Command{ + Use: "portfolio", + Short: "A subcommand to fetch the portfolio data from Moneyforward", + Long: `A subcommand to fetch the portfolio data from Moneyforward`, + Run: func(cmd *cobra.Command, args []string) { + logInfo("Launching a browser..") + browser := browser.Launch() + defer browser.Close() + + browser = login(browser) + + logInfo("Navigating to the portfolio page...") + browser.Click("a[href^='/bs/portfolio']") + + logInfo("Fetching the portfolio data...") + reader := strings.NewReader(browser.GetElmHTML("#bs-portfolio > div:nth-child(1) > div > div.mf-col-custom-content-body > section > div.row > div > section > table")) + + doc, _ := goquery.NewDocumentFromReader(reader) + + logInfo("Fetching each portfolio item amount...") + var result []int + doc.Find("table").Each(func(i int, tablehtml *goquery.Selection) { + tablehtml.Find("tr").Each(func(indextr int, rowhtml *goquery.Selection) { + rowhtml.Find("th, td").Each(func(indexth int, tablecell *goquery.Selection) { + if indexth == AmountCol { + result = append(result, convInt(strings.TrimSpace(tablecell.Text()))) + } + }) + }) + }) + + logInfo(fmt.Sprintf("Get this data: %v", result)) + + logInfo("Outputting data...") + dateStr := time.Now().Format("2006-01-02") + fmt.Printf("%s\t%d\t%d\t%d\t%d\t%d\n", dateStr, result[colBank], result[colStock], result[colFund], result[colMiles], result[colReceivables]) + + logInfo("Finished.") + }, +} + +func init() { + rootCmd.AddCommand(portfolioCmd) + + filter := logInit() + log.SetOutput(filter) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // portfolioCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // portfolioCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/root.go b/cmd/root.go new file mode 100644 index 0000000..924901d --- /dev/null +++ b/cmd/root.go @@ -0,0 +1,96 @@ +/* +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package cmd + +import ( + "fmt" + "os" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var cfgFile string + +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "moneyforward", + Short: "A CLI to handle Moneyforward", + Long: `A CLI to handle Moneyforward`, + // Uncomment the following line if your bare application + // has an action associated with it: + // Run: func(cmd *cobra.Command, args []string) {}, +} + +// Execute adds all child commands to the root command and sets flags appropriately. +// This is called by main.main(). It only needs to happen once to the rootCmd. +func Execute() { + err := rootCmd.Execute() + if err != nil { + os.Exit(1) + } +} + +func init() { + cobra.OnInitialize(initConfig) + + // Here you will define your flags and configuration settings. + // Cobra supports persistent flags, which, if defined here, + // will be global for your application. + + rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.moneyforward.yaml)") + + rootCmd.PersistentFlags().String("user", "", "Moneyforward User Name") + viper.BindPFlag("user", rootCmd.PersistentFlags().Lookup("user")) + + rootCmd.PersistentFlags().String("password", "", "Moneyforward Password") + viper.BindPFlag("password", rootCmd.PersistentFlags().Lookup("password")) + + // Cobra also supports local flags, which will only run + // when this action is called directly. + // rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} + +// initConfig reads in config file and ENV variables if set. +func initConfig() { + if cfgFile != "" { + // Use config file from the flag. + viper.SetConfigFile(cfgFile) + } else { + // Find home directory. + home, err := os.UserHomeDir() + cobra.CheckErr(err) + + // Search config in home directory with name ".moneyforward" (without extension). + viper.AddConfigPath(home) + viper.SetConfigType("yaml") + viper.SetConfigName(".moneyforward") + } + + viper.SetEnvPrefix("moneyforward") + viper.AutomaticEnv() // read in environment variables that match + + // If a config file is found, read it in. + if err := viper.ReadInConfig(); err == nil { + fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed()) + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..e46394b --- /dev/null +++ b/go.mod @@ -0,0 +1,41 @@ +module gitea.kazu634.com/kazu634/moneyforward + +go 1.22.3 + +require ( + github.com/PuerkitoBio/goquery v1.9.2 + github.com/go-rod/rod v0.116.2 + github.com/hashicorp/logutils v1.0.0 + github.com/spf13/cobra v1.8.1 + github.com/spf13/viper v1.19.0 +) + +require ( + github.com/andybalholm/cascadia v1.3.2 // indirect + github.com/fsnotify/fsnotify v1.7.0 // indirect + github.com/hashicorp/hcl v1.0.0 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/magiconair/properties v1.8.7 // indirect + github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect + github.com/sagikazarmark/locafero v0.4.0 // indirect + github.com/sagikazarmark/slog-shim v0.1.0 // indirect + github.com/sourcegraph/conc v0.3.0 // indirect + github.com/spf13/afero v1.11.0 // indirect + github.com/spf13/cast v1.6.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + github.com/subosito/gotenv v1.6.0 // indirect + github.com/ysmood/fetchup v0.2.3 // indirect + github.com/ysmood/goob v0.4.0 // indirect + github.com/ysmood/got v0.40.0 // indirect + github.com/ysmood/gson v0.7.3 // indirect + github.com/ysmood/leakless v0.9.0 // indirect + go.uber.org/atomic v1.9.0 // indirect + go.uber.org/multierr v1.9.0 // indirect + golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect + golang.org/x/net v0.24.0 // indirect + golang.org/x/sys v0.19.0 // indirect + golang.org/x/text v0.14.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d6b62ea --- /dev/null +++ b/go.sum @@ -0,0 +1,135 @@ +github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE= +github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk= +github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= +github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= +github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= +github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= +github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= +github.com/go-rod/rod v0.116.2 h1:A5t2Ky2A+5eD/ZJQr1EfsQSe5rms5Xof/qj296e+ZqA= +github.com/go-rod/rod v0.116.2/go.mod h1:H+CMO9SCNc2TJ2WfrG+pKhITz57uGNYU43qYHh438Mg= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hashicorp/logutils v1.0.0 h1:dLEQVugN8vlakKOUE3ihGLTZJRB4j+M2cdTm/ORI65Y= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= +github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= +github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= +github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/sagikazarmark/locafero v0.4.0 h1:HApY1R9zGo4DBgr7dqsTH/JJxLTTsOt7u6keLGt6kNQ= +github.com/sagikazarmark/locafero v0.4.0/go.mod h1:Pe1W6UlPYUk/+wc/6KFhbORCfqzgYEpgQ3O5fPuL3H4= +github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE= +github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ= +github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= +github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= +github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= +github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= +github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= +github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= +github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/ysmood/fetchup v0.2.3 h1:ulX+SonA0Vma5zUFXtv52Kzip/xe7aj4vqT5AJwQ+ZQ= +github.com/ysmood/fetchup v0.2.3/go.mod h1:xhibcRKziSvol0H1/pj33dnKrYyI2ebIvz5cOOkYGns= +github.com/ysmood/goob v0.4.0 h1:HsxXhyLBeGzWXnqVKtmT9qM7EuVs/XOgkX7T6r1o1AQ= +github.com/ysmood/goob v0.4.0/go.mod h1:u6yx7ZhS4Exf2MwciFr6nIM8knHQIE22lFpWHnfql18= +github.com/ysmood/gop v0.2.0 h1:+tFrG0TWPxT6p9ZaZs+VY+opCvHU8/3Fk6BaNv6kqKg= +github.com/ysmood/gop v0.2.0/go.mod h1:rr5z2z27oGEbyB787hpEcx4ab8cCiPnKxn0SUHt6xzk= +github.com/ysmood/got v0.40.0 h1:ZQk1B55zIvS7zflRrkGfPDrPG3d7+JOza1ZkNxcc74Q= +github.com/ysmood/got v0.40.0/go.mod h1:W7DdpuX6skL3NszLmAsC5hT7JAhuLZhByVzHTq874Qg= +github.com/ysmood/gotrace v0.6.0 h1:SyI1d4jclswLhg7SWTL6os3L1WOKeNn/ZtzVQF8QmdY= +github.com/ysmood/gotrace v0.6.0/go.mod h1:TzhIG7nHDry5//eYZDYcTzuJLYQIkykJzCRIo4/dzQM= +github.com/ysmood/gson v0.7.3 h1:QFkWbTH8MxyUTKPkVWAENJhxqdBa4lYTQWqZCiLG6kE= +github.com/ysmood/gson v0.7.3/go.mod h1:3Kzs5zDl21g5F/BlLTNcuAGAYLKt2lV5G8D1zF3RNmg= +github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU= +github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI= +go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= +golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= +golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= +golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= +golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= +golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/internal/lib/browser/browser.go b/internal/lib/browser/browser.go new file mode 100644 index 0000000..647858d --- /dev/null +++ b/internal/lib/browser/browser.go @@ -0,0 +1,54 @@ +package browser + +import ( + "github.com/go-rod/rod" + "github.com/go-rod/rod/lib/launcher" +) + +type Browser struct { + launcher *launcher.Launcher + page *rod.Page +} + +func Launch() *Browser { + br := Browser{} + + br.launcher = launcher.New().Headless(true).Set("no-sandbox") + u := br.launcher.MustLaunch() + + // Create blank page first: + br.page = rod.New().ControlURL(u).MustConnect().MustPage() + + return &br +} + +func (br *Browser) Close() { + br.page.MustClose() + br.launcher.Kill() +} + +func (br *Browser) Navigate(url string) { + br.page.MustNavigate(url) + br.page.MustWaitIdle() +} + +func (br *Browser) Click(elm string) { + br.page.MustElement(elm).MustClick() + br.page.MustWaitIdle() +} + +func (br *Browser) Input(elm string, str string) { + br.page.MustElement(elm).MustInput(str) +} + +func (br *Browser) GetElmHTML(elm string) string { + return br.page.MustElement(elm).MustHTML() +} + +func (br *Browser) GetElmText(elm string) string { + return br.page.MustElement(elm).MustText() +} + +func (br *Browser) Screenshot(filename string) { + br.page.MustScrollScreenshot(filename) +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..e9a182f --- /dev/null +++ b/main.go @@ -0,0 +1,28 @@ +/* +Copyright © 2024 Kazuhiro MUSASHI + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ +package main + +import "gitea.kazu634.com/kazu634/moneyforward/cmd" + +func main() { + cmd.Execute() +}