You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
309 lines
8.4 KiB
309 lines
8.4 KiB
3 years ago
|
package tdesktop
|
||
|
|
||
|
import (
|
||
|
"github.com/go-faster/errors"
|
||
|
|
||
|
"github.com/gotd/td/bin"
|
||
|
"github.com/gotd/td/internal/crypto"
|
||
|
)
|
||
|
|
||
|
// MTPConfigEnvironment is enum of config environment.
|
||
|
type MTPConfigEnvironment int32
|
||
|
|
||
|
func (e MTPConfigEnvironment) valid() bool {
|
||
|
return e == 0 || e == 1
|
||
|
}
|
||
|
|
||
|
// String implements fmt.Stringer.
|
||
|
func (e MTPConfigEnvironment) String() string {
|
||
|
switch e {
|
||
|
case 0:
|
||
|
return "production"
|
||
|
case 1:
|
||
|
return "test"
|
||
|
default:
|
||
|
return "unknown"
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Test denotes that environment is test.
|
||
|
func (e MTPConfigEnvironment) Test() bool {
|
||
|
return e == 1
|
||
|
}
|
||
|
|
||
|
// MTPConfig is a Telegram Desktop storage structure which stores MTProto config info.
|
||
|
//
|
||
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/mtproto/mtproto_config.h.
|
||
|
type MTPConfig struct {
|
||
|
Environment MTPConfigEnvironment
|
||
|
DCOptions MTPDCOptions
|
||
|
ChatSizeMax int32 // default: 200
|
||
|
MegagroupSizeMax int32 // default: 10000
|
||
|
ForwardedCountMax int32 // default: 100
|
||
|
OnlineUpdatePeriod int32 // default: 120000
|
||
|
OfflineBlurTimeout int32 // default: 5000
|
||
|
OfflineIdleTimeout int32 // default: 30000
|
||
|
OnlineFocusTimeout int32 // default: 1000
|
||
|
OnlineCloudTimeout int32 // default: 300000
|
||
|
NotifyCloudDelay int32 // default: 30000
|
||
|
NotifyDefaultDelay int32 // default: 1500
|
||
|
SavedGifsLimit int32 // default: 200
|
||
|
EditTimeLimit int32 // default: 172800
|
||
|
RevokeTimeLimit int32 // default: 172800
|
||
|
RevokePrivateTimeLimit int32 // default: 172800
|
||
|
RevokePrivateInbox bool // default: false
|
||
|
StickersRecentLimit int32 // default: 30
|
||
|
StickersFavedLimit int32 // default: 5
|
||
|
PinnedDialogsCountMax int32 // default: 5
|
||
|
PinnedDialogsInFolderMax int32 // default: 100
|
||
|
InternalLinksDomain string // default: "https://t.me/"
|
||
|
ChannelsReadMediaPeriod int32 // default: 86400 * 7
|
||
|
CallReceiveTimeoutMs int32 // default: 20000
|
||
|
CallRingTimeoutMs int32 // default: 90000
|
||
|
CallConnectTimeoutMs int32 // default: 30000
|
||
|
CallPacketTimeoutMs int32 // default: 10000
|
||
|
WebFileDCID int32 // default: 4
|
||
|
TxtDomainString string // default: ""
|
||
|
PhoneCallsEnabled bool // default: true
|
||
|
BlockedMode bool // default: false
|
||
|
CaptionLengthMax int32 // default: 1024
|
||
|
}
|
||
|
|
||
|
// See https://github.com/telegramdesktop/tdesktop/blob/v2.9.8/Telegram/SourceFiles/storage/storage_account.cpp#L938.
|
||
|
func readMTPConfig(tgf *tdesktopFile, localKey crypto.Key) (MTPConfig, error) {
|
||
|
encrypted, err := tgf.readArray()
|
||
|
if err != nil {
|
||
|
return MTPConfig{}, errors.Wrap(err, "read encrypted data")
|
||
|
}
|
||
|
|
||
|
decrypted, err := decryptLocal(encrypted, localKey)
|
||
|
if err != nil {
|
||
|
return MTPConfig{}, errors.Wrap(err, "decrypt data")
|
||
|
}
|
||
|
// Skip decrypted data length (uint32).
|
||
|
decrypted = decrypted[4:]
|
||
|
root := qtReader{buf: bin.Buffer{Buf: decrypted}}
|
||
|
|
||
|
cfgReader, err := root.subArray()
|
||
|
if err != nil {
|
||
|
return MTPConfig{}, errors.Wrap(err, "read config array")
|
||
|
}
|
||
|
|
||
|
var m MTPConfig
|
||
|
if err := m.deserialize(&cfgReader); err != nil {
|
||
|
return MTPConfig{}, errors.Wrap(err, "deserialize MTPConfig")
|
||
|
}
|
||
|
return m, err
|
||
|
}
|
||
|
|
||
|
func (m *MTPConfig) deserialize(r *qtReader) error {
|
||
|
version, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read version")
|
||
|
}
|
||
|
if version != kVersion {
|
||
|
return errors.Errorf("wrong version (expected %d, got %d)", kVersion, version)
|
||
|
}
|
||
|
|
||
|
environment, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read environment")
|
||
|
}
|
||
|
m.Environment = MTPConfigEnvironment(environment)
|
||
|
if !m.Environment.valid() {
|
||
|
return errors.Errorf("invalid environment %d", environment)
|
||
|
}
|
||
|
|
||
|
{
|
||
|
sub, err := r.subArray()
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
if err := m.DCOptions.deserialize(&sub); err != nil {
|
||
|
return errors.Wrap(err, "read DC options")
|
||
|
}
|
||
|
}
|
||
|
|
||
|
chatSizeMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read chatSizeMax")
|
||
|
}
|
||
|
m.ChatSizeMax = chatSizeMax
|
||
|
|
||
|
megagroupSizeMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read megagroupSizeMax")
|
||
|
}
|
||
|
m.MegagroupSizeMax = megagroupSizeMax
|
||
|
|
||
|
forwardedCountMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read forwardedCountMax")
|
||
|
}
|
||
|
m.ForwardedCountMax = forwardedCountMax
|
||
|
|
||
|
onlineUpdatePeriod, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read onlineUpdatePeriod")
|
||
|
}
|
||
|
m.OnlineUpdatePeriod = onlineUpdatePeriod
|
||
|
|
||
|
offlineBlurTimeout, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read offlineBlurTimeout")
|
||
|
}
|
||
|
m.OfflineBlurTimeout = offlineBlurTimeout
|
||
|
|
||
|
offlineIdleTimeout, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read offlineIdleTimeout")
|
||
|
}
|
||
|
m.OfflineIdleTimeout = offlineIdleTimeout
|
||
|
|
||
|
onlineFocusTimeout, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read onlineFocusTimeout")
|
||
|
}
|
||
|
m.OnlineFocusTimeout = onlineFocusTimeout
|
||
|
|
||
|
onlineCloudTimeout, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read onlineCloudTimeout")
|
||
|
}
|
||
|
m.OnlineCloudTimeout = onlineCloudTimeout
|
||
|
|
||
|
notifyCloudDelay, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read notifyCloudDelay")
|
||
|
}
|
||
|
m.NotifyCloudDelay = notifyCloudDelay
|
||
|
|
||
|
notifyDefaultDelay, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read notifyDefaultDelay")
|
||
|
}
|
||
|
m.NotifyDefaultDelay = notifyDefaultDelay
|
||
|
|
||
|
savedGifsLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read savedGifsLimit")
|
||
|
}
|
||
|
m.SavedGifsLimit = savedGifsLimit
|
||
|
|
||
|
editTimeLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read editTimeLimit")
|
||
|
}
|
||
|
m.EditTimeLimit = editTimeLimit
|
||
|
|
||
|
revokeTimeLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read revokeTimeLimit")
|
||
|
}
|
||
|
m.RevokeTimeLimit = revokeTimeLimit
|
||
|
|
||
|
revokePrivateTimeLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read revokePrivateTimeLimit")
|
||
|
}
|
||
|
m.RevokePrivateTimeLimit = revokePrivateTimeLimit
|
||
|
|
||
|
revokePrivateInbox, err := r.readUint32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read revokePrivateInbox")
|
||
|
}
|
||
|
m.RevokePrivateInbox = revokePrivateInbox == 1
|
||
|
|
||
|
stickersRecentLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read stickersRecentLimit")
|
||
|
}
|
||
|
m.StickersRecentLimit = stickersRecentLimit
|
||
|
|
||
|
stickersFavedLimit, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read stickersFavedLimit")
|
||
|
}
|
||
|
m.StickersFavedLimit = stickersFavedLimit
|
||
|
|
||
|
pinnedDialogsCountMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read pinnedDialogsCountMax")
|
||
|
}
|
||
|
m.PinnedDialogsCountMax = pinnedDialogsCountMax
|
||
|
|
||
|
pinnedDialogsInFolderMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read pinnedDialogsInFolderMax")
|
||
|
}
|
||
|
m.PinnedDialogsInFolderMax = pinnedDialogsInFolderMax
|
||
|
|
||
|
internalLinksDomain, err := r.readString()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read internalLinksDomain")
|
||
|
}
|
||
|
m.InternalLinksDomain = internalLinksDomain
|
||
|
|
||
|
channelsReadMediaPeriod, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read channelsReadMediaPeriod")
|
||
|
}
|
||
|
m.ChannelsReadMediaPeriod = channelsReadMediaPeriod
|
||
|
|
||
|
callReceiveTimeoutMs, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read callReceiveTimeoutMs")
|
||
|
}
|
||
|
m.CallReceiveTimeoutMs = callReceiveTimeoutMs
|
||
|
|
||
|
callRingTimeoutMs, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read callRingTimeoutMs")
|
||
|
}
|
||
|
m.CallRingTimeoutMs = callRingTimeoutMs
|
||
|
|
||
|
callConnectTimeoutMs, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read callConnectTimeoutMs")
|
||
|
}
|
||
|
m.CallConnectTimeoutMs = callConnectTimeoutMs
|
||
|
|
||
|
callPacketTimeoutMs, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read callPacketTimeoutMs")
|
||
|
}
|
||
|
m.CallPacketTimeoutMs = callPacketTimeoutMs
|
||
|
|
||
|
webFileDCID, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read webFileDCID")
|
||
|
}
|
||
|
m.WebFileDCID = webFileDCID
|
||
|
|
||
|
txtDomainString, err := r.readString()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read txtDomainString")
|
||
|
}
|
||
|
m.TxtDomainString = txtDomainString
|
||
|
|
||
|
phoneCallsEnabled, err := r.readUint32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read phoneCallsEnabled")
|
||
|
}
|
||
|
m.PhoneCallsEnabled = phoneCallsEnabled == 1
|
||
|
|
||
|
blockedMode, err := r.readUint32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read blockedMode")
|
||
|
}
|
||
|
m.BlockedMode = blockedMode == 1
|
||
|
|
||
|
captionLengthMax, err := r.readInt32()
|
||
|
if err != nil {
|
||
|
return errors.Wrap(err, "read captionLengthMax")
|
||
|
}
|
||
|
m.CaptionLengthMax = captionLengthMax
|
||
|
|
||
|
return nil
|
||
|
}
|