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  }