1
0
mirror of https://github.com/danog/Telegram.git synced 2024-12-12 09:29:55 +01:00
Telegram/legacy/TelegraphKit/TGConversation.m

987 lines
34 KiB
Mathematica
Raw Normal View History

2015-10-01 18:19:52 +02:00
#import "TGConversation.h"
#import "TGMessage.h"
#import "PSKeyValueCoder.h"
@implementation TGEncryptedConversationData
- (BOOL)isEqualToEncryptedData:(TGEncryptedConversationData *)other
{
if (_encryptedConversationId != other->_encryptedConversationId || _accessHash != other->_accessHash || _keyFingerprint != other->_keyFingerprint || _handshakeState != other->_handshakeState || _currentRekeyExchangeId != other->_currentRekeyExchangeId)
return false;
return true;
}
- (id)copyWithZone:(NSZone *)__unused zone
{
TGEncryptedConversationData *data = [[TGEncryptedConversationData alloc] init];
data->_encryptedConversationId = _encryptedConversationId;
data->_accessHash = _accessHash;
data->_keyFingerprint = _keyFingerprint;
data->_handshakeState = _handshakeState;
data->_currentRekeyExchangeId = _currentRekeyExchangeId;
data->_currentRekeyIsInitiatedByLocalClient = _currentRekeyIsInitiatedByLocalClient;
data->_currentRekeyNumber = _currentRekeyNumber;
data->_currentRekeyKey = _currentRekeyKey;
data->_currentRekeyKeyId = _currentRekeyKeyId;
return data;
}
- (void)serialize:(NSMutableData *)data
{
uint8_t version = 3;
[data appendBytes:&version length:1];
[data appendBytes:&_encryptedConversationId length:8];
[data appendBytes:&_accessHash length:8];
[data appendBytes:&_keyFingerprint length:8];
[data appendBytes:&_handshakeState length:4];
[data appendBytes:&_currentRekeyExchangeId length:8];
uint8_t currentRekeyIsInitiatedByLocalClient = _currentRekeyIsInitiatedByLocalClient ? 1 : 0;
[data appendBytes:&currentRekeyIsInitiatedByLocalClient length:1];
int32_t currentRekeyNumberLength = (int32_t)_currentRekeyNumber.length;
[data appendBytes:&currentRekeyNumberLength length:4];
if (_currentRekeyNumber != nil)
[data appendData:_currentRekeyNumber];
int32_t currentRekeyKeyLength = (int32_t)_currentRekeyKey.length;
[data appendBytes:&currentRekeyKeyLength length:4];
if (_currentRekeyKey != nil)
[data appendData:_currentRekeyKey];
[data appendBytes:&_currentRekeyKeyId length:8];
}
+ (TGEncryptedConversationData *)deserialize:(NSData *)data ptr:(int *)ptr
{
uint8_t version = 0;
[data getBytes:&version range:NSMakeRange(*ptr, 1)];
(*ptr) += 1;
if (version != 1 && version != 2 && version != 3)
{
TGLog(@"***** Invalid encrypted data version");
return nil;
}
TGEncryptedConversationData *encryptedData = [TGEncryptedConversationData new];
[data getBytes:&encryptedData->_encryptedConversationId range:NSMakeRange(*ptr, 8)];
(*ptr) += 8;
[data getBytes:&encryptedData->_accessHash range:NSMakeRange(*ptr, 8)];
(*ptr) += 8;
[data getBytes:&encryptedData->_keyFingerprint range:NSMakeRange(*ptr, 8)];
(*ptr) += 8;
if (version >= 2)
{
[data getBytes:&encryptedData->_handshakeState range:NSMakeRange(*ptr, 4)];
*ptr += 4;
}
if (version >= 3)
{
[data getBytes:&encryptedData->_currentRekeyExchangeId range:NSMakeRange(*ptr, 8)];
*ptr += 8;
uint8_t currentRekeyIsInitiatedByLocalClient = 0;
[data getBytes:&currentRekeyIsInitiatedByLocalClient range:NSMakeRange(*ptr, 1)];
encryptedData->_currentRekeyIsInitiatedByLocalClient = currentRekeyIsInitiatedByLocalClient;
*ptr += 1;
int32_t currentRekeyNumberLength = 0;
[data getBytes:&currentRekeyNumberLength range:NSMakeRange(*ptr, 4)];
*ptr += 4;
if (currentRekeyNumberLength != 0)
{
encryptedData->_currentRekeyNumber = [data subdataWithRange:NSMakeRange(*ptr, currentRekeyNumberLength)];
*ptr += currentRekeyNumberLength;
}
int32_t currentRekeyKeyLength = 0;
[data getBytes:&currentRekeyKeyLength range:NSMakeRange(*ptr, 4)];
*ptr += 4;
if (currentRekeyKeyLength != 0)
{
encryptedData->_currentRekeyKey = [data subdataWithRange:NSMakeRange(*ptr, currentRekeyKeyLength)];
*ptr += currentRekeyKeyLength;
}
[data getBytes:&encryptedData->_currentRekeyKeyId range:NSMakeRange(*ptr, 8)];
*ptr += 8;
}
return encryptedData;
}
@end
@implementation TGConversationParticipantsData
- (id)init
{
self = [super init];
if (self != nil)
{
_serializedData = nil;
}
return self;
}
- (id)copyWithZone:(NSZone *)__unused zone
{
TGConversationParticipantsData *participantsData = [[TGConversationParticipantsData alloc] init];
participantsData.chatAdminId = _chatAdminId;
participantsData.chatInvitedBy = _chatInvitedBy;
participantsData.chatInvitedDates = _chatInvitedDates;
participantsData.chatParticipantUids = _chatParticipantUids;
participantsData.chatParticipantSecretChatPeerIds = _chatParticipantSecretChatPeerIds;
participantsData.chatParticipantChatPeerIds = _chatParticipantChatPeerIds;
2016-02-25 01:03:51 +01:00
participantsData.chatAdminUids = _chatAdminUids;
2015-10-01 18:19:52 +02:00
participantsData.version = _version;
participantsData.exportedChatInviteString = _exportedChatInviteString;
return participantsData;
}
- (void)addParticipantWithId:(int32_t)uid invitedBy:(int32_t)invitedBy date:(int32_t)date
{
NSMutableArray *chatParticipantUids = [[NSMutableArray alloc] initWithArray:_chatParticipantUids];
if (![chatParticipantUids containsObject:@(uid)])
{
[chatParticipantUids addObject:@(uid)];
_chatParticipantUids = chatParticipantUids;
NSMutableDictionary *chatInvitedBy = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedBy];
chatInvitedBy[@(uid)] = @(invitedBy);
_chatInvitedBy = chatInvitedBy;
NSMutableDictionary *chatInvitedDates = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedDates];
chatInvitedDates[@(uid)] = @(date);
_chatInvitedDates = chatInvitedDates;
}
}
- (void)removeParticipantWithId:(int32_t)uid
{
NSMutableArray *chatParticipantUids = [[NSMutableArray alloc] initWithArray:_chatParticipantUids];
[chatParticipantUids removeObject:@(uid)];
_chatParticipantUids = chatParticipantUids;
NSMutableDictionary *chatInvitedBy = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedBy];
[chatInvitedBy removeObjectForKey:@(uid)];
_chatInvitedBy = chatInvitedBy;
NSMutableDictionary *chatInvitedDates = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedDates];
[chatInvitedDates removeObjectForKey:@(uid)];
_chatInvitedDates = chatInvitedDates;
2016-02-25 01:03:51 +01:00
NSMutableSet *chatAdminUids = [[NSMutableSet alloc] initWithSet:_chatAdminUids];
[chatAdminUids removeObject:@(uid)];
_chatAdminUids = chatAdminUids;
2015-10-01 18:19:52 +02:00
}
- (void)addSecretChatPeerWithId:(int64_t)peerId
{
NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantSecretChatPeerIds];
if (![chatParticipantSecretChatPeerIds containsObject:@(peerId)])
{
[chatParticipantSecretChatPeerIds addObject:@(peerId)];
_chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
}
}
- (void)removeSecretChatPeerWithId:(int64_t)peerId
{
NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantSecretChatPeerIds];
[chatParticipantSecretChatPeerIds removeObject:@(peerId)];
_chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
}
- (void)addChatPeerWithId:(int64_t)peerId
{
NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantChatPeerIds];
if (![chatParticipantChatPeerIds containsObject:@(peerId)])
{
[chatParticipantChatPeerIds addObject:@(peerId)];
_chatParticipantChatPeerIds = chatParticipantChatPeerIds;
}
}
- (void)removeChatPeerWithId:(int64_t)peerId
{
NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantChatPeerIds];
[chatParticipantChatPeerIds removeObject:@(peerId)];
_chatParticipantChatPeerIds = chatParticipantChatPeerIds;
}
+ (TGConversationParticipantsData *)deserializeData:(NSData *)data
{
TGConversationParticipantsData *participantsData = [[TGConversationParticipantsData alloc] init];
int length = (int)data.length;
int ptr = 0;
if (ptr + 12 > length)
{
return nil;
}
int version = 0;
[data getBytes:&version range:NSMakeRange(ptr, 4)];
ptr += 4;
int32_t formatVersion = 0;
if (version == (int)0xabcdef12)
{
[data getBytes:&formatVersion range:NSMakeRange(ptr, 4)];
ptr += 4;
[data getBytes:&version range:NSMakeRange(ptr, 4)];
ptr += 4;
}
int adminId = 0;
[data getBytes:&adminId range:NSMakeRange(ptr, 4)];
ptr += 4;
int count = 0;
[data getBytes:&count range:NSMakeRange(ptr, 4)];
ptr += 4;
NSMutableArray *uids = [[NSMutableArray alloc] init];
NSMutableDictionary *invitedBy = [[NSMutableDictionary alloc] init];
NSMutableDictionary *invitedDates = [[NSMutableDictionary alloc] init];
for (int i = 0; i < count; i++)
{
if (ptr + 4 > length)
{
TGLog(@"***** Invalid participants data");
return nil;
}
int uid = 0;
[data getBytes:&uid range:NSMakeRange(ptr, 4)];
ptr += 4;
if (ptr + 4 > length)
{
TGLog(@"***** Invalid participants data");
return nil;
}
int inviter = 0;
[data getBytes:&inviter range:NSMakeRange(ptr, 4)];
ptr += 4;
if (ptr + 4 > length)
{
TGLog(@"***** Invalid participants data");
return nil;
}
int date = 0;
[data getBytes:&date range:NSMakeRange(ptr, 4)];
ptr += 4;
NSNumber *nUid = [[NSNumber alloc] initWithInt:uid];
[uids addObject:nUid];
[invitedBy setObject:[[NSNumber alloc] initWithInt:inviter] forKey:nUid];
[invitedDates setObject:[[NSNumber alloc] initWithInt:date] forKey:nUid];
}
NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] init];
if (formatVersion >= 1)
{
int count = 0;
[data getBytes:&count range:NSMakeRange(ptr, 4)];
ptr += 4;
for (int i = 0; i < count; i++)
{
if (ptr + 8 > length)
{
TGLog(@"***** Invalid participants data");
return nil;
}
int64_t peerId = 0;
[data getBytes:&peerId range:NSMakeRange(ptr, 8)];
ptr += 8;
[chatParticipantSecretChatPeerIds addObject:@(peerId)];
}
}
NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] init];
if (formatVersion >= 2)
{
int count = 0;
[data getBytes:&count range:NSMakeRange(ptr, 4)];
ptr += 4;
for (int i = 0; i < count; i++)
{
if (ptr + 8 > length)
{
TGLog(@"***** Invalid participants data");
return nil;
}
int64_t peerId = 0;
[data getBytes:&peerId range:NSMakeRange(ptr, 8)];
ptr += 8;
[chatParticipantChatPeerIds addObject:@(peerId)];
}
}
if (formatVersion >= 3)
{
int32_t length = 0;
[data getBytes:&length range:NSMakeRange(ptr, 4)];
ptr += 4;
NSData *linkData = [data subdataWithRange:NSMakeRange(ptr, length)];
ptr += length;
participantsData.exportedChatInviteString = [[NSString alloc] initWithData:linkData encoding:NSUTF8StringEncoding];
}
2016-02-25 01:03:51 +01:00
if (formatVersion >= 4) {
int32_t length = 0;
[data getBytes:&length range:NSMakeRange(ptr, 4)];
ptr += 4;
NSMutableSet *chatAdminUids = [[NSMutableSet alloc] init];
for (int32_t i = 0; i < length; i++) {
int32_t item = 0;
[data getBytes:&item range:NSMakeRange(ptr, 4)];
ptr += 4;
[chatAdminUids addObject:@(item)];
}
participantsData.chatAdminUids = chatAdminUids;
}
2015-10-01 18:19:52 +02:00
participantsData.version = version;
participantsData.chatAdminId = adminId;
participantsData.chatParticipantUids = uids;
participantsData.chatInvitedBy = invitedBy;
participantsData.chatInvitedDates = invitedDates;
participantsData.chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
participantsData.chatParticipantChatPeerIds = chatParticipantChatPeerIds;
return participantsData;
}
- (NSData *)serializedData
{
if (_serializedData == nil)
{
NSMutableData *data = [[NSMutableData alloc] init];
int32_t magic = 0xabcdef12;
[data appendBytes:&magic length:4];
2016-02-25 01:03:51 +01:00
int32_t formatVersion = 4;
2015-10-01 18:19:52 +02:00
[data appendBytes:&formatVersion length:4];
[data appendBytes:&_version length:4];
[data appendBytes:&_chatAdminId length:4];
int count = (int)_chatParticipantUids.count;
[data appendBytes:&count length:4];
for (NSNumber *nUid in _chatParticipantUids)
{
int uid = [nUid intValue];
[data appendBytes:&uid length:4];
int invitedBy = [[_chatInvitedBy objectForKey:nUid] intValue];
[data appendBytes:&invitedBy length:4];
int invitedDate = [[_chatInvitedDates objectForKey:nUid] intValue];
[data appendBytes:&invitedDate length:4];
}
int32_t chatParticipantSecretChatPeerIdsCount = (int32_t)_chatParticipantSecretChatPeerIds.count;
[data appendBytes:&chatParticipantSecretChatPeerIdsCount length:4];
for (NSNumber *nPeerId in _chatParticipantSecretChatPeerIds)
{
int64_t peerId = [nPeerId longLongValue];
[data appendBytes:&peerId length:8];
}
int32_t chatParticipantChatPeerIdsCount = (int32_t)_chatParticipantChatPeerIds.count;
[data appendBytes:&chatParticipantChatPeerIdsCount length:4];
for (NSNumber *nPeerId in _chatParticipantChatPeerIds)
{
int64_t peerId = [nPeerId longLongValue];
[data appendBytes:&peerId length:8];
}
int32_t linkLength = (int32_t)_exportedChatInviteString.length;
[data appendBytes:&linkLength length:4];
if (linkLength != 0)
[data appendData:[_exportedChatInviteString dataUsingEncoding:NSUTF8StringEncoding]];
2016-02-25 01:03:51 +01:00
int32_t chatAdminUidsCount = (int32_t)_chatAdminUids.count;
[data appendBytes:&chatAdminUidsCount length:4];
for (NSNumber *nUid in _chatAdminUids) {
int32_t uid = [nUid intValue];
[data appendBytes:&uid length:4];
}
2015-10-01 18:19:52 +02:00
_serializedData = data;
}
return _serializedData;
}
@end
#pragma mark -
@implementation TGConversation
- (id)initWithConversationId:(int64_t)conversationId unreadCount:(int)unreadCount serviceUnreadCount:(int)serviceUnreadCount
{
self = [super init];
if (self != nil)
{
_conversationId = conversationId;
_unreadCount = unreadCount;
_serviceUnreadCount = serviceUnreadCount;
}
return self;
}
- (instancetype)initWithKeyValueCoder:(PSKeyValueCoder *)coder
{
self = [super init];
if (self != nil) {
_conversationId = [coder decodeInt64ForCKey:"i"];
_accessHash = [coder decodeInt64ForCKey:"ah"];
_displayVariant = [coder decodeInt32ForCKey:"dv"];
_kind = (uint8_t)[coder decodeInt32ForCKey:"kind"];
_pts = [coder decodeInt32ForCKey:"pts"];
_variantSortKey = TGConversationSortKeyDecode(coder, "vsort");
_importantSortKey = TGConversationSortKeyDecode(coder, "isort");
_unimportantSortKey = TGConversationSortKeyDecode(coder, "usort");
_maxReadMessageId = [coder decodeInt32ForCKey:"mread"];
_about = [coder decodeStringForCKey:"about"];
_username = [coder decodeStringForCKey:"username"];
_outgoing = [coder decodeInt32ForCKey:"out"];
_unread = [coder decodeInt32ForCKey:"unr"];
_deliveryError = [coder decodeInt32ForCKey:"der"];
_deliveryState = [coder decodeInt32ForCKey:"ds"];
_date = [coder decodeInt32ForCKey:"date"];
_fromUid = [coder decodeInt32ForCKey:"from"];
_text = [coder decodeStringForCKey:"text"];
_media = [TGMessage parseMediaAttachments:[coder decodeDataCorCKey:"media"]];
_unreadCount = [coder decodeInt32ForCKey:"ucount"];
_serviceUnreadCount = [coder decodeInt32ForCKey:"sucount"];
_chatTitle = [coder decodeStringForCKey:"ct"];
_chatPhotoSmall = [coder decodeStringForCKey:"cp.s"];
_chatPhotoMedium = [coder decodeStringForCKey:"cp.m"];
_chatPhotoBig = [coder decodeStringForCKey:"cp.l"];
_chatParticipants = nil;
_chatParticipantCount = 0;
_chatVersion = [coder decodeInt32ForCKey:"ver"];
_chatIsAdmin = [coder decodeInt32ForCKey:"adm"];
_channelRole = [coder decodeInt32ForCKey:"role"];
_channelIsReadOnly = [coder decodeInt32ForCKey:"ro"];
_flags = [coder decodeInt64ForCKey:"flags"];
_leftChat = false;
_kickedFromChat = [coder decodeInt32ForCKey:"kk"];
_isChat = false;
_isChannel = true;
_isDeleted = false;
_encryptedData = nil;
_isBroadcast = false;
2016-02-25 01:03:51 +01:00
_migratedToChannelId = [coder decodeInt32ForCKey:"mtci"];
_migratedToChannelAccessHash = [coder decodeInt64ForCKey:"mtch"];
_restrictionReason = [coder decodeStringForCKey:"rr"];
2015-10-01 18:19:52 +02:00
}
return self;
}
- (void)encodeWithKeyValueCoder:(PSKeyValueCoder *)coder {
[coder encodeInt64:_conversationId forCKey:"i"];
[coder encodeInt64:_accessHash forCKey:"ah"];
[coder encodeInt32:_displayVariant forCKey:"dv"];
[coder encodeInt32:_kind forCKey:"kind"];
[coder encodeInt32:_pts forCKey:"pts"];
TGConversationSortKeyEncode(coder, "vsort", _variantSortKey);
TGConversationSortKeyEncode(coder, "isort", _importantSortKey);
TGConversationSortKeyEncode(coder, "usort", _unimportantSortKey);
[coder encodeInt32:_maxReadMessageId forCKey:"mread"];
[coder encodeString:_about forCKey:"about"];
[coder encodeString:_username forCKey:"username"];
[coder encodeInt32:_outgoing ? 1 : 0 forCKey:"out"];
[coder encodeInt32:_unread ? 1 : 0 forCKey:"unr"];
[coder encodeInt32:_deliveryError ? 1 : 0 forCKey:"der"];
[coder encodeInt32:_deliveryState forCKey:"ds"];
[coder encodeInt32:_date forCKey:"date"];
[coder encodeInt32:_fromUid forCKey:"from"];
[coder encodeString:_text forCKey:"text"];
[coder encodeData:[TGMessage serializeMediaAttachments:true attachments:_media] forCKey:"media"];
[coder encodeInt32:_unreadCount forCKey:"ucount"];
[coder encodeInt32:_serviceUnreadCount forCKey:"sucount"];
[coder encodeString:_chatTitle forCKey:"ct"];
[coder encodeString:_chatPhotoSmall forCKey:"cp.s"];
[coder encodeString:_chatPhotoMedium forCKey:"cp.m"];
[coder encodeString:_chatPhotoBig forCKey:"cp.l"];
[coder encodeInt32:_chatVersion forCKey:"ver"];
[coder encodeInt32:_chatIsAdmin ? 1 : 0 forCKey:"adm"];
[coder encodeInt32:_channelRole forCKey:"role"];
[coder encodeInt32:_channelIsReadOnly ? 1 : 0 forCKey:"ro"];
[coder encodeInt64:_flags forCKey:"flags"];
[coder encodeInt32:_kickedFromChat forCKey:"kk"];
2016-02-25 01:03:51 +01:00
[coder encodeInt32:_migratedToChannelId forCKey:"mtci"];
[coder encodeInt64:_migratedToChannelAccessHash forCKey:"mtch"];
[coder encodeString:_restrictionReason forCKey:"rr"];
2015-10-01 18:19:52 +02:00
}
- (id)copyWithZone:(NSZone *)__unused zone
{
TGConversation *conversation = [[TGConversation alloc] init];
conversation.conversationId = _conversationId;
conversation.accessHash = _accessHash;
conversation.displayVariant = _displayVariant;
conversation->_kind = _kind;
conversation.pts = _pts;
conversation.variantSortKey = _variantSortKey;
conversation.importantSortKey = _importantSortKey;
conversation.unimportantSortKey = _unimportantSortKey;
conversation.maxReadMessageId = _maxReadMessageId;
conversation.about = _about;
conversation.username = _username;
conversation.outgoing = _outgoing;
conversation.unread = _unread;
conversation.deliveryError = _deliveryError;
conversation.deliveryState = _deliveryState;
conversation.date = _date;
conversation.fromUid = _fromUid;
conversation.text = _text;
conversation.media = _media;
conversation.unreadCount = _unreadCount;
conversation.serviceUnreadCount = _serviceUnreadCount;
conversation.chatTitle = _chatTitle;
conversation.chatPhotoSmall = _chatPhotoSmall;
conversation.chatPhotoMedium = _chatPhotoMedium;
conversation.chatPhotoBig = _chatPhotoBig;
conversation.chatParticipants = [_chatParticipants copy];
conversation.chatParticipantCount = _chatParticipantCount;
conversation.chatVersion = _chatVersion;
conversation.chatIsAdmin = _chatIsAdmin;
conversation.channelRole = _channelRole;
conversation.leftChat = _leftChat;
conversation.kickedFromChat = _kickedFromChat;
conversation.dialogListData = _dialogListData;
conversation.isChat = _isChat;
conversation.isDeleted = _isDeleted;
2016-02-25 01:03:51 +01:00
conversation.restrictionReason = _restrictionReason;
2015-10-01 18:19:52 +02:00
conversation.encryptedData = _encryptedData == nil ? nil : [_encryptedData copy];
conversation.isBroadcast = _isBroadcast;
conversation.isChannel = _isChannel;
conversation.channelIsReadOnly = _channelIsReadOnly;
conversation.flags = _flags;
2016-02-25 01:03:51 +01:00
conversation.migratedToChannelId = _migratedToChannelId;
conversation.migratedToChannelAccessHash = _migratedToChannelAccessHash;
2015-10-01 18:19:52 +02:00
return conversation;
}
- (void)setKind:(uint8_t)kind {
if (_kind != kind || kind != TGConversationSortKeyKind(_variantSortKey)) {
_kind = kind;
_variantSortKey = TGConversationSortKeyUpdateKind(_variantSortKey, kind);
_importantSortKey = TGConversationSortKeyUpdateKind(_importantSortKey, kind);
_unimportantSortKey = TGConversationSortKeyUpdateKind(_unimportantSortKey, kind);
}
}
- (void)setVariantSortKey:(TGConversationSortKey)variantSortKey {
_variantSortKey = variantSortKey;
_date = TGConversationSortKeyTimestamp(variantSortKey);
}
- (void)mergeMessage:(TGMessage *)message
{
_outgoing = message.outgoing;
_date = (int)message.date;
_fromUid = (int)message.fromUid;
_text = message.text;
_media = message.mediaAttachments;
_unread = message.unread;
_deliveryError = message.deliveryState == TGMessageDeliveryStateFailed;
_deliveryState = message.deliveryState;
}
- (NSData *)mediaData
{
if (_mediaData != nil)
return _mediaData;
_mediaData = [TGMessage serializeMediaAttachments:false attachments:_media];
return _mediaData;
}
- (BOOL)isEqualToConversation:(TGConversation *)other
{
if (_conversationId != other.conversationId || _outgoing != other.outgoing || _date != other.date || _fromUid != other.fromUid || ![_text isEqualToString:other.text] || _unreadCount != other.unreadCount || _serviceUnreadCount != other.serviceUnreadCount || _unread != other.unread || _isChat != other.isChat || _deliveryError != other.deliveryError || _deliveryState != other.deliveryState)
return false;
if (_media.count != other.media.count)
return false;
if (_media != nil && ![self.mediaData isEqualToData:other.mediaData])
return false;
if (_isChat)
{
if (![_chatTitle isEqualToString:other.chatTitle] || _chatVersion != other.chatVersion || _leftChat != other.leftChat || _kickedFromChat != other.kickedFromChat ||
(((_chatParticipants != nil) != (other.chatParticipants != nil)) || (_chatParticipants != nil && ![_chatParticipants.serializedData isEqualToData:other.chatParticipants.serializedData]))
)
return false;
if ((_chatPhotoSmall != nil) != (other.chatPhotoSmall != nil) || (_chatPhotoSmall != nil && ![_chatPhotoSmall isEqualToString:other.chatPhotoSmall]))
return false;
if ((_chatPhotoMedium != nil) != (other.chatPhotoMedium != nil) || (_chatPhotoMedium != nil && ![_chatPhotoMedium isEqualToString:other.chatPhotoMedium]))
return false;
if ((_chatPhotoBig != nil) != (other.chatPhotoBig != nil) || (_chatPhotoBig != nil && ![_chatPhotoBig isEqualToString:other.chatPhotoBig]))
return false;
}
if (_encryptedData != nil || other->_encryptedData != nil)
{
if ((_encryptedData != nil) != (other->_encryptedData != nil) || (_encryptedData != nil && ![_encryptedData isEqualToEncryptedData:other->_encryptedData]))
return false;
}
2016-02-25 01:03:51 +01:00
if (_flags != other->_flags) {
return false;
}
if (!TGStringCompare(_restrictionReason, other->_restrictionReason)) {
return false;
}
2015-10-01 18:19:52 +02:00
return true;
}
- (BOOL)isEqualToConversationIgnoringMessage:(TGConversation *)other
{
if (_conversationId != other.conversationId || _isChat != other.isChat)
return false;
if (_isChat)
{
if (![_chatTitle isEqualToString:other.chatTitle] || _chatVersion != other.chatVersion || _leftChat != other.leftChat || _kickedFromChat != other.kickedFromChat ||
(((_chatParticipants != nil) != (other.chatParticipants != nil)) || (_chatParticipants != nil && ![_chatParticipants.serializedData isEqualToData:other.chatParticipants.serializedData]))
)
return false;
if ((_chatPhotoSmall != nil) != (other.chatPhotoSmall != nil) || (_chatPhotoSmall != nil && ![_chatPhotoSmall isEqualToString:other.chatPhotoSmall]))
return false;
if ((_chatPhotoMedium != nil) != (other.chatPhotoMedium != nil) || (_chatPhotoMedium != nil && ![_chatPhotoMedium isEqualToString:other.chatPhotoMedium]))
return false;
if ((_chatPhotoBig != nil) != (other.chatPhotoBig != nil) || (_chatPhotoBig != nil && ![_chatPhotoBig isEqualToString:other.chatPhotoBig]))
return false;
}
2016-02-25 01:03:51 +01:00
if (_flags != other->_flags) {
return false;
}
if (!TGStringCompare(_restrictionReason, other->_restrictionReason)) {
return false;
}
2015-10-01 18:19:52 +02:00
return true;
}
- (NSData *)serializeChatPhoto
{
NSMutableData *data = [[NSMutableData alloc] init];
2016-02-25 01:03:51 +01:00
int32_t magic = 0x7acde441;
[data appendBytes:&magic length:4];
int32_t version = 4;
[data appendBytes:&version length:4];
2015-10-01 18:19:52 +02:00
for (int i = 0; i < 3; i++)
{
NSString *value = nil;
if (i == 0)
value = _chatPhotoSmall;
else if (i == 1)
value = _chatPhotoMedium;
else if (i == 2)
value = _chatPhotoBig;
NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
int length = (int)valueData.length;
[data appendBytes:&length length:4];
if (valueData != nil)
[data appendData:valueData];
}
2016-02-25 01:03:51 +01:00
int8_t hasEncryptedData = _encryptedData != nil ? 1 : 0;
[data appendBytes:&hasEncryptedData length:1];
2015-10-01 18:19:52 +02:00
if (_encryptedData != nil)
[_encryptedData serialize:data];
2016-02-25 01:03:51 +01:00
[data appendBytes:&_flags length:4];
[data appendBytes:&_migratedToChannelId length:4];
[data appendBytes:&_migratedToChannelAccessHash length:8];
2015-10-01 18:19:52 +02:00
return data;
}
- (void)deserializeChatPhoto:(NSData *)data
{
int ptr = 0;
2016-02-25 01:03:51 +01:00
int32_t version = 1;
if (data.length >= 4) {
int32_t magic = 0;
[data getBytes:&magic length:4];
if (magic == 0x7acde441) {
ptr += 4;
[data getBytes:&version range:NSMakeRange(ptr, 4)];
ptr += 4;
}
}
2015-10-01 18:19:52 +02:00
for (int i = 0; i < 3; i++)
{
int length = 0;
[data getBytes:&length range:NSMakeRange(ptr, 4)];
ptr += 4;
uint8_t *valueBytes = malloc(length);
[data getBytes:valueBytes range:NSMakeRange(ptr, length)];
ptr += length;
NSString *value = [[NSString alloc] initWithBytesNoCopy:valueBytes length:length encoding:NSUTF8StringEncoding freeWhenDone:true];
if (i == 0)
_chatPhotoSmall = value;
else if (i == 1)
_chatPhotoMedium = value;
else if (i == 2)
_chatPhotoBig = value;
}
2016-02-25 01:03:51 +01:00
if (version == 1) {
if (ptr + 4 <= (int)data.length) {
_encryptedData = [TGEncryptedConversationData deserialize:data ptr:&ptr];
}
} else {
if (version >= 2) {
int8_t hasEncryptedData = 0;
[data getBytes:&hasEncryptedData range:NSMakeRange(ptr, 1)];
ptr += 1;
if (hasEncryptedData) {
_encryptedData = [TGEncryptedConversationData deserialize:data ptr:&ptr];
}
[data getBytes:&_flags range:NSMakeRange(ptr, 4)];
ptr += 4;
if (version >= 4) {
[data getBytes:&_migratedToChannelId range:NSMakeRange(ptr, 4)];
ptr += 4;
[data getBytes:&_migratedToChannelAccessHash range:NSMakeRange(ptr, 8)];
ptr += 8;
}
}
2015-10-01 18:19:52 +02:00
}
}
- (bool)isEncrypted
{
return _encryptedData != nil;
}
- (void)mergeChannel:(TGConversation *)channel {
_chatTitle = channel.chatTitle;
_chatVersion = channel.chatVersion;
_chatPhotoBig = channel.chatPhotoBig;
_chatPhotoMedium = channel.chatPhotoMedium;
_chatPhotoSmall = channel.chatPhotoSmall;
_accessHash = channel.accessHash;
_username = channel.username;
_chatIsAdmin = channel.chatIsAdmin;
self.channelRole = channel.channelRole;
2016-02-25 01:03:51 +01:00
self.hasExplicitContent = channel.hasExplicitContent;
self.everybodyCanAddMembers = channel.everybodyCanAddMembers;
self.signaturesEnabled = channel.signaturesEnabled;
self.restrictionReason = channel.restrictionReason;
2015-10-01 18:19:52 +02:00
_channelIsReadOnly = channel.channelIsReadOnly;
_leftChat = channel.leftChat;
_kickedFromChat = channel.kickedFromChat;
2016-02-25 01:03:51 +01:00
self.kind = channel.leftChat || channel.kickedFromChat ? TGConversationKindTemporaryChannel : TGConversationKindPersistentChannel;
2015-10-01 18:19:52 +02:00
self.isVerified = channel.isVerified;
}
- (bool)currentUserCanSendMessages {
2016-02-25 01:03:51 +01:00
if (self.isChannelGroup) {
return true;
}
2015-10-01 18:19:52 +02:00
return (_channelRole == TGChannelRoleCreator || _channelRole == TGChannelRolePublisher || !_channelIsReadOnly) && !_leftChat && !_kickedFromChat;
}
+ (NSString *)chatTitleForDecoder:(PSKeyValueCoder *)coder {
return [coder decodeStringForCKey:"ct"];
}
- (bool)postAsChannel {
return _flags & TGConversationFlagPostAsChannel;
}
- (void)setPostAsChannel:(bool)postAsChannel {
if (postAsChannel) {
_flags |= TGConversationFlagPostAsChannel;
} else {
_flags &= ~TGConversationFlagPostAsChannel;
}
}
- (bool)displayExpanded {
return _flags & TGConversationFlagDisplayExpanded;
}
- (void)setDisplayExpanded:(bool)displayExpanded {
if (displayExpanded) {
_flags |= TGConversationFlagDisplayExpanded;
} else {
_flags &= ~TGConversationFlagDisplayExpanded;
}
}
- (bool)isVerified {
return _flags & TGConversationFlagVerified;
}
- (void)setIsVerified:(bool)isVerified {
if (isVerified) {
_flags |= TGConversationFlagVerified;
} else {
_flags &= ~TGConversationFlagVerified;
}
}
2016-02-25 01:03:51 +01:00
- (bool)hasExplicitContent {
return _flags & TGConversationFlagHasExplicitContent;
}
- (void)setHasExplicitContent:(bool)hasExplicitContent {
if (hasExplicitContent) {
_flags |= TGConversationFlagHasExplicitContent;
} else {
_flags &= ~TGConversationFlagHasExplicitContent;
}
}
- (bool)hasAdmins {
return _flags & TGConversationFlagHasAdmins;
}
- (void)setHasAdmins:(bool)hasAdmins {
if (hasAdmins) {
_flags |= TGConversationFlagHasAdmins;
} else {
_flags &= ~TGConversationFlagHasAdmins;
}
}
- (bool)isAdmin {
return _flags & TGConversationFlagIsAdmin;
}
- (void)setIsAdmin:(bool)isAdmin {
if (isAdmin) {
_flags |= TGConversationFlagIsAdmin;
} else {
_flags &= ~TGConversationFlagIsAdmin;
}
}
- (bool)isCreator {
return _flags & TGConversationFlagIsCreator;
}
- (void)setIsCreator:(bool)isCreator {
if (isCreator) {
_flags |= TGConversationFlagIsCreator;
} else {
_flags &= ~TGConversationFlagIsCreator;
}
}
- (bool)isChannelGroup {
return _flags & TGConversationFlagIsChannelGroup;
}
- (void)setIsChannelGroup:(bool)isChannelGroup {
if (isChannelGroup) {
_flags |= TGConversationFlagIsChannelGroup;
} else {
_flags &= ~TGConversationFlagIsChannelGroup;
}
}
- (bool)everybodyCanAddMembers {
return _flags & TGConversationFlagEverybodyCanAddMembers;
}
- (void)setEverybodyCanAddMembers:(bool)everybodyCanAddMembers {
if (everybodyCanAddMembers) {
_flags |= TGConversationFlagEverybodyCanAddMembers;
} else {
_flags &= ~TGConversationFlagEverybodyCanAddMembers;
}
}
- (bool)signaturesEnabled {
return _flags & TGConversationFlagSignaturesEnabled;
}
- (void)setSignaturesEnabled:(bool)signaturesEnabled {
if (signaturesEnabled) {
_flags |= TGConversationFlagSignaturesEnabled;
} else {
_flags &= ~TGConversationFlagSignaturesEnabled;
}
}
- (bool)isDeactivated {
return _flags & TGConversationFlagIsDeactivated;
}
- (void)setIsDeactivated:(bool)isDeactivated {
if (isDeactivated) {
_flags |= TGConversationFlagIsDeactivated;
} else {
_flags &= ~TGConversationFlagIsDeactivated;
}
}
2015-10-01 18:19:52 +02:00
@end