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 */