• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ezeoleaf / larry / 5412090884

29 Jun 2023 12:18PM UTC coverage: 90.424% (-0.4%) from 90.834%
5412090884

Pull #136

github

web-flow
Upgrade: bump github.com/alicebob/miniredis/v2 from 2.30.2 to 2.30.4

Bumps [github.com/alicebob/miniredis/v2](https://github.com/alicebob/miniredis) from 2.30.2 to 2.30.4.
- [Release notes](https://github.com/alicebob/miniredis/releases)
- [Changelog](https://github.com/alicebob/miniredis/blob/master/CHANGELOG.md)
- [Commits](https://github.com/alicebob/miniredis/compare/v2.30.2...v2.30.4)

---
updated-dependencies:
- dependency-name: github.com/alicebob/miniredis/v2
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Pull Request #136: Upgrade: bump github.com/alicebob/miniredis/v2 from 2.30.2 to 2.30.4

661 of 731 relevant lines covered (90.42%)

4.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.66
/provider/github/provider.go
1
package github
2

3
import (
4
        "context"
5
        "fmt"
6
        "log"
7
        "math/rand"
8
        "strconv"
9
        "time"
10

11
        "github.com/ezeoleaf/larry/cache"
12
        "github.com/ezeoleaf/larry/config"
13
        "github.com/ezeoleaf/larry/domain"
14
        "github.com/go-redis/redis/v8"
15
        "github.com/google/go-github/v39/github"
16
        "golang.org/x/oauth2"
17
)
18

19
type searchClient interface {
20
        Repositories(ctx context.Context, query string, opt *github.SearchOptions) (*github.RepositoriesSearchResult, *github.Response, error)
21
}
22
type userClient interface {
23
        Get(ctx context.Context, user string) (*github.User, *github.Response, error)
24
}
25

26
// Provider represents the provider client
27
type Provider struct {
28
        GithubSearchClient searchClient
29
        GithubUserClient   userClient
30
        CacheClient        cache.Client
31
        Config             config.Config
32
}
33

34
const emptyChar = " "
35

36
// NewProvider returns a new provider client
37
func NewProvider(apiKey string, cfg config.Config, cacheClient cache.Client) Provider {
1✔
38
        log.Print("New Github Provider")
1✔
39
        p := Provider{Config: cfg, CacheClient: cacheClient}
1✔
40

1✔
41
        ts := oauth2.StaticTokenSource(
1✔
42
                &oauth2.Token{AccessToken: apiKey},
1✔
43
        )
1✔
44
        tc := oauth2.NewClient(context.Background(), ts)
1✔
45

1✔
46
        p.GithubSearchClient = github.NewClient(tc).Search
1✔
47
        p.GithubUserClient = github.NewClient(tc).Users
1✔
48

1✔
49
        return p
1✔
50
}
1✔
51

52
// GetContentToPublish returns a string with the content to publish to be used by the publishers
53
func (p Provider) GetContentToPublish() (*domain.Content, error) {
×
54
        r, err := p.getRepo()
×
55
        if err != nil {
×
56
                return nil, err
×
57
        }
×
58
        return p.getContent(r), nil
×
59
}
60

61
func (p Provider) getRepositories(randomChar string) ([]*github.Repository, int, error) {
3✔
62
        so := github.SearchOptions{ListOptions: github.ListOptions{PerPage: 1}, TextMatch: true}
3✔
63

3✔
64
        _, t, e := p.GithubSearchClient.Repositories(context.Background(), p.getQueryString(randomChar), &so)
3✔
65

3✔
66
        if e != nil {
4✔
67
                return nil, -1, e
1✔
68
        }
1✔
69

70
        return nil, t.LastPage, nil
2✔
71
}
72

73
func (p Provider) getRandomChar() string {
3✔
74
        if rand.Intn(11) > 2 {
6✔
75
                return emptyChar
3✔
76
        }
3✔
77

78
        var letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
×
79

×
80
        return string(letters[rand.Intn(len(letters))])
×
81
}
82

83
func (p Provider) getRepo() (*github.Repository, error) {
3✔
84
        rand.Seed(time.Now().UTC().UnixNano())
3✔
85
        rc := p.getRandomChar()
3✔
86

3✔
87
        _, total, err := p.getRepositories(rc)
3✔
88
        if err != nil {
4✔
89
                return nil, err
1✔
90
        }
1✔
91

92
        if total < 1 {
3✔
93
                log.Printf("char %s returned 0 repositories\n", rc)
1✔
94
                return nil, fmt.Errorf("char %s returned 0 repositories", rc)
1✔
95
        }
1✔
96

97
        var repo *github.Repository
1✔
98

1✔
99
        var found bool
1✔
100

1✔
101
        for !found {
2✔
102
                randPos := rand.Intn(total)
1✔
103

1✔
104
                repo = p.getSpecificRepo(rc, randPos)
1✔
105

1✔
106
                found = repo != nil && p.isRepoNotInCache(*repo.ID)
1✔
107

1✔
108
                if found {
2✔
109
                        if *repo.Archived {
1✔
110
                                found = false
×
111
                                log.Printf("repository archived: %d\n", *repo.ID)
×
112
                        } else if p.isBlacklisted(*repo.ID) {
1✔
113
                                found = false
×
114
                                log.Printf("repository blacklisted: %d\n", *repo.ID)
×
115
                        }
×
116
                }
117
        }
118

119
        return repo, nil
1✔
120
}
121

122
func (p Provider) getQueryString(randomChar string) string {
11✔
123
        var qs string
11✔
124

11✔
125
        if p.Config.Topic != "" && p.Config.Language != "" {
12✔
126
                qs = fmt.Sprintf("topic:%s+language:%s", p.Config.Topic, p.Config.Language)
1✔
127
        } else if p.Config.Topic != "" {
12✔
128
                qs = fmt.Sprintf("topic:%s", p.Config.Topic)
1✔
129
        } else {
10✔
130
                qs = fmt.Sprintf("language:%s", p.Config.Language)
9✔
131
        }
9✔
132

133
        if randomChar != emptyChar {
18✔
134
                qs = fmt.Sprintf("%s+%s", randomChar, qs)
7✔
135
        }
7✔
136

137
        return qs
11✔
138
}
139

140
func (p Provider) getSpecificRepo(randomChar string, pos int) *github.Repository {
4✔
141
        so := github.SearchOptions{ListOptions: github.ListOptions{PerPage: 1, Page: pos}, TextMatch: true}
4✔
142

4✔
143
        repositories, _, e := p.GithubSearchClient.Repositories(context.Background(), p.getQueryString(randomChar), &so)
4✔
144

4✔
145
        if e != nil {
5✔
146
                return nil
1✔
147
        }
1✔
148

149
        return repositories.Repositories[0]
3✔
150
}
151

152
func cacheKey(cacheKeyPrefix string, repoID int64) string {
6✔
153
        return cacheKeyPrefix + strconv.FormatInt(repoID, 10)
6✔
154
}
6✔
155

156
func cacheKeyBlacklist(cfg config.Config, repoID int64) string {
1✔
157
        return "blacklist-" + cacheKey(cfg.GetCacheKeyPrefix(), repoID)
1✔
158
}
1✔
159

160
func (p Provider) isRepoNotInCache(repoID int64) bool {
5✔
161
        k := cacheKey(p.Config.GetCacheKeyPrefix(), repoID)
5✔
162
        _, err := p.CacheClient.Get(k)
5✔
163

5✔
164
        switch {
5✔
165
        case err == redis.Nil:
2✔
166
                err := p.CacheClient.Set(k, true, p.cacheExpirationMinutes())
2✔
167
                if err != nil {
2✔
168
                        return false
×
169
                }
×
170

171
                return true
2✔
172
        case err != nil:
2✔
173
                log.Println("Get failed", err)
2✔
174
                return false
2✔
175
        }
176

177
        return false
1✔
178
}
179

180
func (p Provider) isBlacklisted(repoID int64) bool {
1✔
181
        k := cacheKeyBlacklist(p.Config, repoID)
1✔
182
        if _, err := p.CacheClient.Get(k); err != redis.Nil {
1✔
183
                return true
×
184
        }
×
185
        return false
1✔
186
}
187

188
func (p Provider) cacheExpirationMinutes() time.Duration {
5✔
189
        expirationMinutes := p.Config.CacheSize * p.Config.Periodicity
5✔
190
        if expirationMinutes < 0 {
7✔
191
                expirationMinutes = 0
2✔
192
        }
2✔
193
        return time.Duration(expirationMinutes) * time.Minute
5✔
194
}
195

196
func (p Provider) getContent(repo *github.Repository) *domain.Content {
7✔
197
        c := domain.Content{Title: repo.Name, Subtitle: repo.Description, URL: repo.HTMLURL, ExtraData: []string{}}
7✔
198

7✔
199
        if p.Config.TweetLanguage && repo.Language != nil {
9✔
200
                l := "Lang: " + *repo.Language
2✔
201
                c.ExtraData = append(c.ExtraData, l)
2✔
202
        }
2✔
203

204
        if repo.StargazersCount != nil {
8✔
205
                stargazers := "⭐️ " + strconv.Itoa(*repo.StargazersCount)
1✔
206
                c.ExtraData = append(c.ExtraData, stargazers)
1✔
207
        }
1✔
208

209
        owner := p.getRepoUser(repo.Owner)
7✔
210
        if owner != "" {
8✔
211
                author := "Author: @" + owner
1✔
212
                c.ExtraData = append(c.ExtraData, author)
1✔
213
        }
1✔
214

215
        if repo.UpdatedAt != nil {
9✔
216
                lastUpdatedAt := fmt.Sprintf("Updated on: %s", repo.GetUpdatedAt().Format("2006-01-02"))
2✔
217
                c.ExtraData = append(c.ExtraData, lastUpdatedAt)
2✔
218
        }
2✔
219

220
        hs := p.Config.GetHashtags()
7✔
221
        hashtags := ""
7✔
222

7✔
223
        if len(hs) == 0 {
13✔
224
                if p.Config.Topic != "" {
7✔
225
                        hashtags += "#" + p.Config.Topic + " "
1✔
226
                } else if p.Config.Language != "" {
7✔
227
                        hashtags += "#" + p.Config.Language + " "
1✔
228
                } else if repo.Language != nil {
9✔
229
                        hashtags += "#" + *repo.Language + " "
4✔
230
                }
4✔
231
        } else {
1✔
232
                for _, h := range hs {
4✔
233
                        if hashtags != "" {
5✔
234
                                hashtags += " "
2✔
235
                        }
2✔
236
                        hashtags += h
3✔
237
                }
238
        }
239

240
        c.ExtraData = append(c.ExtraData, hashtags)
7✔
241

7✔
242
        return &c
7✔
243
}
244

245
func (p Provider) getRepoUser(owner *github.User) string {
12✔
246
        if owner == nil || owner.Login == nil {
20✔
247
                return ""
8✔
248
        }
8✔
249

250
        gUser, _, err := p.GithubUserClient.Get(context.Background(), *owner.Login)
4✔
251

4✔
252
        if err != nil {
5✔
253
                return ""
1✔
254
        }
1✔
255

256
        return gUser.GetTwitterUsername()
3✔
257
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc