fix for preview

This commit is contained in:
onysd 2026-07-13 10:11:29 +03:00
parent 935876570b
commit d70148aca3
5 changed files with 240 additions and 14 deletions

View file

@ -42,6 +42,11 @@ type ChannelStore interface {
// viewerUserID may be zero for anonymous public-link projection; this lookup
// never returns viewer-specific membership or dialog state.
ResolvePublicChannelUsername(ctx context.Context, viewerUserID int64, username string) (domain.Channel, bool, error)
// ResolvePublicChannelInvite resolves an active (not revoked, not deleted,
// not expired) invite hash to its target channel/supergroup for the
// anonymous public invite-link preview page. It never returns viewer-specific
// membership state and does not require a userID.
ResolvePublicChannelInvite(ctx context.Context, hash string) (domain.Channel, domain.ChannelInvite, bool, error)
SearchPublicChannels(ctx context.Context, viewerUserID int64, query string, limit int) (domain.PublicChannelSearchResult, error)
SetSignatures(ctx context.Context, userID, channelID int64, enabled bool) (domain.Channel, error)
SetChannelPhoto(ctx context.Context, userID, channelID int64, photo *domain.Photo, date int) (domain.SetChannelPhotoResult, error)

View file

@ -273,6 +273,30 @@ func (s *ChannelStore) CheckInvite(_ context.Context, userID int64, hash string,
}, nil
}
// ResolvePublicChannelInvite is the anonymous, unauthenticated counterpart of
// CheckInvite: no userID/membership lookup, just "is this hash currently
// joinable" plus the public channel projection for the invite preview page.
func (s *ChannelStore) ResolvePublicChannelInvite(_ context.Context, hash string) (domain.Channel, domain.ChannelInvite, bool, error) {
hash = strings.TrimSpace(hash)
if hash == "" {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
s.mu.RLock()
defer s.mu.RUnlock()
invite, ok := s.invites[hash]
if !ok || invite.Revoked {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
if invite.ExpireDate > 0 && invite.ExpireDate < int(time.Now().Unix()) {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
channel, ok := s.channels[invite.ChannelID]
if !ok || channel.Deleted {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
return channel, invite, true, nil
}
func (s *ChannelStore) ImportInvite(_ context.Context, req domain.ImportChannelInviteRequest) (domain.CreateChannelResult, error) {
if req.UserID == 0 || strings.TrimSpace(req.Hash) == "" {
return domain.CreateChannelResult{}, domain.ErrInviteHashEmpty

View file

@ -36,6 +36,27 @@ func (s *ChannelStore) CheckInvite(ctx context.Context, userID int64, hash strin
return domain.CheckChannelInviteResult{Channel: channel, Invite: invite, Already: already, Self: member}, nil
}
// ResolvePublicChannelInvite is the anonymous, unauthenticated counterpart of
// CheckInvite: no userID/membership lookup, just "is this hash currently
// joinable" plus the public channel projection for the invite preview page.
func (s *ChannelStore) ResolvePublicChannelInvite(ctx context.Context, hash string) (domain.Channel, domain.ChannelInvite, bool, error) {
hash = strings.TrimSpace(hash)
if hash == "" {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
channel, invite, err := s.getInviteByHash(ctx, s.db, hash)
if err != nil {
if errors.Is(err, domain.ErrInviteHashInvalid) {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
return domain.Channel{}, domain.ChannelInvite{}, false, err
}
if invite.ExpireDate > 0 && invite.ExpireDate < nowUnix() {
return domain.Channel{}, domain.ChannelInvite{}, false, nil
}
return channel, invite, true, nil
}
func (s *ChannelStore) ImportInvite(ctx context.Context, req domain.ImportChannelInviteRequest) (domain.CreateChannelResult, error) {
if req.UserID == 0 || strings.TrimSpace(req.Hash) == "" {
return domain.CreateChannelResult{}, domain.ErrInviteHashEmpty