merged from gramsrv upstream
This commit is contained in:
parent
79c64ee916
commit
21a0856587
651 changed files with 54774 additions and 4590 deletions
|
|
@ -1,9 +1,13 @@
|
|||
package domain
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const officialWelcomeMessageTemplate = "👋 Welcome to OwpenGram!\n\nYou just signed in via %s.\n\nIf this wasn't you, revoke this session from \"Settings > Privacy and Security > Active sessions\" immediately."
|
||||
|
|
@ -40,3 +44,202 @@ func SignInMethodLabel(u User) string {
|
|||
}
|
||||
return "phone number"
|
||||
}
|
||||
|
||||
const (
|
||||
MaxWelcomeMessagesPerPeer = 5
|
||||
MaxWelcomeMessageContentBytes = 4 << 20
|
||||
InitialWelcomeRevision = int64(1)
|
||||
WelcomeMessageDeliveryTTL = 24 * time.Hour
|
||||
)
|
||||
|
||||
var (
|
||||
ErrWelcomeMessageInvalid = errors.New("welcome message invalid")
|
||||
ErrWelcomeMessagePeerInvalid = errors.New("welcome message peer invalid")
|
||||
ErrWelcomeMessageForbidden = errors.New("welcome message forbidden")
|
||||
ErrWelcomeMessageNotFound = errors.New("welcome message not found")
|
||||
ErrWelcomeMessageNotModified = errors.New("welcome message not modified")
|
||||
ErrWelcomeMessageLimit = errors.New("welcome message limit exceeded")
|
||||
ErrWelcomeMessageRandomIDConflict = errors.New("welcome message random id conflict")
|
||||
ErrWelcomeMessageRevisionOverflow = errors.New("welcome message revision overflow")
|
||||
)
|
||||
|
||||
// WelcomeMessageContent is a durable peer template. It intentionally does not
|
||||
// contain transient receiver, device, callback, report, TTL or reply fields.
|
||||
type WelcomeMessageContent struct {
|
||||
Message string
|
||||
Entities []MessageEntity
|
||||
Media *MessageMedia
|
||||
ReplyMarkup *MessageReplyMarkup
|
||||
RichMessage *MessageRichMessage
|
||||
InvertMedia bool
|
||||
NoForwards bool
|
||||
}
|
||||
|
||||
func (c WelcomeMessageContent) Validate() error {
|
||||
if err := ValidateEphemeralContent(EphemeralContent{
|
||||
Message: c.Message, Entities: c.Entities, Media: c.Media,
|
||||
ReplyMarkup: c.ReplyMarkup, RichMessage: c.RichMessage,
|
||||
}); err != nil {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
if c.InvertMedia && c.Media == nil {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
raw, err := json.Marshal(c)
|
||||
if err != nil || len(raw) > MaxWelcomeMessageContentBytes {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WelcomeMessage struct {
|
||||
ID int
|
||||
Peer Peer
|
||||
CreatorUserID int64
|
||||
Date int
|
||||
EditDate int
|
||||
RandomID int64
|
||||
Content WelcomeMessageContent
|
||||
CreateFingerprint [32]byte
|
||||
Version uint64
|
||||
}
|
||||
|
||||
func (m WelcomeMessage) ValidateStored() error {
|
||||
if m.ID <= 0 || m.ID > MaxMessageBoxID || m.Peer.Type != PeerTypeChannel || m.Peer.ID <= 0 ||
|
||||
m.CreatorUserID <= 0 || m.Date <= 0 || m.RandomID == 0 || m.Version == 0 ||
|
||||
(m.EditDate != 0 && m.EditDate < m.Date) || m.CreateFingerprint == ([32]byte{}) {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
return m.Content.Validate()
|
||||
}
|
||||
|
||||
type CreateWelcomeMessageRequest struct {
|
||||
Peer Peer
|
||||
CreatorUserID int64
|
||||
Date int
|
||||
RandomID int64
|
||||
Content WelcomeMessageContent
|
||||
CreateFingerprint [32]byte
|
||||
}
|
||||
|
||||
func (r CreateWelcomeMessageRequest) Validate() error {
|
||||
if r.Peer.Type != PeerTypeChannel || r.Peer.ID <= 0 || r.CreatorUserID <= 0 ||
|
||||
r.Date <= 0 || r.RandomID == 0 || r.CreateFingerprint == ([32]byte{}) {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
return r.Content.Validate()
|
||||
}
|
||||
|
||||
type WelcomeMessageEditFields struct {
|
||||
SetMessage bool
|
||||
Message string
|
||||
SetEntities bool
|
||||
Entities []MessageEntity
|
||||
SetMedia bool
|
||||
Media *MessageMedia
|
||||
SetReplyMarkup bool
|
||||
ReplyMarkup *MessageReplyMarkup
|
||||
SetRichMessage bool
|
||||
RichMessage *MessageRichMessage
|
||||
SetInvertMedia bool
|
||||
InvertMedia bool
|
||||
}
|
||||
|
||||
func (f WelcomeMessageEditFields) Empty() bool {
|
||||
return !f.SetMessage && !f.SetEntities && !f.SetMedia && !f.SetReplyMarkup &&
|
||||
!f.SetRichMessage && !f.SetInvertMedia
|
||||
}
|
||||
|
||||
func (f WelcomeMessageEditFields) Apply(current WelcomeMessageContent) (WelcomeMessageContent, error) {
|
||||
if f.Empty() {
|
||||
return WelcomeMessageContent{}, ErrWelcomeMessageInvalid
|
||||
}
|
||||
if f.SetMessage {
|
||||
current.Message = f.Message
|
||||
}
|
||||
if f.SetEntities {
|
||||
current.Entities = f.Entities
|
||||
}
|
||||
if f.SetMedia {
|
||||
current.Media = f.Media
|
||||
}
|
||||
if f.SetReplyMarkup {
|
||||
current.ReplyMarkup = f.ReplyMarkup
|
||||
}
|
||||
if f.SetRichMessage {
|
||||
current.RichMessage = f.RichMessage
|
||||
}
|
||||
if f.SetInvertMedia {
|
||||
current.InvertMedia = f.InvertMedia
|
||||
}
|
||||
if err := current.Validate(); err != nil {
|
||||
return WelcomeMessageContent{}, err
|
||||
}
|
||||
return current, nil
|
||||
}
|
||||
|
||||
type EditWelcomeMessageRequest struct {
|
||||
Peer Peer
|
||||
ID int
|
||||
EditDate int
|
||||
Fields WelcomeMessageEditFields
|
||||
}
|
||||
|
||||
func (r EditWelcomeMessageRequest) Validate() error {
|
||||
if r.Peer.Type != PeerTypeChannel || r.Peer.ID <= 0 || r.ID <= 0 ||
|
||||
r.ID > MaxMessageBoxID || r.EditDate <= 0 || r.Fields.Empty() {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type WelcomeMessageList struct {
|
||||
Hash int64
|
||||
Messages []WelcomeMessage
|
||||
NotModified bool
|
||||
}
|
||||
|
||||
// WelcomeMessageDelivery is a short-lived, non-PTS snapshot created in the
|
||||
// same transaction as one inactive->active membership transition. It is not a
|
||||
// message-history row and must be physically removed no later than ExpiresAt.
|
||||
type WelcomeMessageDelivery struct {
|
||||
ID int64
|
||||
JoinEventID int64
|
||||
ChannelID int64
|
||||
TargetUserID int64
|
||||
TemplateID int
|
||||
EphemeralID int
|
||||
JoinedAt int
|
||||
Content WelcomeMessageContent
|
||||
AttemptCount int
|
||||
ExpiresAt time.Time
|
||||
}
|
||||
|
||||
func (d WelcomeMessageDelivery) ValidateStored(now time.Time) error {
|
||||
if d.ID <= 0 || d.JoinEventID <= 0 || d.ChannelID <= 0 || d.TargetUserID <= 0 ||
|
||||
d.TemplateID <= 0 || d.EphemeralID <= 0 || d.EphemeralID > MaxMessageBoxID ||
|
||||
d.JoinedAt <= 0 || d.AttemptCount <= 0 || d.ExpiresAt.IsZero() || !d.ExpiresAt.After(now) {
|
||||
return ErrWelcomeMessageInvalid
|
||||
}
|
||||
return d.Content.Validate()
|
||||
}
|
||||
|
||||
func WelcomeCreateFingerprint(peer Peer, creatorUserID, randomID int64, content WelcomeMessageContent) ([32]byte, error) {
|
||||
raw, err := json.Marshal(struct {
|
||||
Peer Peer
|
||||
CreatorUserID int64
|
||||
RandomID int64
|
||||
Content WelcomeMessageContent
|
||||
}{peer, creatorUserID, randomID, content})
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
return sha256.Sum256(raw), nil
|
||||
}
|
||||
|
||||
func NextWelcomeRevision(current int64) (int64, error) {
|
||||
if current < InitialWelcomeRevision || current == math.MaxInt64 {
|
||||
return 0, ErrWelcomeMessageRevisionOverflow
|
||||
}
|
||||
return current + 1, nil
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue