-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy pathuserStatistics.go
140 lines (131 loc) · 3.85 KB
/
userStatistics.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// Copyright 2020 ratelimit Author(https://github.com/yudeguang/ratelimit). All Rights Reserved.
//
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file,
// You can obtain one at https://github.com/yudeguang/ratelimit.
package ratelimit
import (
"fmt"
"sort"
"strconv"
)
const (
Chinese = iota
English
)
/*
某用户剩余访问次数,只返回所有规则中时间范围跨度最大的一条规则的剩余访问次数。
例如,假如规定了每天能访问多少次,每小时能返回多少次,每分钟能返回多少次
那么此处只返回每天剩余访问次数。
例:
RemainingVisit("username")
*/
func (r *Rule) RemainingVisit(key interface{}) int {
return rightInt(r.RemainingVisits(key), 1)[0]
}
// 返回右往左最多n个元素
func rightInt(s []int, n int) []int {
if len(s) < n {
return s
}
if n <= 0 {
return nil
}
return s[len(s)-n:]
}
/*
某用户剩余访问次数,例:
RemainingVisits("username")
*/
func (r *Rule) RemainingVisits(key interface{}) []int {
arr := make([]int, 0, len(r.rules))
for i := range r.rules {
arr = append(arr, r.rules[i].remainingVisits(key))
}
return arr
}
/*
打印各细分规则下的剩余访问次数
*/
func (r *Rule) PrintRemainingVisits(key interface{}, language ...int) {
//先确定语言,默认为中文,目前只支持中文,英文两种语言
lan := 0
if len(language) == 1 && language[0] == 1 {
lan = 1
}
for i := range r.rules {
if lan == 0 {
fmt.Println(key, "在", r.rules[i].defaultExpiration, "内共允许访问", r.rules[i].numberOfAllowedAccesses, "次,剩余", r.rules[i].remainingVisits(key))
} else {
fmt.Println(key, "allowed", r.rules[i].numberOfAllowedAccesses, "visits within", r.rules[i].defaultExpiration, ",with", r.rules[i].remainingVisits(key), "remaining")
}
}
}
/*
以IP作为用户名,此用户剩余访问次数,例:
RemainingVisitsByIP4("127.0.0.1")
*/
func (r *Rule) RemainingVisitsByIP4(ip string) []int {
ipInt64 := ip4StringToInt64(ip)
if ipInt64 == 0 {
return []int{}
}
return r.RemainingVisits(ipInt64)
}
// 获得当前所有的在线用户,注意所有用int64存储的用户会被默认认为是IP地址,会被自动转换为IP的字符串形式输出以方便查看
// 如果不是本身就是以int64形式存储,而不是IP4,那么可以用ip4StringToInt64自己再转换回去
func (r *Rule) GetCurOnlineUsers() []string {
//向切片Sli中插入没出现过的元素V,如果切片中有V,则不插入
var insertIgnoreString = func(s []string, v string) []string {
for _, val := range s {
if val == v {
return s
}
}
s = append(s, v)
return s
}
var users []string
for i := range r.rules {
r.rules[i].usedVisitorRecordsIndex.Range(func(k, v interface{}) bool {
var user string
switch k.(type) {
case int64:
user = int64ToIp4String(k.(int64))
default:
user = fmt.Sprint(k)
}
users = insertIgnoreString(users, user)
return true
})
}
sort.Strings(users)
return users
}
// 返回所有用户的剩余返回次数详情,注意,为简单起见,返回值被转化为string类型 默认只返回1000
func (r *Rule) GetCurOnlineUsersVisitsDetail(num ...int) (CurOnlineUsersVisitsDetail [][]string) {
if len(num) > 0 && num[0] < 1 {
panic("num must be>0")
}
CurOnlineUsers := r.GetCurOnlineUsers()
sort.Strings(CurOnlineUsers)
for _, user := range CurOnlineUsers {
visits := r.RemainingVisits(user)
var visitsString []string
visitsString = append(visitsString, user)
for i := range visits {
visitsString = append(visitsString, strconv.Itoa(visits[i]))
}
if len(num) == 0 {
if len(CurOnlineUsersVisitsDetail) >= 1000 {
break
}
} else {
if len(CurOnlineUsersVisitsDetail) >= num[0] {
break
}
}
CurOnlineUsersVisitsDetail = append(CurOnlineUsersVisitsDetail, visitsString)
}
return
}