diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e8e100d --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,28 @@ +on: + push: + tags: + - "*" + +permissions: + contents: write + +jobs: + goreleaser: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set up Go + uses: actions/setup-go@v2 + with: + go-version: 1.17 + - name: Run GoReleaser + uses: goreleaser/goreleaser-action@v2 + with: + distribution: goreleaser + version: latest + args: release --rm-dist + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} diff --git a/.goreleaser.yaml b/.goreleaser.yaml index c9fe579..ba2e35b 100644 --- a/.goreleaser.yaml +++ b/.goreleaser.yaml @@ -2,15 +2,11 @@ project_name: gtasks release: prerelease: auto - draft: true name_template: "gtasks {{.Version}}" before: hooks: - # You may remove this if you don't use go modules. - go mod tidy - # you may remove this if you don't need go generate - # - go generate ./... builds: - env: - CGO_ENABLED=0 @@ -27,11 +23,11 @@ archives: windows: Windows 386: i386 amd64: x86_64 - checksum: name_template: "checksums.txt" snapshot: name_template: "{{ incpatch .Version }}-next" + changelog: sort: asc filters: diff --git a/Makefile b/Makefile index f32b997..3fee403 100644 --- a/Makefile +++ b/Makefile @@ -9,8 +9,6 @@ linux: mac: @echo "Building for mac" GOOS=darwin GOARCH=amd64 go build -o ./bin/mac/gtasks - @ cd bin/mac - gtasks all: @echo "Building for every OS and Platform" GOOS=windows GOARCH=386 GO386=softfloat go build -o ./bin/windows/gtasks.exe diff --git a/README.md b/README.md index 6b1ebaf..5cc7d40 100644 --- a/README.md +++ b/README.md @@ -6,59 +6,55 @@ --- -## Currently available commands - -- [x] Login -- [x] View Task-List -- [x] Create Task-List -- [x] Update Task-List title -- [x] Delete Task-List -- [x] View Tasks -- [x] Create Tasks -- [ ] Edit Task -- [x] Mark as completed -- [x] Delete Task +## Docs +Refer to the [docs website](https://gtasks.sidv.dev) to read about available commands. ## Instructions to install (make sure `$HOME/go/bin` is added to `$PATH` + ```bash go install github.com/BRO3886/gtasks@latest ``` -or you can download the binary: + +or you can download the binary: 1. Download the binary for your system (check [releases](https://github.com/BRO3886/google-tasks-cli/releases)) 2. Move to a particular folder, for eg Documents -3. Append the absolute path (use ```pwd```) of the folder to ```PATH``` -4. Execute ```gtasks``` from anywhere +3. Append the absolute path (use `pwd`) of the folder to `PATH` +4. Execute `gtasks` from anywhere ## Instructions to Run and Build from Source: - - Pre-requisites - - Go - - Directions to install - ```bash - git clone https://github.com/BRO3886/google-tasks-cli - ``` - - Directions to execute - - (if you're on linux) - - ```bash - make linux - ./bin/linux/gtasks - ``` - - (if you're on windows) - - ```bash - make windows - ./bin/windows/gtasks - ``` - - Or, you can check out the pre-compiled binaries under **Releases** - - - Usage + +- Pre-requisites + - Go +- Directions to install + +```bash +git clone https://github.com/BRO3886/google-tasks-cli +``` + +- Directions to execute + +(if you're on linux) + +```bash +make linux +./bin/linux/gtasks +``` + +(if you're on windows) + +```bash +make windows +./bin/windows/gtasks +``` + +Or, you can check out the pre-compiled binaries under **Releases** + +- Usage + ``` Usage: gtasks [command] @@ -79,67 +75,97 @@ Use "gtasks [command] --help" for more information about a command. ## Commands ### Help -* To see details about a command + +- To see details about a command + ```bash gtasks help ``` -### Login -* Login +### Auth + +- Login + ```bash gtasks login ``` +- Logout + +```bash +gtasks logout +``` + ### Tasklists -* Viewing Tasklists + +- Viewing Tasklists + ```bash gtasks tasklists view ``` -* Creating a Tasklist +- Creating a Tasklist + ```bash -gtasks tasklists create -t 'title' -gtasks tasklists create --title 'title' +gtasks tasklists add -t 'title' +gtasks tasklists add --title 'title' ``` -* Deleting a Tasklist +- Deleting a Tasklist + ```bash gtasks tasklists rm ``` ### Tasks -* To pre-select tasklist, provide it's title as follows: + +- To pre-select tasklist, provide it's title as follows: + ```bash gtasks tasks -l subcommand [--subcommand-flags] ``` + Examples: + ```bash gtasks tasks [--tasklist|-l] "DSC VIT" view [--include-completed | -i] ``` + **Note:** If the `-l` flag is not provided you will be able to choose a tasklist from the prompt -* Viewing tasks +- Viewing tasks + ```bash gtasks tasks view ``` -* Include completed tasks +- Include completed tasks + ```bash gtasks tasks view -i gtasks tasks view --include-completed ``` -* Adding a task +- Sort options + +```bash +gtasks tasks view ... --sort [due,title,position, default=position] +``` + +- Adding a task + ```bash gtasks tasks add ``` -* Mark task as completed +- Mark task as completed + ```bash gtasks tasks done ``` -* Deleting a task +- Deleting a task + ```bash gtasks tasks rm ``` diff --git a/api/auth.go b/api/auth.go new file mode 100644 index 0000000..ac9c603 --- /dev/null +++ b/api/auth.go @@ -0,0 +1,104 @@ +package api + +import ( + "context" + "encoding/json" + "fmt" + "net/http" + "os" + + "github.com/BRO3886/gtasks/internal/config" + "github.com/BRO3886/gtasks/internal/utils" + "golang.org/x/oauth2" + "google.golang.org/api/option" + "google.golang.org/api/tasks/v1" +) + +func Login(c *oauth2.Config) error { + folderPath := config.GetInstallLocation() + // fmt.Println(folderPath) + tokFile := folderPath + "/token.json" + _, err := tokenFromFile(tokFile) + if err != nil { + tok := getTokenFromWeb(c) + saveToken(tokFile, tok) + return nil + } + return fmt.Errorf("already logged in") +} + +func Logout() error { + folderPath := config.GetInstallLocation() + // fmt.Println(folderPath) + tokFile := folderPath + "/token.json" + return os.Remove(tokFile) +} + +// gets the tasks service +func GetService() *tasks.Service { + c := config.ReadCredentials() + client := getClient(c) + srv, err := tasks.NewService(context.Background(), option.WithHTTPClient(client)) + if err != nil { + utils.ErrorP("Unable to retrieve tasks Client %v", err) + } + + return srv +} + +// Retrieve a token, saves the token, then returns the generated client. +func getClient(c *oauth2.Config) *http.Client { + // The file token.json stores the user's access and refresh tokens, and is + // created automatically when the authorization flow completes for the first + // time. + folderPath := config.GetInstallLocation() + // fmt.Println(folderPath) + tokFile := folderPath + "/token.json" + tok, err := tokenFromFile(tokFile) + if err != nil { + tok = getTokenFromWeb(c) + saveToken(tokFile, tok) + } + return c.Client(context.Background(), tok) +} + +// Request a token from the web, then returns the retrieved token. +func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { + authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) + utils.Warn("Go to the following link in your browser then type the "+ + "authorization code: \n%v\n\nEnter the code: ", authURL) + + var authCode string + if _, err := fmt.Scan(&authCode); err != nil { + utils.ErrorP("Unable to read authorization code: %v", err) + } + + tok, err := config.Exchange(context.TODO(), authCode) + if err != nil { + utils.ErrorP("Unable to retrieve token from web: %v", err) + } + return tok +} + +// Retrieves a token from a local file. +func tokenFromFile(file string) (*oauth2.Token, error) { + f, err := os.Open(file) + if err != nil { + return nil, err + } + defer f.Close() + tok := &oauth2.Token{} + err = json.NewDecoder(f).Decode(tok) + return tok, err +} + +// Saves a token to a file path. +func saveToken(path string, token *oauth2.Token) { + utils.Warn("Saving credential file\n") + f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) + if err != nil { + utils.ErrorP("Unable to cache oauth token: %v", err) + } + defer f.Close() + json.NewEncoder(f).Encode(token) +} diff --git a/cmd/login.go b/cmd/login.go index 66da0ec..f2cf9b4 100644 --- a/cmd/login.go +++ b/cmd/login.go @@ -1,18 +1,10 @@ package cmd import ( - "context" - "encoding/json" - "fmt" - "net/http" - "os" - + "github.com/BRO3886/gtasks/api" "github.com/BRO3886/gtasks/internal/config" "github.com/BRO3886/gtasks/internal/utils" "github.com/spf13/cobra" - "golang.org/x/oauth2" - "google.golang.org/api/option" - "google.golang.org/api/tasks/v1" ) // loginCmd represents the login command @@ -22,80 +14,15 @@ var loginCmd = &cobra.Command{ Long: `This command uses the credentials.json file and makes a request to get your tokens`, Run: func(cmd *cobra.Command, args []string) { c := config.ReadCredentials() - getClient(c) + err := api.Login(c) + if err != nil { + utils.ErrorP("%v\n", err) + return + } + utils.Info("Logged in successfully\n") }, } func init() { rootCmd.AddCommand(loginCmd) } - -// Retrieve a token, saves the token, then returns the generated client. -func getClient(c *oauth2.Config) *http.Client { - // The file token.json stores the user's access and refresh tokens, and is - // created automatically when the authorization flow completes for the first - // time. - folderPath := config.GetInstallLocation() - // fmt.Println(folderPath) - tokFile := folderPath + "/token.json" - tok, err := tokenFromFile(tokFile) - if err != nil { - tok = getTokenFromWeb(c) - saveToken(tokFile, tok) - } - return c.Client(context.Background(), tok) -} - -// Request a token from the web, then returns the retrieved token. -func getTokenFromWeb(config *oauth2.Config) *oauth2.Token { - authURL := config.AuthCodeURL("state-token", oauth2.AccessTypeOffline) - utils.Warn("Go to the following link in your browser then type the "+ - "authorization code: \n%v\n\nEnter the code: ", authURL) - - var authCode string - if _, err := fmt.Scan(&authCode); err != nil { - utils.ErrorP("Unable to read authorization code: %v", err) - } - - tok, err := config.Exchange(context.TODO(), authCode) - if err != nil { - utils.ErrorP("Unable to retrieve token from web: %v", err) - } - return tok -} - -// Retrieves a token from a local file. -func tokenFromFile(file string) (*oauth2.Token, error) { - f, err := os.Open(file) - if err != nil { - return nil, err - } - defer f.Close() - tok := &oauth2.Token{} - err = json.NewDecoder(f).Decode(tok) - return tok, err -} - -// Saves a token to a file path. -func saveToken(path string, token *oauth2.Token) { - utils.Info("Saving credential file to: %s\n", path) - f, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0600) - if err != nil { - utils.ErrorP("Unable to cache oauth token: %v", err) - } - defer f.Close() - json.NewEncoder(f).Encode(token) -} - -// gets the tasks service -func getService() *tasks.Service { - c := config.ReadCredentials() - client := getClient(c) - - srv, err := tasks.NewService(context.Background(), option.WithHTTPClient(client)) - if err != nil { - utils.ErrorP("Unable to retrieve tasks Client %v", err) - } - - return srv -} diff --git a/cmd/logout.go b/cmd/logout.go new file mode 100644 index 0000000..03d6eb3 --- /dev/null +++ b/cmd/logout.go @@ -0,0 +1,26 @@ +package cmd + +import ( + "github.com/BRO3886/gtasks/api" + "github.com/BRO3886/gtasks/internal/utils" + "github.com/spf13/cobra" +) + +// logoutCmd represents the logout command +var logoutCmd = &cobra.Command{ + Use: "logout", + Short: "Logout currently signed in user", + Long: `Logout currently signed in user.`, + Run: func(cmd *cobra.Command, args []string) { + err := api.Logout() + if err != nil { + utils.ErrorP("%v\n", err) + return + } + utils.Info("Logged out successfully\n") + }, +} + +func init() { + rootCmd.AddCommand(logoutCmd) +} diff --git a/cmd/tasklists.go b/cmd/tasklists.go index d081408..30dbeda 100644 --- a/cmd/tasklists.go +++ b/cmd/tasklists.go @@ -1,8 +1,6 @@ package cmd import ( - "errors" - "github.com/BRO3886/gtasks/api" "github.com/BRO3886/gtasks/internal/utils" "github.com/fatih/color" @@ -29,14 +27,6 @@ var tasklistsCmd = &cobra.Command{ gtasks tasklists rm `, - Args: func(cmd *cobra.Command, args []string) error { - if len(args) < 1 { - return errors.New("requires at least one arg. Use -h to show the list of available commands") - } - return nil - }, - Run: func(cmd *cobra.Command, args []string) { - }, } var showlistsCmd = &cobra.Command{ @@ -44,7 +34,7 @@ var showlistsCmd = &cobra.Command{ Short: "view tasklists", Long: `view task lists for the account currently signed in`, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() list, err := api.GetTaskLists(srv) if err != nil { utils.ErrorP("Error: %v\n", err) @@ -56,12 +46,12 @@ var showlistsCmd = &cobra.Command{ }, } -var createlistsCmd = &cobra.Command{ - Use: "create", - Short: "create tasklist", - Long: `Create tasklist for the currently signed in account`, +var addListcmd = &cobra.Command{ + Use: "add", + Short: "add tasklist", + Long: `add tasklist for the currently signed in account`, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() if title == "" { utils.Warn("%s\n", "Title should not be empty. Use -t for title.\nExamples:\ngtasks tasklists create -t <TITLE>\ngtasks tasklists create --title <TITLE>") return @@ -81,7 +71,7 @@ var removeListCmd = &cobra.Command{ Short: "remove tasklist", Long: `Remove a tasklist for the currently signed in account`, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() list, err := api.GetTaskLists(srv) if err != nil { utils.ErrorP("Error %v", err) @@ -118,7 +108,7 @@ var updateTitleCmd = &cobra.Command{ Short: "update tasklist title", Long: `Update tasklist title for the currently signed in account`, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() if title == "" { utils.Warn("Title should not be empty. Use -t for title.\nExamples:\ngtasks tasklists update -t <TITLE>\ngtasks tasklists update --title <TITLE>\n") return @@ -157,8 +147,8 @@ var updateTitleCmd = &cobra.Command{ var title string func init() { - createlistsCmd.Flags().StringVarP(&title, "title", "t", "", "title of task list (required)") + addListcmd.Flags().StringVarP(&title, "title", "t", "", "title of task list (required)") updateTitleCmd.Flags().StringVarP(&title, "title", "t", "", "title of task list (required)") - tasklistsCmd.AddCommand(showlistsCmd, createlistsCmd, removeListCmd, updateTitleCmd) + tasklistsCmd.AddCommand(showlistsCmd, addListcmd, removeListCmd, updateTitleCmd) rootCmd.AddCommand(tasklistsCmd) } diff --git a/cmd/tasks.go b/cmd/tasks.go index aff2fcb..3e2faf6 100644 --- a/cmd/tasks.go +++ b/cmd/tasks.go @@ -45,7 +45,7 @@ var viewTasksCmd = &cobra.Command{ tasklist for the currently signed in account `, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() tList := getTaskLists(srv) utils.Print("Tasks in %s:\n", tList.Title) @@ -101,7 +101,7 @@ var createTaskCmd = &cobra.Command{ tasklist for the currently signed in account `, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() tList := getTaskLists(srv) utils.Warn("Creating task in %s\n", tList.Title) @@ -161,7 +161,7 @@ var markCompletedCmd = &cobra.Command{ in a selected tasklist for the currently signed in account `, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() tList := getTaskLists(srv) tID := tList.Id @@ -192,7 +192,7 @@ var deleteTaskCmd = &cobra.Command{ for the currently signed in account `, Run: func(cmd *cobra.Command, args []string) { - srv := getService() + srv := api.GetService() tList := getTaskLists(srv) tID := tList.Id diff --git a/docs/content/docs/task commands/index.md b/docs/content/docs/task commands/index.md index 332942d..5a663c2 100644 --- a/docs/content/docs/task commands/index.md +++ b/docs/content/docs/task commands/index.md @@ -1,19 +1,21 @@ --- -title: 'Task commands' +title: "Task commands" draft: false weight: 4 summary: View, create, and delete tasks in a tasklist --- ## Help command -* to view inline help for all the commands + +- to view inline help for all the commands + ``` ❯ gtasks tasks help View, create, list and delete tasks in a tasklist for the currently signed in account. Usage: - [WITH LIST FLAG] + [WITH LIST FLAG] gtasks tasks -l "<task-list name>" view|add|rm|done [WITHOUT LIST FLAG] @@ -37,18 +39,22 @@ Use "gtasks tasks [command] --help" for more information about a command. ``` ## Add Task -* First select the tasklist + +- First select the tasklist + ``` ❯ gtasks tasks add -Use the arrow keys to navigate: ↓ ↑ → ← -? Select Tasklist: +Use the arrow keys to navigate: ↓ ↑ → ← +? Select Tasklist: ▸ DSC VIT Daily todo Life Placement todo ↓ To watch ``` -* Then add task + +- Then add task + ``` ❯ gtasks tasks add ✔ DSC VIT @@ -57,24 +63,30 @@ Title: testing Note: testing Due Date: 12 July 2021 ``` -* For a shorthand syntax use: + +- For a shorthand syntax use: + ``` gtasks tasks add -l "DSC VIT" --title <some title> [--note <some note> | --due <some due date>] ``` ## View all tasks in a tasklist -* First select tasklist + +- First select tasklist + ``` ❯ gtasks tasks view -Use the arrow keys to navigate: ↓ ↑ → ← -? Select Tasklist: +Use the arrow keys to navigate: ↓ ↑ → ← +? Select Tasklist: ▸ DSC VIT Daily todo Life Placement todo ↓ To watch ``` -* Then you'll be able to see tasks in a tabular format + +- Then you'll be able to see tasks in a tabular format + ``` ❯ gtasks tasks view ✔ DSC VIT @@ -92,13 +104,17 @@ Tasks in DSC VIT: | 6 | Keats ios | Check up on the apple dev | ✖ | 08 July 2021 | | | | account status - Swamita | | | ``` -* To include completed tasks: + +- To include completed tasks: + ``` ❯ gtasks tasks view --include-completed ❯ gtasks tasks -l "DSC VIT" view -i ``` + Example: + ``` ❯ gtasks tasks -l "DSC VIT" view -i Tasks in DSC VIT: @@ -122,28 +138,42 @@ Tasks in DSC VIT: | 11 | testing | testing 1 2 3 | ✔ | No Due Date | | 12 | abdcd | ahfje | ✔ | 10 July 2021 | ``` -* To show completed tasks: + +- To show completed tasks: + ``` ❯ gtasks tasks view --completed ❯ gtasks tasks -l "DSC VIT" view --completed ``` +- To change sort order (due date, title, position, defeault=position) + +``` +❯ gtasks tasks view --sort due + +❯ gtasks tasks -l "DSC VIT" view --sort title +``` + ## Mark task as done -* With prompt: + +- With prompt: + ``` ❯ gtasks tasks done ✔ DSC VIT Tasks in DSC VIT: -Use the arrow keys to navigate: ↓ ↑ → ← -? Select Task: +Use the arrow keys to navigate: ↓ ↑ → ← +? Select Task: ▸ testing HopeHouse Vitty App Publishing Cadence ↓ Keats android ``` -* For a shorter syntax: + +- For a shorter syntax: + ``` ❯ gtasks tasks view -l "DSC VIT" Tasks in DSC VIT: @@ -161,24 +191,28 @@ Tasks in DSC VIT: | | | account status - Swamita | | | ❯ gtasks tasks done -l "DSC VIT" 1 -Marked as complete: testing +Marked as complete: testing ``` ## Delete a task -* With prompt: + +- With prompt: + ``` ❯ gtasks tasks rm ✔ DSC VIT Tasks in DSC VIT: -Use the arrow keys to navigate: ↓ ↑ → ← -? Select Task: +Use the arrow keys to navigate: ↓ ↑ → ← +? Select Task: ▸ testing HopeHouse Vitty App Publishing Cadence ↓ Keats android ``` -* For a shorter syntax: + +- For a shorter syntax: + ``` ❯ gtasks tasks view -l "DSC VIT" Tasks in DSC VIT: @@ -196,5 +230,5 @@ Tasks in DSC VIT: | | | account status - Swamita | | | ❯ gtasks tasks rm -l "DSC VIT" 1 -Deleted: testing +Deleted: testing ``` diff --git a/docs/content/docs/tasklist commands/index.md b/docs/content/docs/tasklist commands/index.md index b3efb13..b38feef 100644 --- a/docs/content/docs/tasklist commands/index.md +++ b/docs/content/docs/tasklist commands/index.md @@ -1,12 +1,14 @@ --- -title: 'Tasklist commands' +title: "Tasklist commands" draft: false weight: 3 summary: View and create tasklists for currently signed-in account. --- ## Help command -* to view inline help for all the commands + +- to view inline help for all the commands + ``` ❯ gtasks tasklists --help @@ -39,21 +41,27 @@ Use "gtasks tasklists [command] --help" for more information about a command. ``` ## Create Tasklist + Examples: + ``` -❯ gtasks tasklists create --title "some title" +❯ gtasks tasklists add --title "some title" -❯ gtasks tasklists create -t "some title" +❯ gtasks tasklists add -t "some title" ``` ## View all Tasklists + Example: + ``` ❯ gtasks tasklists view ``` ## Update a tasklist title + Examples: + ``` ❯ gtasks tasklists update --title "some title" @@ -61,15 +69,17 @@ Examples: ``` ## Delete a tasklist + Examples: + ``` ❯ gtasks tasklists rm -Use the arrow keys to navigate: ↓ ↑ → ← -? Select Tasklist: +Use the arrow keys to navigate: ↓ ↑ → ← +? Select Tasklist: ▸ VIT Daily todo personal projects To watch ↓ DSC VIT - + ``` diff --git a/internal/config/credentials.go b/internal/config/credentials.go index 435d5fe..a2f2e66 100644 --- a/internal/config/credentials.go +++ b/internal/config/credentials.go @@ -25,21 +25,7 @@ func ReadCredentials() *oauth2.Config { } func GenerateConfig() { - credString := ` - { - "installed": { - "client_id": "415973160530-1onpd10rt7vl0dc79sh0hf8qb7ilc0bo.apps.googleusercontent.com", - "project_id": "tasks-cli-tool-1604690538991", - "auth_uri": "https://accounts.google.com/o/oauth2/auth", - "token_uri": "https://oauth2.googleapis.com/token", - "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", - "client_secret": "s-QOvdsBvXh7vgIGJSgojFa7", - "redirect_uris": [ - "urn:ietf:wg:oauth:2.0:oob", - "http://localhost" - ] - } - }` + credString := `{"installed":{"client_id":"415973160530-1onpd10rt7vl0dc79sh0hf8qb7ilc0bo.apps.googleusercontent.com","project_id":"tasks-cli-tool-1604690538991","auth_uri":"https://accounts.google.com/o/oauth2/auth","token_uri":"https://oauth2.googleapis.com/token","auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs","client_secret":"s-QOvdsBvXh7vgIGJSgojFa7","redirect_uris":["urn:ietf:wg:oauth:2.0:oob","http://localhost"]}}` mode := int(0666) folderPath := GetInstallLocation() ioutil.WriteFile(folderPath+"/config.json", []byte(credString), os.FileMode(mode)) diff --git a/main.go b/main.go index 976fc68..cd09790 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ /* -Copyright © 2020 SIDDHARTHA VARMA <siddverma1999@gmail.com> +Copyright © 2022 SIDDHARTHA VARMA <siddverma1999@gmail.com> Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.