github.com/Azareal/Gosora@v0.0.0-20210729070923-553e66b59003/common/relations.go (about) 1 package common 2 3 import ( 4 "database/sql" 5 6 qgen "github.com/Azareal/Gosora/query_gen" 7 ) 8 9 var UserBlocks BlockStore 10 11 //var UserFriends FriendStore 12 13 type BlockStore interface { 14 IsBlockedBy(blocker, blockee int) (bool, error) 15 BulkIsBlockedBy(blockers []int, blockee int) (bool, error) 16 Add(blocker, blockee int) error 17 Remove(blocker, blockee int) error 18 BlockedByOffset(blocker, offset, perPage int) ([]int, error) 19 BlockedByCount(blocker int) int 20 } 21 22 type DefaultBlockStore struct { 23 isBlocked *sql.Stmt 24 add *sql.Stmt 25 remove *sql.Stmt 26 blockedBy *sql.Stmt 27 blockedByCount *sql.Stmt 28 } 29 30 func NewDefaultBlockStore(acc *qgen.Accumulator) (*DefaultBlockStore, error) { 31 ub := "users_blocks" 32 return &DefaultBlockStore{ 33 isBlocked: acc.Select(ub).Cols("blocker").Where("blocker=? AND blockedUser=?").Prepare(), 34 add: acc.Insert(ub).Columns("blocker,blockedUser").Fields("?,?").Prepare(), 35 remove: acc.Delete(ub).Where("blocker=? AND blockedUser=?").Prepare(), 36 blockedBy: acc.Select(ub).Columns("blockedUser").Where("blocker=?").Limit("?,?").Prepare(), 37 blockedByCount: acc.Count(ub).Where("blocker=?").Prepare(), 38 }, acc.FirstError() 39 } 40 41 func (s *DefaultBlockStore) IsBlockedBy(blocker, blockee int) (bool, error) { 42 e := s.isBlocked.QueryRow(blocker, blockee).Scan(&blocker) 43 if e == ErrNoRows { 44 return false, nil 45 } 46 return e == nil, e 47 } 48 49 // TODO: Optimise the query to avoid preparing it on the spot? Maybe, use knowledge of the most common IN() parameter counts? 50 func (s *DefaultBlockStore) BulkIsBlockedBy(blockers []int, blockee int) (bool, error) { 51 if len(blockers) == 0 { 52 return false, nil 53 } 54 if len(blockers) == 1 { 55 return s.IsBlockedBy(blockers[0], blockee) 56 } 57 idList, q := inqbuild(blockers) 58 count, e := qgen.NewAcc().Count("users_blocks").Where("blocker IN(" + q + ") AND blockedUser=?").TotalP(idList...) 59 if e == ErrNoRows { 60 return false, nil 61 } 62 return count == 0, e 63 } 64 65 func (s *DefaultBlockStore) Add(blocker, blockee int) error { 66 _, e := s.add.Exec(blocker, blockee) 67 return e 68 } 69 70 func (s *DefaultBlockStore) Remove(blocker, blockee int) error { 71 _, e := s.remove.Exec(blocker, blockee) 72 return e 73 } 74 75 func (s *DefaultBlockStore) BlockedByOffset(blocker, offset, perPage int) (uids []int, err error) { 76 rows, e := s.blockedBy.Query(blocker, offset, perPage) 77 if e != nil { 78 return nil, e 79 } 80 defer rows.Close() 81 for rows.Next() { 82 var uid int 83 if e := rows.Scan(&uid); e != nil { 84 return nil, e 85 } 86 uids = append(uids, uid) 87 } 88 return uids, rows.Err() 89 } 90 91 func (s *DefaultBlockStore) BlockedByCount(blocker int) (count int) { 92 e := s.blockedByCount.QueryRow(blocker).Scan(&count) 93 if e != nil { 94 LogError(e) 95 } 96 return count 97 } 98 99 type FriendInvite struct { 100 Requester int 101 Target int 102 } 103 104 type FriendStore interface { 105 AddInvite(requester, target int) error 106 Confirm(requester, target int) error 107 GetOwSentInvites(uid int) ([]FriendInvite, error) 108 GetOwnRecvInvites(uid int) ([]FriendInvite, error) 109 } 110 111 type DefaultFriendStore struct { 112 addInvite *sql.Stmt 113 confirm *sql.Stmt 114 getOwnSentInvites *sql.Stmt 115 getOwnRecvInvites *sql.Stmt 116 } 117 118 func NewDefaultFriendStore(acc *qgen.Accumulator) (*DefaultFriendStore, error) { 119 ufi := "users_friends_invites" 120 return &DefaultFriendStore{ 121 addInvite: acc.Insert(ufi).Columns("requester,target").Fields("?,?").Prepare(), 122 confirm: acc.Insert("users_friends").Columns("uid,uid2").Fields("?,?").Prepare(), 123 getOwnSentInvites: acc.Select(ufi).Cols("requester,target").Where("requester=?").Prepare(), 124 getOwnRecvInvites: acc.Select(ufi).Cols("requester,target").Where("target=?").Prepare(), 125 }, acc.FirstError() 126 } 127 128 func (s *DefaultFriendStore) AddInvite(requester, target int) error { 129 _, e := s.addInvite.Exec(requester, target) 130 return e 131 } 132 133 func (s *DefaultFriendStore) Confirm(requester, target int) error { 134 _, e := s.confirm.Exec(requester, target) 135 return e 136 } 137 138 func (s *DefaultFriendStore) GetOwnSentInvites(uid int) ([]FriendInvite, error) { 139 return nil, nil 140 } 141 func (s *DefaultFriendStore) GetOwnRecvInvites(uid int) ([]FriendInvite, error) { 142 return nil, nil 143 }