-
Notifications
You must be signed in to change notification settings - Fork 1
/
friendlink.go
184 lines (167 loc) · 4.86 KB
/
friendlink.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
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package official
import (
"net/url"
"time"
"github.com/webx-top/com"
"github.com/webx-top/db"
"github.com/webx-top/echo"
"github.com/webx-top/echo/code"
"github.com/admpub/nging/v5/application/library/common"
"github.com/admpub/webx/application/dbschema"
)
var (
FriendlinkMaxUnsuccessfuls int64 = 5 // 每个用户提交友情链接的最大数量(不包含已经通过的)
)
func NewFriendlink(ctx echo.Context) *Friendlink {
m := &Friendlink{
OfficialCommonFriendlink: dbschema.NewOfficialCommonFriendlink(ctx),
}
return m
}
type Friendlink struct {
*dbschema.OfficialCommonFriendlink
}
func (f *Friendlink) Exists(customerID uint64, url string, host string) (bool, error) {
cond := db.NewCompounds()
if customerID > 0 {
cond.Add(db.Cond{`customer_id`: customerID})
}
cond.Add(db.Or(
db.Cond{`url`: url},
db.Cond{`host`: host},
))
return f.OfficialCommonFriendlink.Exists(nil, cond.And())
}
func (f *Friendlink) ListPage(cond *db.Compounds, orderby ...interface{}) ([]*FriendlinkExt, error) {
list := []*FriendlinkExt{}
_, err := common.NewLister(f, &list, func(r db.Result) db.Result {
return r.OrderBy(orderby...)
}, cond.And()).Paging(f.Context())
return list, err
}
// ListShowAndRecord 前台列表显示,并记录回调
func (f *Friendlink) ListShowAndRecord(limit int, categoryIds ...uint) ([]*dbschema.OfficialCommonFriendlink, error) {
if !f.Context().Internal().Bool(`FriendlinkReturnRecorded`) {
f.RecordReturn()
f.Context().Internal().Set(`FriendlinkReturnRecord`, true)
}
if limit == 0 {
return nil, nil
}
list := []*dbschema.OfficialCommonFriendlink{}
cond := db.NewCompounds()
cond.AddKV(`process`, `success`)
var sorts []interface{}
if len(categoryIds) > 0 && categoryIds[0] > 0 {
cond.AddKV(`category_id`, categoryIds[0])
} else {
sorts = append(sorts, `category_id`)
}
sorts = append(sorts, `-return_count`)
sorts = append(sorts, `-id`)
_, err := f.ListByOffset(&list, func(r db.Result) db.Result {
return r.OrderBy(sorts...)
}, 0, limit, cond.And())
return list, err
}
func (f *Friendlink) ExistsOther(customerID uint64, url string, host string, id uint) (bool, error) {
cond := db.NewCompounds()
if customerID > 0 {
cond.Add(db.Cond{`customer_id`: customerID})
}
cond.Add(db.Or(
db.Cond{`url`: url},
db.Cond{`host`: host},
))
cond.Add(db.Cond{`id`: db.NotEq(id)})
return f.OfficialCommonFriendlink.Exists(nil, cond.And())
}
func (f *Friendlink) check() error {
var exists bool
if len(f.Url) == 0 {
return f.Context().NewError(code.InvalidParameter, `请输入网址`)
}
if !com.IsURL(f.Url) {
return f.Context().NewError(code.InvalidParameter, `请输入正确的网址`)
}
urlInfo, err := url.Parse(f.Url)
if err != nil {
return f.Context().NewError(code.InvalidParameter, `网址格式错误: %v`, err.Error())
}
if len(urlInfo.Host) == 0 {
return f.Context().NewError(code.InvalidParameter, `网址格式错误: 域名解析失败`)
}
f.Host = urlInfo.Host
if f.Id > 0 {
exists, err = f.ExistsOther(f.CustomerId, f.Url, f.Host, f.Id)
} else {
if f.CustomerId > 0 {
count, err := f.Count(nil, db.And(
db.Cond{`customer_id`: f.CustomerId},
db.Cond{`process`: db.NotEq(`success`)},
))
if err != nil {
return err
}
if count >= FriendlinkMaxUnsuccessfuls {
return f.Context().NewError(code.DataProcessing, `您已经有“%v”个链接正在处理中,请等待处理通过后再添加新链接`, count)
}
}
exists, err = f.Exists(f.CustomerId, f.Url, f.Host)
}
if err != nil {
return err
}
if exists {
return f.Context().NewError(code.DataAlreadyExists, `网址或域名已经存在`)
}
return nil
}
func (f *Friendlink) Add() (pk interface{}, err error) {
if err := f.check(); err != nil {
return nil, err
}
return f.OfficialCommonFriendlink.Insert()
}
func (f *Friendlink) Edit(mw func(db.Result) db.Result, args ...interface{}) error {
return f.OfficialCommonFriendlink.Update(mw, args...)
}
func (f *Friendlink) IncrReturnCount(id uint) error {
return f.UpdateFields(nil, echo.H{
"return_count": db.Raw(`return_count+1`),
"return_time": uint(time.Now().Unix()),
}, `id`, id)
}
func (f *Friendlink) VerifyFail(id uint) error {
return f.UpdateFields(nil, echo.H{
"verify_fail_count": db.Raw(`verify_fail_count+1`),
"verify_time": uint(time.Now().Unix()),
"verify_result": `invalid`,
}, `id`, id)
}
func (f *Friendlink) RecordReturn() error {
referer := f.Context().Referer()
if len(referer) == 0 {
return nil
}
info, err := url.Parse(referer)
if err != nil {
return err
}
if len(info.Host) == 0 {
return nil
}
if info.Host == f.Context().Host() {
return nil
}
err = f.Get(func(r db.Result) db.Result {
return r.Select(`host`, `return_time`)
}, `host`, info.Host)
if err != nil {
return err
}
if (time.Now().Unix() - 3600) <= int64(f.ReturnTime) { // 每小时只统计一次
return nil
}
return f.IncrReturnCount(f.Id)
}