github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/forum_actions.go (about)

     1  package common
     2  
     3  import (
     4  	"database/sql"
     5  	"fmt"
     6  	"strconv"
     7  
     8  	qgen "github.com/Azareal/Gosora/query_gen"
     9  )
    10  
    11  var ForumActionStore ForumActionStoreInt
    12  
    13  //var ForumActionRunnableStore ForumActionRunnableStoreInt
    14  
    15  const (
    16  	ForumActionDelete = iota
    17  	ForumActionLock
    18  	ForumActionUnlock
    19  	ForumActionMove
    20  )
    21  
    22  func ConvStringToAct(s string) int {
    23  	switch s {
    24  	case "delete":
    25  		return ForumActionDelete
    26  	case "lock":
    27  		return ForumActionLock
    28  	case "unlock":
    29  		return ForumActionUnlock
    30  	case "move":
    31  		return ForumActionMove
    32  	}
    33  	return -1
    34  }
    35  func ConvActToString(a int) string {
    36  	switch a {
    37  	case ForumActionDelete:
    38  		return "delete"
    39  	case ForumActionLock:
    40  		return "lock"
    41  	case ForumActionUnlock:
    42  		return "unlock"
    43  	case ForumActionMove:
    44  		return "move"
    45  	}
    46  	return ""
    47  }
    48  
    49  var forumActionStmts ForumActionStmts
    50  
    51  type ForumActionStmts struct {
    52  	get1    *sql.Stmt
    53  	get2    *sql.Stmt
    54  	lock1   *sql.Stmt
    55  	lock2   *sql.Stmt
    56  	unlock1 *sql.Stmt
    57  	unlock2 *sql.Stmt
    58  }
    59  
    60  type ForumAction struct {
    61  	ID                         int
    62  	Forum                      int
    63  	RunOnTopicCreation         bool
    64  	RunDaysAfterTopicCreation  int
    65  	RunDaysAfterTopicLastReply int
    66  	Action                     int
    67  	Extra                      string
    68  }
    69  
    70  func init() {
    71  	DbInits.Add(func(acc *qgen.Accumulator) error {
    72  		t := "topics"
    73  		forumActionStmts = ForumActionStmts{
    74  			get1: acc.Select(t).Cols("tid,createdBy,poll").Where("parentID=?").DateOlderThanQ("createdAt", "day").Stmt(),
    75  			get2: acc.Select(t).Cols("tid,createdBy,poll").Where("parentID=?").DateOlderThanQ("lastReplyAt", "day").Stmt(),
    76  
    77  			/*lock1:   acc.Update(t).Set("is_closed=1").Where("parentID=?").DateOlderThanQ("createdAt", "day").Stmt(),
    78  			lock2:   acc.Update(t).Set("is_closed=1").Where("parentID=?").DateOlderThanQ("lastReplyAt", "day").Stmt(),
    79  			unlock1: acc.Update(t).Set("is_closed=0").Where("parentID=?").DateOlderThanQ("createdAt", "day").Stmt(),
    80  			unlock2: acc.Update(t).Set("is_closed=0").Where("parentID=?").DateOlderThanQ("lastReplyAt", "day").Stmt(),*/
    81  		}
    82  		return acc.FirstError()
    83  	})
    84  }
    85  
    86  func (a *ForumAction) Run() error {
    87  	if a.RunDaysAfterTopicCreation > 0 {
    88  		if e := a.runDaysAfterTopicCreation(); e != nil {
    89  			return e
    90  		}
    91  	}
    92  	if a.RunDaysAfterTopicLastReply > 0 {
    93  		if e := a.runDaysAfterTopicLastReply(); e != nil {
    94  			return e
    95  		}
    96  	}
    97  	return nil
    98  }
    99  
   100  func (a *ForumAction) runQ(stmt *sql.Stmt, days int, f func(t *Topic) error) error {
   101  	rows, e := stmt.Query(days, a.Forum)
   102  	if e != nil {
   103  		return e
   104  	}
   105  	defer rows.Close()
   106  	for rows.Next() {
   107  		// TODO: Decouple this
   108  		t := &Topic{ParentID: a.Forum}
   109  		if e := rows.Scan(&t.ID, &t.CreatedBy, &t.Poll); e != nil {
   110  			return e
   111  		}
   112  		if e = f(t); e != nil {
   113  			return e
   114  		}
   115  	}
   116  	return rows.Err()
   117  }
   118  
   119  func (a *ForumAction) runDaysAfterTopicCreation() (e error) {
   120  	switch a.Action {
   121  	case ForumActionDelete:
   122  		// TODO: Bulk delete?
   123  		e = a.runQ(forumActionStmts.get1, a.RunDaysAfterTopicCreation, func(t *Topic) error {
   124  			return t.Delete()
   125  		})
   126  	case ForumActionLock:
   127  		/*_, e := forumActionStmts.lock1.Exec(a.Forum)
   128  		if e != nil {
   129  			return e
   130  		}*/
   131  		// TODO: Bulk lock? Lock and get resultset of changed topics somehow?
   132  		fmt.Println("ForumActionLock")
   133  		e = a.runQ(forumActionStmts.get1, a.RunDaysAfterTopicCreation, func(t *Topic) error {
   134  			fmt.Printf("t: %+v\n", t)
   135  			return t.Lock()
   136  		})
   137  	case ForumActionUnlock:
   138  		// TODO: Bulk unlock? Unlock and get resultset of changed topics somehow?
   139  		e = a.runQ(forumActionStmts.get1, a.RunDaysAfterTopicCreation, func(t *Topic) error {
   140  			return t.Unlock()
   141  		})
   142  	case ForumActionMove:
   143  		destForum, e := strconv.Atoi(a.Extra)
   144  		if e != nil {
   145  			return e
   146  		}
   147  		e = a.runQ(forumActionStmts.get1, a.RunDaysAfterTopicCreation, func(t *Topic) error {
   148  			return t.MoveTo(destForum)
   149  		})
   150  	}
   151  	return e
   152  }
   153  
   154  func (a *ForumAction) runDaysAfterTopicLastReply() (e error) {
   155  	switch a.Action {
   156  	case ForumActionDelete:
   157  		e = a.runQ(forumActionStmts.get2, a.RunDaysAfterTopicLastReply, func(t *Topic) error {
   158  			return t.Delete()
   159  		})
   160  	case ForumActionLock:
   161  		// TODO: Bulk lock? Lock and get resultset of changed topics somehow?
   162  		e = a.runQ(forumActionStmts.get2, a.RunDaysAfterTopicLastReply, func(t *Topic) error {
   163  			return t.Lock()
   164  		})
   165  	case ForumActionUnlock:
   166  		// TODO: Bulk unlock? Unlock and get resultset of changed topics somehow?
   167  		e = a.runQ(forumActionStmts.get2, a.RunDaysAfterTopicLastReply, func(t *Topic) error {
   168  			return t.Unlock()
   169  		})
   170  	case ForumActionMove:
   171  		destForum, e := strconv.Atoi(a.Extra)
   172  		if e != nil {
   173  			return e
   174  		}
   175  		e = a.runQ(forumActionStmts.get2, a.RunDaysAfterTopicLastReply, func(t *Topic) error {
   176  			return t.MoveTo(destForum)
   177  		})
   178  	}
   179  	return nil
   180  }
   181  
   182  func (a *ForumAction) TopicCreation(tid int) error {
   183  	if !a.RunOnTopicCreation {
   184  		return nil
   185  	}
   186  	return nil
   187  }
   188  
   189  type ForumActionStoreInt interface {
   190  	Get(faid int) (*ForumAction, error)
   191  	GetInForum(fid int) ([]*ForumAction, error)
   192  	GetAll() ([]*ForumAction, error)
   193  	GetNewTopicActions(fid int) ([]*ForumAction, error)
   194  
   195  	Add(fa *ForumAction) (int, error)
   196  	Delete(faid int) error
   197  	Exists(faid int) bool
   198  	Count() int
   199  	CountInForum(fid int) int
   200  
   201  	DailyTick() error
   202  }
   203  
   204  type DefaultForumActionStore struct {
   205  	get                *sql.Stmt
   206  	getInForum         *sql.Stmt
   207  	getAll             *sql.Stmt
   208  	getNewTopicActions *sql.Stmt
   209  
   210  	add          *sql.Stmt
   211  	delete       *sql.Stmt
   212  	exists       *sql.Stmt
   213  	count        *sql.Stmt
   214  	countInForum *sql.Stmt
   215  }
   216  
   217  func NewDefaultForumActionStore(acc *qgen.Accumulator) (*DefaultForumActionStore, error) {
   218  	fa := "forums_actions"
   219  	allCols := "faid,fid,runOnTopicCreation,runDaysAfterTopicCreation,runDaysAfterTopicLastReply,action,extra"
   220  	return &DefaultForumActionStore{
   221  		get:                acc.Select(fa).Columns("fid,runOnTopicCreation,runDaysAfterTopicCreation,runDaysAfterTopicLastReply,action,extra").Where("faid=?").Prepare(),
   222  		getInForum:         acc.Select(fa).Columns("faid,runOnTopicCreation,runDaysAfterTopicCreation,runDaysAfterTopicLastReply,action,extra").Where("fid=?").Prepare(),
   223  		getAll:             acc.Select(fa).Columns(allCols).Prepare(),
   224  		getNewTopicActions: acc.Select(fa).Columns(allCols).Where("fid=? AND runOnTopicCreation=1").Prepare(),
   225  
   226  		add:          acc.Insert(fa).Columns("fid,runOnTopicCreation,runDaysAfterTopicCreation,runDaysAfterTopicLastReply,action,extra").Fields("?,?,?,?,?,?").Prepare(),
   227  		delete:       acc.Delete(fa).Where("faid=?").Prepare(),
   228  		exists:       acc.Exists(fa, "faid").Prepare(),
   229  		count:        acc.Count(fa).Prepare(),
   230  		countInForum: acc.Count(fa).Where("fid=?").Prepare(),
   231  	}, acc.FirstError()
   232  }
   233  
   234  func (s *DefaultForumActionStore) DailyTick() error {
   235  	fas, e := s.GetAll()
   236  	if e != nil {
   237  		return e
   238  	}
   239  	for _, fa := range fas {
   240  		if e := fa.Run(); e != nil {
   241  			return e
   242  		}
   243  	}
   244  	return nil
   245  }
   246  
   247  func (s *DefaultForumActionStore) Get(id int) (*ForumAction, error) {
   248  	fa := ForumAction{ID: id}
   249  	var str string
   250  	e := s.get.QueryRow(id).Scan(&fa.Forum, &fa.RunOnTopicCreation, &fa.RunDaysAfterTopicCreation, &fa.RunDaysAfterTopicLastReply, &str, &fa.Extra)
   251  	fa.Action = ConvStringToAct(str)
   252  	return &fa, e
   253  }
   254  
   255  func (s *DefaultForumActionStore) GetInForum(fid int) (fas []*ForumAction, e error) {
   256  	rows, e := s.getInForum.Query(fid)
   257  	if e != nil {
   258  		return nil, e
   259  	}
   260  	defer rows.Close()
   261  	var str string
   262  	for rows.Next() {
   263  		fa := ForumAction{Forum: fid}
   264  		if e := rows.Scan(&fa.ID, &fa.RunOnTopicCreation, &fa.RunDaysAfterTopicCreation, &fa.RunDaysAfterTopicLastReply, &str, &fa.Extra); e != nil {
   265  			return nil, e
   266  		}
   267  		fa.Action = ConvStringToAct(str)
   268  		fas = append(fas, &fa)
   269  	}
   270  	return fas, rows.Err()
   271  }
   272  
   273  func (s *DefaultForumActionStore) GetAll() (fas []*ForumAction, e error) {
   274  	rows, e := s.getAll.Query()
   275  	if e != nil {
   276  		return nil, e
   277  	}
   278  	defer rows.Close()
   279  	var str string
   280  	for rows.Next() {
   281  		fa := ForumAction{}
   282  		if e := rows.Scan(&fa.ID, &fa.Forum, &fa.RunOnTopicCreation, &fa.RunDaysAfterTopicCreation, &fa.RunDaysAfterTopicLastReply, &str, &fa.Extra); e != nil {
   283  			return nil, e
   284  		}
   285  		fa.Action = ConvStringToAct(str)
   286  		fas = append(fas, &fa)
   287  	}
   288  	return fas, rows.Err()
   289  }
   290  
   291  func (s *DefaultForumActionStore) GetNewTopicActions(fid int) (fas []*ForumAction, e error) {
   292  	rows, e := s.getNewTopicActions.Query(fid)
   293  	if e != nil {
   294  		return nil, e
   295  	}
   296  	defer rows.Close()
   297  	var str string
   298  	for rows.Next() {
   299  		fa := ForumAction{RunOnTopicCreation: true}
   300  		if e := rows.Scan(&fa.ID, &fa.Forum, &fa.RunDaysAfterTopicCreation, &fa.RunDaysAfterTopicLastReply, &str, &fa.Extra); e != nil {
   301  			return nil, e
   302  		}
   303  		fa.Action = ConvStringToAct(str)
   304  		fas = append(fas, &fa)
   305  	}
   306  	return fas, rows.Err()
   307  }
   308  
   309  func (s *DefaultForumActionStore) Add(fa *ForumAction) (int, error) {
   310  	res, e := s.add.Exec(fa.Forum, fa.RunOnTopicCreation, fa.RunDaysAfterTopicCreation, fa.RunDaysAfterTopicLastReply, ConvActToString(fa.Action), fa.Extra)
   311  	if e != nil {
   312  		return 0, e
   313  	}
   314  	lastID, e := res.LastInsertId()
   315  	return int(lastID), e
   316  }
   317  
   318  func (s *DefaultForumActionStore) Delete(id int) error {
   319  	_, e := s.delete.Exec(id)
   320  	return e
   321  }
   322  
   323  func (s *DefaultForumActionStore) Exists(id int) bool {
   324  	err := s.exists.QueryRow(id).Scan(&id)
   325  	if err != nil && err != ErrNoRows {
   326  		LogError(err)
   327  	}
   328  	return err != ErrNoRows
   329  }
   330  
   331  func (s *DefaultForumActionStore) Count() (count int) {
   332  	err := s.count.QueryRow().Scan(&count)
   333  	if err != nil {
   334  		LogError(err)
   335  	}
   336  	return count
   337  }
   338  
   339  func (s *DefaultForumActionStore) CountInForum(fid int) (count int) {
   340  	return Countf(s.countInForum, fid)
   341  }
   342  
   343  /*type ForumActionRunnable struct {
   344  	ID         int
   345  	ActionID   int
   346  	TargetID   int
   347  	TargetType int // 0 = topic
   348  	RunAfter   int //unixtime
   349  }
   350  
   351  type ForumActionRunnableStoreInt interface {
   352  	GetAfterTime(unix int) ([]*ForumActionRunnable, error)
   353  	GetInForum(fid int) ([]*ForumActionRunnable, error)
   354  	Delete(faid int) error
   355  	DeleteInForum(fid int) error
   356  	DeleteByActionID(faid int) error
   357  	Count() int
   358  	CountInForum(fid int) int
   359  }
   360  
   361  type DefaultForumActionRunnableStore struct {
   362  	delete        *sql.Stmt
   363  	deleteInForum *sql.Stmt
   364  	count         *sql.Stmt
   365  	countInForum  *sql.Stmt
   366  }
   367  
   368  func NewDefaultForumActionRunnableStore(acc *qgen.Accumulator) (*DefaultForumActionRunnableStore, error) {
   369  	fa := "forums_actions"
   370  	return &DefaultForumActionRunnableStore{
   371  		delete:        acc.Delete(fa).Where("faid=?").Prepare(),
   372  		deleteInForum: acc.Delete(fa).Where("fid=?").Prepare(),
   373  		count:         acc.Count(fa).Prepare(),
   374  		countInForum:  acc.Count(fa).Where("faid=?").Prepare(),
   375  	}, acc.FirstError()
   376  }
   377  
   378  func (s *DefaultForumActionRunnableStore) Delete(id int) error {
   379  	_, e := s.delete.Exec(id)
   380  	return e
   381  }
   382  
   383  func (s *DefaultForumActionRunnableStore) DeleteInForum(fid int) error {
   384  	_, e := s.deleteInForum.Exec(id)
   385  	return e
   386  }
   387  
   388  func (s *DefaultForumActionRunnableStore) Count() (count int) {
   389  	err := s.count.QueryRow().Scan(&count)
   390  	if err != nil {
   391  		LogError(err)
   392  	}
   393  	return count
   394  }
   395  
   396  func (s *DefaultForumActionRunnableStore) CountInForum(fid int) (count int) {
   397  	return Countf(s.countInForum, fid)
   398  }
   399  */