-
Notifications
You must be signed in to change notification settings - Fork 3
/
limiter.go
90 lines (75 loc) · 1.67 KB
/
limiter.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package wbot
import (
"strconv"
"strings"
"time"
"github.com/twiny/ratelimit"
"github.com/twiny/wbot/pkg/api"
)
var (
defaultRateLimit = "10/1s"
)
type (
rateLimiter struct {
table map[string]*ratelimit.Limiter
}
)
func newRateLimiter(limits ...*api.RateLimit) *rateLimiter {
rl := &rateLimiter{
table: make(map[string]*ratelimit.Limiter),
}
// Handle the default wildcard limit.
hasWildcard := false
if len(limits) > 0 {
for _, limit := range limits {
if limit.Hostname == "*" {
hasWildcard = true
break
}
}
}
if !hasWildcard {
limits = append(limits, &api.RateLimit{
Hostname: "*",
Rate: defaultRateLimit,
})
}
for _, rate := range limits {
r, l := parseRateLimit(rate.Rate)
rl.table[rate.Hostname] = ratelimit.NewLimiter(r, l)
}
return rl
}
func (l *rateLimiter) wait(u *api.ParsedURL) {
limit, found := l.table[u.Root]
if !found {
limit = l.table["*"]
}
limit.Take()
}
func parseRateLimit(s string) (rate int, interval time.Duration) {
parts := strings.Split(s, "/")
if len(parts) != 2 {
return parseRateLimit(defaultRateLimit)
}
rate, err := strconv.Atoi(parts[0])
if err != nil {
return parseRateLimit(defaultRateLimit)
}
intervalValueStr := parts[1][:len(parts[1])-1]
intervalValue, err := strconv.Atoi(intervalValueStr)
if err != nil {
return parseRateLimit(defaultRateLimit)
}
switch parts[1][len(parts[1])-1] {
case 's', 'S':
interval = time.Duration(intervalValue) * time.Second
case 'm', 'M':
interval = time.Duration(intervalValue) * time.Minute
case 'h', 'H':
interval = time.Duration(intervalValue) * time.Hour
default:
return parseRateLimit(defaultRateLimit)
}
return rate, interval
}