gosora/common/ip_search.go

85 lines
2.1 KiB
Go

package common
import (
"database/sql"
qgen "git.tuxpa.in/a/gosora/query_gen"
)
var IPSearch IPSearcher
type IPSearcher interface {
Lookup(ip string) (uids []int, e error)
}
type DefaultIPSearcher struct {
searchUsers *sql.Stmt
searchTopics *sql.Stmt
searchReplies *sql.Stmt
searchUsersReplies *sql.Stmt
}
// NewDefaultIPSearcher gives you a new instance of DefaultIPSearcher
func NewDefaultIPSearcher() (*DefaultIPSearcher, error) {
acc := qgen.NewAcc()
uu := "users"
q := func(tbl string) *sql.Stmt {
return acc.Select(uu).Columns("uid").InQ("uid", acc.Select(tbl).Columns("createdBy").Where("ip=?")).Prepare()
}
return &DefaultIPSearcher{
searchUsers: acc.Select(uu).Columns("uid").Where("last_ip=? OR last_ip LIKE CONCAT('%-',?)").Prepare(),
searchTopics: q("topics"),
searchReplies: q("replies"),
searchUsersReplies: q("users_replies"),
}, acc.FirstError()
}
func (s *DefaultIPSearcher) Lookup(ip string) (uids []int, e error) {
var uid int
reqUserList := make(map[int]bool)
runQuery2 := func(rows *sql.Rows, e error) error {
if e != nil {
return e
}
defer rows.Close()
for rows.Next() {
if e := rows.Scan(&uid); e != nil {
return e
}
reqUserList[uid] = true
}
return rows.Err()
}
runQuery := func(stmt *sql.Stmt) error {
return runQuery2(stmt.Query(ip))
}
e = runQuery2(s.searchUsers.Query(ip, ip))
if e != nil {
return uids, e
}
e = runQuery(s.searchTopics)
if e != nil {
return uids, e
}
e = runQuery(s.searchReplies)
if e != nil {
return uids, e
}
e = runQuery(s.searchUsersReplies)
if e != nil {
return uids, e
}
// Convert the user ID map to a slice, then bulk load the users
uids = make([]int, len(reqUserList))
var i int
for userID := range reqUserList {
uids[i] = userID
i++
}
return uids, nil
}