├── .gitignore ├── .travis.yml ├── Dockerfile ├── LICENSE ├── README.md ├── app ├── config.go ├── config_test.go ├── parse.go ├── parse_test.go ├── request.go ├── starme.go └── starring.go ├── arrays ├── array.go └── array_test.go ├── build.sh ├── cmd └── cli.go ├── images ├── README.md ├── star-go-c.gif ├── star-go-ls.gif └── token │ ├── step1.png │ ├── step2.png │ ├── step3.png │ ├── step4.png │ ├── step5.png │ └── step6.png ├── logo.png └── main.go /.gitignore: -------------------------------------------------------------------------------- 1 | *.exe 2 | 3 | 4 | 5 | star.json 6 | 7 | star-go 8 | *.star-go* 9 | *.*config 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | 3 | go: 4 | - "1.10.x" 5 | 6 | #before_install: mkdir -p ~/.star-go 7 | 8 | script: go test ./... 9 | notifications: 10 | email: false -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM golang:1.8 2 | 3 | WORKDIR /go/src/github.com/teyushen/star-go 4 | COPY . . 5 | 6 | RUN mkdir .star-go && rm -rf .git .gitignore .idea .DS_Store 7 | 8 | RUN go get -d -v github.com/teyushen/star-go 9 | RUN go install -v github.com/teyushen/star-go 10 | 11 | 12 | ENTRYPOINT ["star-go"] 13 | #CMD ["star-go"] 14 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Dennis 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![step1](https://github.com/teyushen/star-go/blob/master/logo.png) 2 | 3 | 4 | [![Build Status](https://travis-ci.org/teyushen/star-go.svg?branch=master)](https://travis-ci.org/teyushen/star-go) ![MIT](https://img.shields.io/packagist/l/doctrine/orm.svg) 5 | 6 | ## Features 7 | 8 | Sometimes we want to trace Github Projects we are interesed. And we always want to know how many numbers of ⭐️ they get now. 9 | 10 | This project can easily help us focus on projects we are interested, and can also help us order these projects by numbers of ⭐️. 11 | 12 | 13 | ## Demo 14 | 15 | - ![step1](https://github.com/teyushen/star-go/blob/master/images/star-go-ls.gif) 16 | 17 | - ![step1](https://github.com/teyushen/star-go/blob/master/images/star-go-c.gif) 18 | 19 | 20 | ## Prerequisites 21 | 22 | * Create a github token ([how to generate a github token](https://github.com/teyushen/star-go/tree/master/images)) 23 | 24 | > You will get something like `3061ba66c81c7590e3b2a3bd3055fece429fb531` 25 | 26 | ## Determine how to use star-go 27 | 28 | * [Golang](https://golang.org/doc/install) 29 | * [Docker](https://docs.docker.com/install/) 30 | 31 | ## Use with Golang 32 | 33 | 1. Install star-go 34 | 35 | ``` 36 | $ go get github.com/teyushen/star-go 37 | $ go install github.com/teyushen/star-go 38 | ``` 39 | 40 | 41 | 2. Initial the star-go 42 | 43 | ``` 44 | $ star-go init 45 | ``` 46 | 47 | > e.g. 48 | > `$ star-go init 3061ba66c81c7590e3b2a3bd3055fece429fb531` 49 | 50 | 51 | 3. Add you interesting github repositories 52 | 53 | ``` 54 | $ star-go focus ... 55 | ``` 56 | 57 | > e.g. 58 | > `$ star-go focus teyushen/star-go teyushen/dockerfile golang/go` 59 | 60 | 4. Order the numbers of size of repositories you are interested 61 | 62 | ``` 63 | $ star-go compare 64 | ``` 65 | 66 | ## Use with Docker 67 | 68 | 69 | 1. Create a directory 70 | 71 | - Linux or Mac 72 | 73 | ``` 74 | $ mkdir -p ~/.star-go 75 | ``` 76 | 77 | - Windows 78 | 79 | ``` 80 | $ mkdir C:\.star-go 81 | ``` 82 | 83 | 2. Initial the star-go 84 | 85 | - Linux or Mac 86 | 87 | ``` 88 | $ docker run -it -v ~/.star-go:/root/.star-go --rm sldennis/star-go init 89 | ``` 90 | 91 | > e.g. 92 | > `docker run -it -v ~/.star-go:/root/.star-go --rm sldennis/star-go init 3061ba66c81c7590e3b2a3bd3055fece429fb531 93 | ` 94 | 95 | - Windows 96 | 97 | ``` 98 | $ docker run -it -v C:/.star-go:/root/.star-go --rm sldennis/star-go init 99 | ``` 100 | 101 | > e.g. 102 | > `docker run -it -v C:/.star-go:/root/.star-go --rm sldennis/star-go init 3061ba66c81c7590e3b2a3bd3055fece429fb531 103 | ` 104 | 105 | 3. Add you interesting github repositories 106 | 107 | - Linux or Mac 108 | 109 | ``` 110 | $ docker run -it -v ~/.star-go:/root/.star-go --rm sldennis/star-go focus ... 111 | ``` 112 | 113 | > e.g. 114 | > `docker run -it -v ~/.star-go:/root/.star-go --rm sldennis/star-go focus teyushen/star-go teyushen/dockerfile golang/go` 115 | 116 | - Windows 117 | 118 | ``` 119 | $ docker run -it -v C:/.star-go:/root/.star-go --rm sldennis/star-go focus ... 120 | ``` 121 | 122 | > e.g. 123 | > `docker run -it -v C:/.star-go:/root/.star-go --rm sldennis/star-go focus teyushen/star-go teyushen/dockerfile golang/go` 124 | 4. Order the numbers of size of repositories you are interested 125 | 126 | - Linux or Mac 127 | 128 | ``` 129 | $ docker run -it -v ~/.star-go:/root/.star-go --rm sldennis/star-go compare 130 | ``` 131 | 132 | - Windows 133 | 134 | ``` 135 | $ docker run -it -v C:/.star-go:/root/.star-go --rm sldennis/star-go compare 136 | ``` 137 | 138 | ## Authors 139 | 140 | - [Blair Lee](https://github.com/blairlee227) - *Logo Designer* - [dribbble](https://dribbble.com/blairlee) 141 | 142 | ## License 143 | 144 | MIT 145 | -------------------------------------------------------------------------------- /app/config.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "io/ioutil" 5 | "encoding/json" 6 | "log" 7 | "github.com/teyushen/star-go/arrays" 8 | "os/user" 9 | "strconv" 10 | "os" 11 | ) 12 | 13 | const basePath = "/.star-go" 14 | var usr, _ = user.Current() 15 | 16 | 17 | type User struct { 18 | Token string 19 | } 20 | 21 | type RepoConfig struct { 22 | Owner string 23 | RepoNames []string 24 | } 25 | 26 | func CheckAndCreatePath() { 27 | if _, err := os.Stat(usr.HomeDir + basePath); os.IsNotExist(err) { 28 | os.Mkdir(usr.HomeDir + basePath, os.ModePerm) 29 | } 30 | } 31 | 32 | func SaveUser(u User) { 33 | writeToConfig(usr.HomeDir + basePath + "/.star-go-config", u) 34 | } 35 | 36 | func GetUser() User { 37 | 38 | content, err := ioutil.ReadFile(usr.HomeDir + basePath + "/.star-go-config") 39 | if err != nil { 40 | log.Fatal(err) 41 | } 42 | 43 | user := User{} 44 | json.Unmarshal(content, &user) 45 | 46 | log.Printf("Filename: [%s/.star-go-config] -> %s", usr.HomeDir + basePath, user) 47 | 48 | return user 49 | } 50 | 51 | func SaveRepos(repos []RepoConfig, number int) { 52 | 53 | repoConfigs := make([]RepoConfig, 0) 54 | for _, repo := range repos { 55 | needMerge := mergeRepo(repoConfigs, repo) 56 | if !needMerge { 57 | repoConfigs = append(repoConfigs, repo) 58 | } 59 | } 60 | writeToConfig(usr.HomeDir + basePath + "/.watching" + strconv.Itoa(number), repoConfigs) 61 | } 62 | 63 | func mergeRepo(existRepos []RepoConfig, repo RepoConfig) bool { 64 | 65 | for index, value := range existRepos { 66 | if value.Owner == repo.Owner { 67 | for _, name := range repo.RepoNames { 68 | if !arrays.Contains(value.RepoNames, name) { 69 | existRepos[index].RepoNames = append(existRepos[index].RepoNames, name) 70 | } 71 | } 72 | return true 73 | } 74 | } 75 | return false 76 | } 77 | 78 | func AppendRepos(number int, repos ...RepoConfig) []RepoConfig { 79 | 80 | repoConfigs := GetRepos(number) 81 | for _, repo := range repos { 82 | needMerge := mergeRepo(repoConfigs, repo) 83 | if !needMerge { 84 | repoConfigs = append(repoConfigs, repo) 85 | } 86 | } 87 | SaveRepos(repoConfigs, number) 88 | return repoConfigs 89 | } 90 | 91 | func GetRepos(number int) []RepoConfig { 92 | 93 | content, err := ioutil.ReadFile(usr.HomeDir + basePath + "/.watching" + strconv.Itoa(number)) 94 | if err != nil { 95 | log.Fatal(err) 96 | } 97 | 98 | repos := make([]RepoConfig, 0) 99 | json.Unmarshal(content, &repos) 100 | 101 | log.Printf("Filename: [%s/.watching%d] -> %s", usr.HomeDir + basePath, number, content) 102 | 103 | return repos 104 | } 105 | 106 | func writeToConfig(filename string, str interface{}) { 107 | b, _ := json.Marshal(str) 108 | 109 | err := ioutil.WriteFile(filename, b, 0777) 110 | 111 | if err != nil { 112 | panic(err) 113 | } 114 | return 115 | } 116 | -------------------------------------------------------------------------------- /app/config_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "testing" 5 | "os" 6 | ) 7 | 8 | func TestMain(m *testing.M) { 9 | CheckAndCreatePath() 10 | retCode := m.Run() 11 | os.Exit(retCode) 12 | } 13 | 14 | func TestSaveUser(t *testing.T) { 15 | SaveUser(User{"123456"}) 16 | user := GetUser() 17 | 18 | if user.Token != "123456" { 19 | t.Errorf("Expected User Token is '123456', but got '%s'", user.Token) 20 | return 21 | } 22 | 23 | } 24 | 25 | func TestSaveRepos(t *testing.T) { 26 | repo1 := RepoConfig{"me", []string{"star-go", "star-go1"}} 27 | repo2 := RepoConfig{"you", []string{"no-star", "no-star1"}} 28 | SaveRepos([]RepoConfig{repo1, repo2}, 1) 29 | repos := GetRepos(1) 30 | 31 | if len(repos) != 2 { 32 | t.Errorf("Expected repo size is '2', but got '%v'", len(repos)) 33 | return 34 | } 35 | 36 | if o := repos[0].Owner; o != "me" { 37 | t.Errorf("Expected Owner is 'me', but got '%s'", o) 38 | return 39 | } 40 | if o := repos[1].Owner; o != "you" { 41 | t.Errorf("Expected Owner is 'you', but got '%s'", o) 42 | return 43 | } 44 | if size := len(repos[0].RepoNames); size != 2 { 45 | t.Errorf("Expected me repo size is '2', but got '%d'", size) 46 | return 47 | } 48 | if size := len(repos[1].RepoNames); size != 2 { 49 | t.Errorf("Expected you repo size is '2', but got '%d'", size) 50 | return 51 | } 52 | 53 | } 54 | 55 | func TestAppendRepos(t *testing.T) { 56 | TestSaveRepos(t) 57 | repo1 := RepoConfig{"me", []string{"star-go2", "star-go3"}} 58 | repo2 := RepoConfig{"they", []string{"star1", "star3"}} 59 | AppendRepos(1, repo1, repo2) 60 | repos := GetRepos(1) 61 | 62 | if len(repos) != 3 { 63 | t.Errorf("Expected repo size is '3', but got '%v'", len(repos)) 64 | return 65 | } 66 | 67 | if size := len(repos[0].RepoNames); size != 4 { 68 | t.Errorf("Expected RepoName size is 4, but got '%d'", size) 69 | return 70 | } 71 | 72 | if o := repos[2].Owner; o != "they" { 73 | t.Errorf("Expected Owner is 'they', but got '%s'", o) 74 | return 75 | } 76 | if size := len(repos[2].RepoNames); size != 2 { 77 | t.Errorf("Expected RepoName size is 2, but got '%d'", size) 78 | return 79 | } 80 | 81 | } 82 | 83 | func TestMergeRepo(t *testing.T) { 84 | 85 | existRepos := make([]RepoConfig, 0) 86 | existRepos = append(existRepos, RepoConfig{"Dennis", []string{"star-go", "oauth2"}}) 87 | 88 | repo1 := RepoConfig{"Dennis", []string{"23"}} 89 | repo2 := RepoConfig{"golang", []string{"go"}} 90 | 91 | 92 | if !mergeRepo(existRepos, repo1) { 93 | t.Error("Expected true, but got false") 94 | return 95 | } 96 | if mergeRepo(existRepos, repo2) { 97 | t.Error("Expected false, but got true") 98 | return 99 | } 100 | 101 | } 102 | 103 | 104 | -------------------------------------------------------------------------------- /app/parse.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "strings" 5 | "errors" 6 | ) 7 | 8 | func ParseToRepo(str string) (RepoConfig, error) { 9 | if strings.ContainsAny(str, "/") && len(strings.Split(str, "/")) == 2 { 10 | return RepoConfig{strings.Split(str, "/")[0], []string{strings.Split(str, "/")[1]}}, nil 11 | } 12 | return RepoConfig{}, errors.New("Can not parse this string: " + str) 13 | } 14 | -------------------------------------------------------------------------------- /app/parse_test.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import "testing" 4 | 5 | func TestParseToRepo(t *testing.T) { 6 | str1 := "teyushen/star-go" 7 | str2 := "teyushen" 8 | str3 := "teyushen/star-go/star-go" 9 | 10 | repoConfig1, error1 := ParseToRepo(str1) 11 | 12 | if error1 != nil || repoConfig1.Owner != "teyushen" || repoConfig1.RepoNames[0] != "star-go" { 13 | t.Errorf("Expected owner: 'teyushen', repoName: 'star-go', but got owner:'%s', repoNAme: %s", repoConfig1.Owner, repoConfig1.RepoNames[0]) 14 | return 15 | } 16 | 17 | _, error2 := ParseToRepo(str2) 18 | 19 | if error2 == nil { 20 | t.Errorf("something wrong") 21 | return 22 | } 23 | 24 | _, error3 := ParseToRepo(str3) 25 | 26 | if error3 == nil { 27 | t.Errorf("something wrong") 28 | return 29 | } 30 | 31 | } 32 | -------------------------------------------------------------------------------- /app/request.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "net/http" 5 | "log" 6 | ) 7 | 8 | func request(method, token string, url string) *http.Response { 9 | client := &http.Client{} 10 | req, _ := http.NewRequest(method, url, nil) 11 | req.Header.Set("Authorization", "token " + token) 12 | resp, err := client.Do(req) 13 | if err != nil { 14 | log.Fatal(err) 15 | } 16 | 17 | return resp 18 | } -------------------------------------------------------------------------------- /app/starme.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "fmt" 5 | ) 6 | 7 | func StarOnMe(u User, url string) { 8 | 9 | resp := request("PUT", u.Token, url) 10 | 11 | if resp.StatusCode == 204 { 12 | fmt.Println("Thanks for giving a star to me!") 13 | } 14 | } 15 | 16 | func RemoveStarOnMe(u User, url string) { 17 | 18 | resp := request("DELETE", u.Token, url) 19 | 20 | if resp.StatusCode == 204 { 21 | fmt.Println("Oh No! Why you do this to me?") 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/starring.go: -------------------------------------------------------------------------------- 1 | package app 2 | 3 | import ( 4 | "sort" 5 | "io/ioutil" 6 | "encoding/json" 7 | "fmt" 8 | "strings" 9 | "log" 10 | ) 11 | 12 | func GetRepoInfo(u User, url string) RepoInformation { 13 | 14 | resp := request("GET", u.Token, url) 15 | 16 | bodyText, _ := ioutil.ReadAll(resp.Body) 17 | 18 | if strings.Contains(string(bodyText), "Bad credentials") { 19 | fmt.Println(string(bodyText), "Token: ", u.Token) 20 | } 21 | 22 | reposInfo := RepoInformation{} 23 | json.Unmarshal(bodyText, &reposInfo) 24 | 25 | return reposInfo 26 | } 27 | 28 | func CollectAllReposInfo(u User, urls ...string) []RepoInformation { 29 | 30 | reposInfo := make([]RepoInformation, 0) 31 | ch := make(chan RepoInformation) 32 | 33 | for _, url := range urls { 34 | go func() { 35 | ch <- GetRepoInfo(u, url) 36 | }() 37 | reposInfo = append(reposInfo, <- ch) 38 | } 39 | 40 | return reposInfo 41 | } 42 | 43 | func PrepareReposInfo(number int) []RepoInformation{ 44 | u := GetUser() 45 | repos := GetRepos(number) 46 | 47 | arr := make([]string, 0) 48 | for _, repo := range repos { 49 | //arr = append(arr, "https://api.github.com/users/" + repo.Owner + "/repos") 50 | //arr = append(arr, "https://api.github.com/orgs/" + repo.Owner + "/repos") 51 | for _, repoName := range repo.RepoNames { 52 | arr = append(arr, "https://api.github.com/repos/" + repo.Owner + "/" + repoName) 53 | } 54 | } 55 | 56 | log.Println(arr) 57 | if len(arr) == 0 { 58 | fmt.Println("Can not find any match repository") 59 | } 60 | // 61 | //reposInfo := CollectAllReposInfo(u, arr...) 62 | //compareReposInfo := make([]RepoInformation, 0) 63 | //for _, repo := range repos { 64 | // for _, repoInfo := range reposInfo { 65 | // //log.Println(repo.Owner, repoInfo.Owner.Login, arrays.Contains(repo.RepoNames, repoInfo.Name)) 66 | // if repo.Owner == repoInfo.Owner.Login && arrays.Contains(repo.RepoNames, repoInfo.Name) { 67 | // compareReposInfo = append(compareReposInfo, repoInfo) 68 | // } 69 | // 70 | // } 71 | //} 72 | return CollectAllReposInfo(u, arr...) 73 | } 74 | 75 | type byStar []RepoInformation 76 | 77 | func (a byStar) Len() int { return len(a) } 78 | func (a byStar) Swap(i, j int) { a[i], a[j] = a[j], a[i] } 79 | func (a byStar) Less(i, j int) bool { return a[i].StargazersCount > a[j].StargazersCount } 80 | 81 | 82 | func CompareStar(reposInfo []RepoInformation) { 83 | 84 | sort.Sort(byStar(reposInfo)) 85 | 86 | //fmt.Println("|Top|---------------|star|---------------|language|--------------------|name|") 87 | fmt.Printf("%5v %15v %15v %50v \n", "TOP", "STAR", "LANGUAGE", "FULLNAME") 88 | for index, value := range reposInfo { 89 | fmt.Printf("%5v %15v %15v %50v \n", index+1, value.StargazersCount, value.Language, value.FullName) 90 | } 91 | 92 | } 93 | 94 | type Owner struct { 95 | Login string `json:"login"` 96 | } 97 | 98 | type RepoInformation struct { 99 | Owner Owner `json:"owner"` 100 | Language string `json:"language"` 101 | Name string `json:name` 102 | FullName string `json:"full_name"` 103 | StargazersCount int `json:"stargazers_count"` 104 | } -------------------------------------------------------------------------------- /arrays/array.go: -------------------------------------------------------------------------------- 1 | package arrays 2 | 3 | 4 | 5 | func Contains(slice []string, str string) bool { 6 | for _, value := range slice { 7 | if value == str { 8 | return true 9 | } 10 | } 11 | return false 12 | } -------------------------------------------------------------------------------- /arrays/array_test.go: -------------------------------------------------------------------------------- 1 | package arrays 2 | 3 | import "testing" 4 | 5 | func TestContains(t *testing.T) { 6 | str1 := "teyushen/star-go" 7 | str2 := "teyushen" 8 | 9 | 10 | strArray := make([]string, 0) 11 | strArray = append(strArray, "teyushen", "Golang") 12 | 13 | Contains(strArray, str2) 14 | 15 | if Contains(strArray, str1) { 16 | t.Errorf("it should be false") 17 | return 18 | } 19 | 20 | if !Contains(strArray, str2) { 21 | t.Errorf("it should be true") 22 | return 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /build.sh: -------------------------------------------------------------------------------- 1 | docker build -t sldennis/star-go . 2 | docker push sldennis/star-go 3 | -------------------------------------------------------------------------------- /cmd/cli.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "gopkg.in/urfave/cli.v2" 5 | "fmt" 6 | "github.com/teyushen/star-go/app" 7 | "os" 8 | ) 9 | 10 | const StarGoUrl = "https://api.github.com/user/starred/teyushen/star-go" 11 | const StarredUrl = "https://api.github.com/users/teyushen/starred" 12 | 13 | func Cli() { 14 | 15 | app := &cli.App{ 16 | Name: "star-go", 17 | Version: "0.1.0", 18 | Usage: "A cli help you easy to show how many stars on Github", 19 | Description: "This can help us easily compare how many stars of Repository in Github we interested", 20 | Authors: []*cli.Author{ 21 | {Name: "Dennis", Email: "teyushen@gmail.com"}, 22 | }, 23 | Flags: []cli.Flag{ 24 | //&cli.StringFlag{Name: "name", Value: "bob", Usage: "a name to say"}, 25 | }, 26 | Commands: []*cli.Command{ 27 | { 28 | Name: "init", 29 | Aliases: []string{}, 30 | ArgsUsage: "", 31 | //UsageText: "star-go init TOKEN", 32 | Usage: "Use it to initial the basic configuration", 33 | Description: "This is how we add Github token into our config", 34 | Action: func(c *cli.Context) error { 35 | if c.NArg() == 1 { 36 | token := c.Args().First() 37 | fmt.Println("Your Github token is: ", c.Args().First()) 38 | user := app.User{token} 39 | app.CheckAndCreatePath() 40 | app.SaveUser(user) 41 | app.StarOnMe(user, StarGoUrl) 42 | } else if c.NArg() < 1 { 43 | fmt.Println("Please enter you Github token. ", "Try again...") 44 | } else { 45 | fmt.Println("Just need only one Github token") 46 | fmt.Println("Please try again...") 47 | } 48 | return nil 49 | }, 50 | },{ 51 | Name: "focus", 52 | Aliases: []string{"f"}, 53 | ArgsUsage: "...", 54 | Usage: "Save the repository which you are interested", 55 | Description: "The repository you want to focus on", 56 | Flags: []cli.Flag{ 57 | &cli.IntFlag{Name: "tab", Aliases: []string{"t"}, Value: 1, Usage: "which tab you want to save"}, 58 | }, 59 | Action: func(c *cli.Context) error { 60 | if c.NArg() > 0 { 61 | repos := make([]app.RepoConfig, 0) 62 | for _, value := range c.Args().Slice() { 63 | repo , err := app.ParseToRepo(value) 64 | if err == nil { 65 | repos = append(repos, repo) 66 | } 67 | } 68 | app.SaveRepos(repos, c.Int("tab")) 69 | 70 | } else { 71 | fmt.Println("Please try something like ''teyushen/star-go") 72 | } 73 | return nil 74 | }, 75 | },{ 76 | Name: "append", 77 | Aliases: []string{"a"}, 78 | ArgsUsage: "...", 79 | Usage: "Append the repository you are interested on already focus", 80 | Description: "The repository you want to focus on", 81 | Flags: []cli.Flag{ 82 | &cli.IntFlag{Name: "tab", Aliases: []string{"t"}, Value: 1, Usage: "which tab you want to save"}, 83 | }, 84 | Action: func(c *cli.Context) error { 85 | if c.NArg() > 0 { 86 | repos := make([]app.RepoConfig, 0) 87 | for _, value := range c.Args().Slice() { 88 | repo , err := app.ParseToRepo(value) 89 | if err == nil { 90 | repos = append(repos, repo) 91 | } 92 | } 93 | app.AppendRepos(c.Int("tab"), repos...) 94 | 95 | } else { 96 | fmt.Println("Please try something like ''teyushen/star-go") 97 | } 98 | return nil 99 | }, 100 | },{ 101 | Name: "compare", 102 | Aliases: []string{"c"}, 103 | Usage: "Use this to order the numbers of star", 104 | Description: "Compare all the repositories you are interested", 105 | Flags: []cli.Flag{ 106 | &cli.IntFlag{Name: "tab", Aliases: []string{"t"}, Value: 1, Usage: "which tab you want to save"}, 107 | }, 108 | Action: func(c *cli.Context) error { 109 | app.CompareStar(app.PrepareReposInfo(c.Int("tab"))) 110 | return nil 111 | }, 112 | },{ 113 | Name: "list", 114 | Aliases: []string{"ls"}, 115 | Usage: "Display all the focus repositories", 116 | Description: "List all the repo you are interested", 117 | Flags: []cli.Flag{ 118 | &cli.IntFlag{Name: "tab", Aliases: []string{"t"}, Value: 1, Usage: "which tab you want to save"}, 119 | }, 120 | Action: func(c *cli.Context) error { 121 | //cc := color.New(color.FgBlue) 122 | fmt.Printf("%10s %20s\n", "Owner", "Repositories") 123 | fmt.Println("-----------------------------------------------------------------------") 124 | for _, repo := range app.GetRepos(c.Int("tab")) { 125 | fmt.Printf("%10s %s\n", repo.Owner, repo.RepoNames) 126 | } 127 | return nil 128 | }, 129 | }, 130 | }, 131 | } 132 | app.Run(os.Args) 133 | } -------------------------------------------------------------------------------- /images/README.md: -------------------------------------------------------------------------------- 1 | # Generate New Token 2 | 3 | * step1 4 | 5 | ![step1](https://github.com/teyushen/star-go/blob/master/images/token/step1.png) 6 | 7 | * step2 8 | 9 | ![step2](https://github.com/teyushen/star-go/blob/master/images/token/step2.png) 10 | 11 | * step3 12 | 13 | ![step3](https://github.com/teyushen/star-go/blob/master/images/token/step3.png) 14 | 15 | * step4 16 | 17 | ![step4](https://github.com/teyushen/star-go/blob/master/images/token/step4.png) 18 | 19 | * step5 20 | 21 | ![step5](https://github.com/teyushen/star-go/blob/master/images/token/step5.png) 22 | 23 | * step6 24 | 25 | ![step6](https://github.com/teyushen/star-go/blob/master/images/token/step6.png) -------------------------------------------------------------------------------- /images/star-go-c.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/star-go-c.gif -------------------------------------------------------------------------------- /images/star-go-ls.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/star-go-ls.gif -------------------------------------------------------------------------------- /images/token/step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step1.png -------------------------------------------------------------------------------- /images/token/step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step2.png -------------------------------------------------------------------------------- /images/token/step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step3.png -------------------------------------------------------------------------------- /images/token/step4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step4.png -------------------------------------------------------------------------------- /images/token/step5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step5.png -------------------------------------------------------------------------------- /images/token/step6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/images/token/step6.png -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/teyushen/star-go/6129a53685be48de08b4e72fe3ba9c6818a36d32/logo.png -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "io/ioutil" 6 | "github.com/teyushen/star-go/cmd" 7 | ) 8 | 9 | func init() { 10 | log.SetFlags(log.LstdFlags | log.Lshortfile) 11 | log.SetOutput(ioutil.Discard) 12 | } 13 | 14 | 15 | func main() { 16 | cmd.Cli() 17 | 18 | } 19 | --------------------------------------------------------------------------------