website/pkg/models/blocklist.go

167 lines
3.8 KiB
Go
Raw Normal View History

package models
import (
"time"
"code.nonshy.com/nonshy/website/pkg/log"
"gorm.io/gorm"
)
// Block table.
type Block struct {
ID uint64 `gorm:"primaryKey"`
SourceUserID uint64 `gorm:"index"`
TargetUserID uint64 `gorm:"index"`
CreatedAt time.Time
UpdatedAt time.Time
}
// AddBlock is sourceUserId adding targetUserId to their block list.
func AddBlock(sourceUserID, targetUserID uint64) error {
// Unfriend in the process.
RemoveFriend(sourceUserID, targetUserID)
// Did we already block this user?
var b *Block
forward := DB.Where(
"source_user_id = ? AND target_user_id = ?",
sourceUserID, targetUserID,
).First(&b).Error
// Update existing.
if forward == nil {
return nil
}
// Create the block.
b = &Block{
SourceUserID: sourceUserID,
TargetUserID: targetUserID,
}
return DB.Create(b).Error
}
// IsBlocking quickly sees if either user blocks the other.
func IsBlocking(sourceUserID, targetUserID uint64) bool {
b := &Block{}
result := DB.Where(
"(source_user_id = ? AND target_user_id = ?) OR "+
"(target_user_id = ? AND source_user_id = ?)",
sourceUserID, targetUserID,
sourceUserID, targetUserID,
).First(&b)
return result.Error == nil
}
// IsBlocked quickly checks if sourceUserID currently blocks targetUserID.
func IsBlocked(sourceUserID, targetUserID uint64) bool {
b := &Block{}
result := DB.Where(
"source_user_id = ? AND target_user_id = ?",
sourceUserID, targetUserID,
).First(&b)
return result.Error == nil
}
// PaginateBlockList views a user's blocklist.
func PaginateBlockList(user *User, pager *Pagination) ([]*User, error) {
// We paginate over the Block table.
var (
bs = []*Block{}
userIDs = []uint64{}
query *gorm.DB
)
query = DB.Where(
"source_user_id = ?",
user.ID,
)
query = query.Order(pager.Sort)
query.Model(&Block{}).Count(&pager.Total)
result := query.Offset(pager.GetOffset()).Limit(pager.PerPage).Find(&bs)
if result.Error != nil {
return nil, result.Error
}
// Now of these friends get their User objects.
for _, b := range bs {
userIDs = append(userIDs, b.TargetUserID)
}
return GetUsers(user, userIDs)
}
// BlockedUserIDs returns all user IDs blocked by the user (bidirectional, source or target user).
func BlockedUserIDs(userId uint64) []uint64 {
var (
bs = []*Block{}
userIDs = []uint64{}
)
DB.Where("source_user_id = ? OR target_user_id = ?", userId, userId).Find(&bs)
for _, row := range bs {
for _, uid := range []uint64{row.TargetUserID, row.SourceUserID} {
if uid != userId {
userIDs = append(userIDs, uid)
}
}
}
return userIDs
}
// BlockedUserIDsByUser returns all user IDs blocked by the user (one directional only)
func BlockedUserIDsByUser(userId uint64) []uint64 {
var (
bs = []*Block{}
userIDs = []uint64{}
)
DB.Where("source_user_id = ?", userId).Find(&bs)
for _, row := range bs {
for _, uid := range []uint64{row.TargetUserID, row.SourceUserID} {
if uid != userId {
userIDs = append(userIDs, uid)
}
}
}
return userIDs
}
// BlockedUsernames returns all usernames blocked by the user.
func BlockedUsernames(userId uint64) []string {
var (
userIDs = BlockedUserIDsByUser(userId)
usernames = []string{}
)
if len(userIDs) == 0 {
return usernames
}
if res := DB.Table(
"users",
).Select(
"username",
).Where(
"id IN ?", userIDs,
).Scan(&usernames); res.Error != nil {
log.Error("BlockedUsernames(%d): %s", userId, res.Error)
}
return usernames
}
// UnblockUser removes targetUserID from your blocklist.
func UnblockUser(sourceUserID, targetUserID uint64) error {
result := DB.Where(
"source_user_id = ? AND target_user_id = ?",
sourceUserID, targetUserID,
).Delete(&Block{})
return result.Error
}
// Save photo.
func (b *Block) Save() error {
result := DB.Save(b)
return result.Error
}