feat: sync community aggregates
Sync telesrv 36eda30 (feat(communities): implement Layer 228 community aggregates). Skipped telesrv docs changes per public sync rules; normalized the public appearance seed label.
This commit is contained in:
parent
7de1766941
commit
da6a57e1a3
52 changed files with 5687 additions and 289 deletions
|
|
@ -508,6 +508,15 @@ func (s *Service) ListAdminedPublicChannels(ctx context.Context, userID int64) (
|
|||
return s.channels.ListAdminedPublicChannels(ctx, userID)
|
||||
}
|
||||
|
||||
// ListCommunityLinkableChannels returns owned/administered channels that are not
|
||||
// already linked to another Community. Private megagroups are valid candidates.
|
||||
func (s *Service) ListCommunityLinkableChannels(ctx context.Context, userID int64) ([]domain.Channel, error) {
|
||||
if s == nil || s.channels == nil || userID == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
return s.channels.ListCommunityLinkableChannels(ctx, userID)
|
||||
}
|
||||
|
||||
// ListStoryPostableChannels returns channels where user can publish stories.
|
||||
func (s *Service) ListStoryPostableChannels(ctx context.Context, userID int64) ([]domain.Channel, error) {
|
||||
if s == nil || s.channels == nil || userID == 0 {
|
||||
|
|
|
|||
185
internal/app/communities/service.go
Normal file
185
internal/app/communities/service.go
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
package communities
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
"telesrv/internal/store"
|
||||
)
|
||||
|
||||
// Service owns Community business validation. The store is the aggregate
|
||||
// transaction boundary because link changes span community/link and peer rows.
|
||||
type Service struct {
|
||||
communities store.CommunityStore
|
||||
}
|
||||
|
||||
func NewService(communities store.CommunityStore) *Service {
|
||||
return &Service{communities: communities}
|
||||
}
|
||||
|
||||
func validPeer(peer domain.Peer) bool {
|
||||
return peer.ID > 0 && (peer.Type == domain.PeerTypeChannel || peer.Type == domain.PeerTypeUser)
|
||||
}
|
||||
|
||||
func validVisibility(v domain.CommunityPeerVisibility) bool {
|
||||
return v == domain.CommunityPeerVisible || v == domain.CommunityPeerHidden
|
||||
}
|
||||
|
||||
func (s *Service) Create(ctx context.Context, userID int64, req domain.CreateCommunityRequest) (domain.CommunityView, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || !validPeer(req.InitialPeer) || !validVisibility(req.Visibility) {
|
||||
return domain.CommunityView{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
req.CreatorUserID = userID
|
||||
req.Title = strings.TrimSpace(req.Title)
|
||||
req.About = strings.TrimSpace(req.About)
|
||||
if req.Title == "" || utf8.RuneCountInString(req.Title) > domain.MaxCommunityTitleRunes {
|
||||
return domain.CommunityView{}, domain.ErrChannelTitleInvalid
|
||||
}
|
||||
if utf8.RuneCountInString(req.About) > domain.MaxCommunityAboutRunes {
|
||||
return domain.CommunityView{}, domain.ErrAboutTooLong
|
||||
}
|
||||
return s.communities.CreateCommunity(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) Get(ctx context.Context, userID, communityID int64) (domain.CommunityView, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 {
|
||||
return domain.CommunityView{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.GetCommunity(ctx, userID, communityID)
|
||||
}
|
||||
|
||||
func (s *Service) GetMany(ctx context.Context, userID int64, ids []int64) ([]domain.CommunityView, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 {
|
||||
return nil, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.GetCommunities(ctx, userID, ids)
|
||||
}
|
||||
|
||||
func (s *Service) ListJoined(ctx context.Context, userID int64) ([]domain.CommunityView, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 {
|
||||
return nil, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.ListJoinedCommunities(ctx, userID)
|
||||
}
|
||||
|
||||
func (s *Service) TogglePeerLink(ctx context.Context, userID int64, req domain.CommunityTogglePeerLinkRequest) (domain.CommunityTogglePeerLinkResult, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || req.CommunityID == 0 || !validPeer(req.Peer) {
|
||||
return domain.CommunityTogglePeerLinkResult{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
if !req.Deleted && !validVisibility(req.Visibility) {
|
||||
return domain.CommunityTogglePeerLinkResult{}, domain.ErrCommunityPeerInvalid
|
||||
}
|
||||
req.ActorUserID = userID
|
||||
return s.communities.ToggleCommunityPeerLink(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) SetCollapsed(ctx context.Context, userID, communityID int64, collapsed bool) (domain.CommunityView, bool, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 {
|
||||
return domain.CommunityView{}, false, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.SetCommunityCollapsed(ctx, userID, communityID, collapsed)
|
||||
}
|
||||
|
||||
func (s *Service) ListPeerLinkRequests(ctx context.Context, userID, communityID int64, offset string, limit int) (domain.CommunityPeerLinkRequestPage, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 {
|
||||
return domain.CommunityPeerLinkRequestPage{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
if limit <= 0 || limit > domain.MaxCommunityLinkRequests {
|
||||
limit = domain.MaxCommunityLinkRequests
|
||||
}
|
||||
return s.communities.ListCommunityPeerLinkRequests(ctx, userID, communityID, offset, limit)
|
||||
}
|
||||
|
||||
func (s *Service) DecidePeerLinkRequest(ctx context.Context, userID, communityID int64, peer domain.Peer, reject bool, date int) (domain.CommunityTogglePeerLinkResult, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 || !validPeer(peer) {
|
||||
return domain.CommunityTogglePeerLinkResult{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.DecideCommunityPeerLinkRequest(ctx, userID, communityID, peer, reject, date)
|
||||
}
|
||||
|
||||
func (s *Service) DecideAllPeerLinkRequests(ctx context.Context, userID, communityID int64, reject bool, date int) ([]domain.CommunityTogglePeerLinkResult, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 {
|
||||
return nil, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.DecideAllCommunityPeerLinkRequests(ctx, userID, communityID, reject, date)
|
||||
}
|
||||
|
||||
func (s *Service) ToggleParticipantBanned(ctx context.Context, userID, communityID, participantUserID int64, unban bool, date int) (domain.CommunityParticipantBanResult, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 || participantUserID == 0 {
|
||||
return domain.CommunityParticipantBanResult{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.ToggleCommunityParticipantBanned(ctx, userID, communityID, participantUserID, unban, date)
|
||||
}
|
||||
|
||||
func (s *Service) ParticipantJoinedChats(ctx context.Context, userID, communityID, participantUserID int64) (domain.CommunityParticipantJoinedChats, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 || participantUserID == 0 {
|
||||
return domain.CommunityParticipantJoinedChats{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
return s.communities.GetCommunityParticipantJoinedChats(ctx, userID, communityID, participantUserID)
|
||||
}
|
||||
|
||||
func (s *Service) Participants(ctx context.Context, userID, communityID int64, filter domain.ChannelParticipantsFilter, offset, limit int) (domain.CommunityParticipantList, error) {
|
||||
if s == nil || s.communities == nil || userID == 0 || communityID == 0 {
|
||||
return domain.CommunityParticipantList{}, domain.ErrCommunityInvalid
|
||||
}
|
||||
if offset < 0 {
|
||||
offset = 0
|
||||
}
|
||||
if offset > domain.MaxChannelParticipantsOffset {
|
||||
offset = domain.MaxChannelParticipantsOffset
|
||||
}
|
||||
if limit <= 0 || limit > domain.MaxCommunityParticipants {
|
||||
limit = domain.MaxCommunityParticipants
|
||||
}
|
||||
return s.communities.ListCommunityParticipants(ctx, userID, communityID, filter, offset, limit)
|
||||
}
|
||||
|
||||
func (s *Service) EditTitle(ctx context.Context, userID, communityID int64, title string) (domain.CommunityView, bool, error) {
|
||||
title = strings.TrimSpace(title)
|
||||
if title == "" || utf8.RuneCountInString(title) > domain.MaxCommunityTitleRunes {
|
||||
return domain.CommunityView{}, false, domain.ErrChannelTitleInvalid
|
||||
}
|
||||
return s.communities.EditCommunityTitle(ctx, userID, communityID, title)
|
||||
}
|
||||
|
||||
func (s *Service) EditAbout(ctx context.Context, userID, communityID int64, about string) (domain.CommunityView, bool, error) {
|
||||
about = strings.TrimSpace(about)
|
||||
if utf8.RuneCountInString(about) > domain.MaxCommunityAboutRunes {
|
||||
return domain.CommunityView{}, false, domain.ErrAboutTooLong
|
||||
}
|
||||
return s.communities.EditCommunityAbout(ctx, userID, communityID, about)
|
||||
}
|
||||
|
||||
func (s *Service) EditAdmin(ctx context.Context, userID int64, req domain.CommunityEditAdminRequest) (domain.CommunityView, bool, error) {
|
||||
if req.CommunityID == 0 || req.UserID == 0 || userID == 0 {
|
||||
return domain.CommunityView{}, false, domain.ErrCommunityInvalid
|
||||
}
|
||||
req.ActorUserID = userID
|
||||
return s.communities.EditCommunityAdmin(ctx, req)
|
||||
}
|
||||
|
||||
func (s *Service) EditDefaultBannedRights(ctx context.Context, userID, communityID int64, rights domain.ChannelBannedRights) (domain.CommunityView, bool, error) {
|
||||
return s.communities.EditCommunityDefaultBannedRights(ctx, userID, communityID, rights)
|
||||
}
|
||||
|
||||
func (s *Service) SetPhoto(ctx context.Context, userID, communityID int64, photo *domain.Photo, date int) (domain.CommunityView, bool, error) {
|
||||
return s.communities.SetCommunityPhoto(ctx, userID, communityID, photo, date)
|
||||
}
|
||||
|
||||
func (s *Service) Delete(ctx context.Context, userID, communityID int64, date int) (domain.CommunityView, []domain.Peer, error) {
|
||||
return s.communities.DeleteCommunity(ctx, userID, communityID, date)
|
||||
}
|
||||
|
||||
func (s *Service) SetPinned(ctx context.Context, userID, communityID int64, pinned bool) (bool, error) {
|
||||
return s.communities.SetCommunityPinned(ctx, userID, communityID, pinned)
|
||||
}
|
||||
|
||||
func (s *Service) ReorderPinned(ctx context.Context, userID int64, order []domain.Peer, force bool) (bool, error) {
|
||||
return s.communities.ReorderCommunityPinned(ctx, userID, order, force)
|
||||
}
|
||||
|
||||
func (s *Service) SearchScope(ctx context.Context, userID, communityID int64) (domain.CommunitySearchScope, error) {
|
||||
return s.communities.CommunitySearchScope(ctx, userID, communityID)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue