b6931fe16a
Run group promotions on group change. Run group promotions on registration. Load the CreatedAt field when users are loaded. Set the default for last_ip properly. Fix the default values in the group promotion form. Add initial group promotion tests. Add panel_group_promotion_registered_for phrase. Add the registeredFor column to the users_groups_promotions table. You will need to run the updater / patcher for this commit.
135 lines
4.5 KiB
Go
135 lines
4.5 KiB
Go
package common
|
|
|
|
import (
|
|
"database/sql"
|
|
//"log"
|
|
"time"
|
|
|
|
qgen "github.com/Azareal/Gosora/query_gen"
|
|
)
|
|
|
|
var GroupPromotions GroupPromotionStore
|
|
|
|
type GroupPromotion struct {
|
|
ID int
|
|
From int
|
|
To int
|
|
TwoWay bool
|
|
|
|
Level int
|
|
Posts int
|
|
MinTime int
|
|
RegisteredFor int
|
|
}
|
|
|
|
type GroupPromotionStore interface {
|
|
GetByGroup(gid int) (gps []*GroupPromotion, err error)
|
|
Get(id int) (*GroupPromotion, error)
|
|
PromoteIfEligible(u *User, level, posts int, registeredAt time.Time) error
|
|
Delete(id int) error
|
|
Create(from, to int, twoWay bool, level, posts, registeredFor int) (int, error)
|
|
}
|
|
|
|
type DefaultGroupPromotionStore struct {
|
|
getByGroup *sql.Stmt
|
|
get *sql.Stmt
|
|
delete *sql.Stmt
|
|
create *sql.Stmt
|
|
|
|
getByUser *sql.Stmt
|
|
getByUserMins *sql.Stmt
|
|
updateUser *sql.Stmt
|
|
updateGeneric *sql.Stmt
|
|
}
|
|
|
|
func NewDefaultGroupPromotionStore(acc *qgen.Accumulator) (*DefaultGroupPromotionStore, error) {
|
|
ugp := "users_groups_promotions"
|
|
prs := &DefaultGroupPromotionStore{
|
|
getByGroup: acc.Select(ugp).Columns("pid, from_gid, to_gid, two_way, level, posts, minTime, registeredFor").Where("from_gid=? OR to_gid=?").Prepare(),
|
|
get: acc.Select(ugp).Columns("from_gid, to_gid, two_way, level, posts, minTime, registeredFor").Where("pid=?").Prepare(),
|
|
delete: acc.Delete(ugp).Where("pid=?").Prepare(),
|
|
create: acc.Insert(ugp).Columns("from_gid, to_gid, two_way, level, posts, minTime, registeredFor").Fields("?,?,?,?,?,?,?").Prepare(),
|
|
|
|
//err := s.getByUser.QueryRow(u.Group, level, posts, mins).Scan(&g.ID, &g.To, &g.TwoWay, &g.Level, &g.Posts, &g.MinTime, &g.RegisteredFor)
|
|
//getByUserMins: acc.Select(ugp).Columns("pid, to_gid, two_way, level, posts, minTime, registeredFor").Where("from_gid=? AND level<=? AND posts<=?").DateOlderThanQ("registeredFor", "minute").Orderby("level DESC").Limit("1").Prepare(),
|
|
getByUserMins: acc.Select(ugp).Columns("pid, to_gid, two_way, level, posts, minTime, registeredFor").Where("from_gid=? AND level<=? AND posts<=? AND registeredFor<=?").Orderby("level DESC").Limit("1").Prepare(),
|
|
getByUser: acc.Select(ugp).Columns("pid, to_gid, two_way, level, posts, minTime, registeredFor").Where("from_gid=? AND level<=? AND posts<=?").Orderby("level DESC").Limit("1").Prepare(),
|
|
updateUser: acc.Update("users").Set("group=?").Where("group=? AND uid=?").Prepare(),
|
|
updateGeneric: acc.Update("users").Set("group=?").Where("group=? AND level>=? AND posts>=?").Prepare(),
|
|
}
|
|
AddScheduledFifteenMinuteTask(prs.Tick)
|
|
return prs, acc.FirstError()
|
|
}
|
|
|
|
func (s *DefaultGroupPromotionStore) Tick() error {
|
|
return nil
|
|
}
|
|
|
|
func (s *DefaultGroupPromotionStore) GetByGroup(gid int) (gps []*GroupPromotion, err error) {
|
|
rows, err := s.getByGroup.Query(gid, gid)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
for rows.Next() {
|
|
g := &GroupPromotion{}
|
|
err := rows.Scan(&g.ID, &g.From, &g.To, &g.TwoWay, &g.Level, &g.Posts, &g.MinTime, &g.RegisteredFor)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
gps = append(gps, g)
|
|
}
|
|
return gps, rows.Err()
|
|
}
|
|
|
|
// TODO: Cache the group promotions to avoid hitting the database as much
|
|
func (s *DefaultGroupPromotionStore) Get(id int) (*GroupPromotion, error) {
|
|
/*g, err := s.cache.Get(id)
|
|
if err == nil {
|
|
return u, nil
|
|
}*/
|
|
|
|
g := &GroupPromotion{ID: id}
|
|
err := s.get.QueryRow(id).Scan(&g.From, &g.To, &g.TwoWay, &g.Level, &g.Posts, &g.MinTime, &g.RegisteredFor)
|
|
if err == nil {
|
|
//s.cache.Set(u)
|
|
}
|
|
return g, err
|
|
}
|
|
|
|
// TODO: Optimise this to avoid the query
|
|
func (s *DefaultGroupPromotionStore) PromoteIfEligible(u *User, level, posts int, registeredAt time.Time) error {
|
|
mins := time.Since(registeredAt).Minutes()
|
|
g := &GroupPromotion{From: u.Group}
|
|
//log.Printf("pre getByUserMins: %+v\n", u)
|
|
err := s.getByUserMins.QueryRow(u.Group, level, posts, mins).Scan(&g.ID, &g.To, &g.TwoWay, &g.Level, &g.Posts, &g.MinTime, &g.RegisteredFor)
|
|
if err == sql.ErrNoRows {
|
|
//log.Print("no matches found")
|
|
return nil
|
|
} else if err != nil {
|
|
return err
|
|
}
|
|
//log.Printf("g: %+v\n", g)
|
|
if g.RegisteredFor == 0 {
|
|
_, err = s.updateGeneric.Exec(g.To, g.From, g.Level, g.Posts)
|
|
} else {
|
|
_, err = s.updateUser.Exec(g.To, g.From, u.ID)
|
|
}
|
|
return err
|
|
}
|
|
|
|
func (s *DefaultGroupPromotionStore) Delete(id int) error {
|
|
_, err := s.delete.Exec(id)
|
|
return err
|
|
}
|
|
|
|
func (s *DefaultGroupPromotionStore) Create(from, to int, twoWay bool, level, posts, registeredFor int) (int, error) {
|
|
res, err := s.create.Exec(from, to, twoWay, level, posts, 0, registeredFor)
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
lastID, err := res.LastInsertId()
|
|
return int(lastID), err
|
|
}
|