/legacy/TelegraphKit/TGConversation.m

https://gitlab.com/iranjith4/Telegram · Objective C · 791 lines · 661 code · 130 blank · 0 comment · 211 complexity · 16aaf066651b022db6d6eeac779fec55 MD5 · raw file

  1. #import "TGConversation.h"
  2. #import "TGMessage.h"
  3. #import "PSKeyValueCoder.h"
  4. typedef enum {
  5. TGConversationFlagDisplayExpanded = (1 << 0),
  6. TGConversationFlagPostAsChannel = (1 << 1),
  7. TGConversationFlagKicked = (1 << 2),
  8. TGConversationFlagVerified = (1 << 3)
  9. } TGConversationFlags;
  10. @implementation TGEncryptedConversationData
  11. - (BOOL)isEqualToEncryptedData:(TGEncryptedConversationData *)other
  12. {
  13. if (_encryptedConversationId != other->_encryptedConversationId || _accessHash != other->_accessHash || _keyFingerprint != other->_keyFingerprint || _handshakeState != other->_handshakeState || _currentRekeyExchangeId != other->_currentRekeyExchangeId)
  14. return false;
  15. return true;
  16. }
  17. - (id)copyWithZone:(NSZone *)__unused zone
  18. {
  19. TGEncryptedConversationData *data = [[TGEncryptedConversationData alloc] init];
  20. data->_encryptedConversationId = _encryptedConversationId;
  21. data->_accessHash = _accessHash;
  22. data->_keyFingerprint = _keyFingerprint;
  23. data->_handshakeState = _handshakeState;
  24. data->_currentRekeyExchangeId = _currentRekeyExchangeId;
  25. data->_currentRekeyIsInitiatedByLocalClient = _currentRekeyIsInitiatedByLocalClient;
  26. data->_currentRekeyNumber = _currentRekeyNumber;
  27. data->_currentRekeyKey = _currentRekeyKey;
  28. data->_currentRekeyKeyId = _currentRekeyKeyId;
  29. return data;
  30. }
  31. - (void)serialize:(NSMutableData *)data
  32. {
  33. uint8_t version = 3;
  34. [data appendBytes:&version length:1];
  35. [data appendBytes:&_encryptedConversationId length:8];
  36. [data appendBytes:&_accessHash length:8];
  37. [data appendBytes:&_keyFingerprint length:8];
  38. [data appendBytes:&_handshakeState length:4];
  39. [data appendBytes:&_currentRekeyExchangeId length:8];
  40. uint8_t currentRekeyIsInitiatedByLocalClient = _currentRekeyIsInitiatedByLocalClient ? 1 : 0;
  41. [data appendBytes:&currentRekeyIsInitiatedByLocalClient length:1];
  42. int32_t currentRekeyNumberLength = (int32_t)_currentRekeyNumber.length;
  43. [data appendBytes:&currentRekeyNumberLength length:4];
  44. if (_currentRekeyNumber != nil)
  45. [data appendData:_currentRekeyNumber];
  46. int32_t currentRekeyKeyLength = (int32_t)_currentRekeyKey.length;
  47. [data appendBytes:&currentRekeyKeyLength length:4];
  48. if (_currentRekeyKey != nil)
  49. [data appendData:_currentRekeyKey];
  50. [data appendBytes:&_currentRekeyKeyId length:8];
  51. }
  52. + (TGEncryptedConversationData *)deserialize:(NSData *)data ptr:(int *)ptr
  53. {
  54. uint8_t version = 0;
  55. [data getBytes:&version range:NSMakeRange(*ptr, 1)];
  56. (*ptr) += 1;
  57. if (version != 1 && version != 2 && version != 3)
  58. {
  59. TGLog(@"***** Invalid encrypted data version");
  60. return nil;
  61. }
  62. TGEncryptedConversationData *encryptedData = [TGEncryptedConversationData new];
  63. [data getBytes:&encryptedData->_encryptedConversationId range:NSMakeRange(*ptr, 8)];
  64. (*ptr) += 8;
  65. [data getBytes:&encryptedData->_accessHash range:NSMakeRange(*ptr, 8)];
  66. (*ptr) += 8;
  67. [data getBytes:&encryptedData->_keyFingerprint range:NSMakeRange(*ptr, 8)];
  68. (*ptr) += 8;
  69. if (version >= 2)
  70. {
  71. [data getBytes:&encryptedData->_handshakeState range:NSMakeRange(*ptr, 4)];
  72. *ptr += 4;
  73. }
  74. if (version >= 3)
  75. {
  76. [data getBytes:&encryptedData->_currentRekeyExchangeId range:NSMakeRange(*ptr, 8)];
  77. *ptr += 8;
  78. uint8_t currentRekeyIsInitiatedByLocalClient = 0;
  79. [data getBytes:&currentRekeyIsInitiatedByLocalClient range:NSMakeRange(*ptr, 1)];
  80. encryptedData->_currentRekeyIsInitiatedByLocalClient = currentRekeyIsInitiatedByLocalClient;
  81. *ptr += 1;
  82. int32_t currentRekeyNumberLength = 0;
  83. [data getBytes:&currentRekeyNumberLength range:NSMakeRange(*ptr, 4)];
  84. *ptr += 4;
  85. if (currentRekeyNumberLength != 0)
  86. {
  87. encryptedData->_currentRekeyNumber = [data subdataWithRange:NSMakeRange(*ptr, currentRekeyNumberLength)];
  88. *ptr += currentRekeyNumberLength;
  89. }
  90. int32_t currentRekeyKeyLength = 0;
  91. [data getBytes:&currentRekeyKeyLength range:NSMakeRange(*ptr, 4)];
  92. *ptr += 4;
  93. if (currentRekeyKeyLength != 0)
  94. {
  95. encryptedData->_currentRekeyKey = [data subdataWithRange:NSMakeRange(*ptr, currentRekeyKeyLength)];
  96. *ptr += currentRekeyKeyLength;
  97. }
  98. [data getBytes:&encryptedData->_currentRekeyKeyId range:NSMakeRange(*ptr, 8)];
  99. *ptr += 8;
  100. }
  101. return encryptedData;
  102. }
  103. @end
  104. @implementation TGConversationParticipantsData
  105. - (id)init
  106. {
  107. self = [super init];
  108. if (self != nil)
  109. {
  110. _serializedData = nil;
  111. }
  112. return self;
  113. }
  114. - (id)copyWithZone:(NSZone *)__unused zone
  115. {
  116. TGConversationParticipantsData *participantsData = [[TGConversationParticipantsData alloc] init];
  117. participantsData.chatAdminId = _chatAdminId;
  118. participantsData.chatInvitedBy = _chatInvitedBy;
  119. participantsData.chatInvitedDates = _chatInvitedDates;
  120. participantsData.chatParticipantUids = _chatParticipantUids;
  121. participantsData.chatParticipantSecretChatPeerIds = _chatParticipantSecretChatPeerIds;
  122. participantsData.chatParticipantChatPeerIds = _chatParticipantChatPeerIds;
  123. participantsData.version = _version;
  124. participantsData.exportedChatInviteString = _exportedChatInviteString;
  125. return participantsData;
  126. }
  127. - (void)addParticipantWithId:(int32_t)uid invitedBy:(int32_t)invitedBy date:(int32_t)date
  128. {
  129. NSMutableArray *chatParticipantUids = [[NSMutableArray alloc] initWithArray:_chatParticipantUids];
  130. if (![chatParticipantUids containsObject:@(uid)])
  131. {
  132. [chatParticipantUids addObject:@(uid)];
  133. _chatParticipantUids = chatParticipantUids;
  134. NSMutableDictionary *chatInvitedBy = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedBy];
  135. chatInvitedBy[@(uid)] = @(invitedBy);
  136. _chatInvitedBy = chatInvitedBy;
  137. NSMutableDictionary *chatInvitedDates = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedDates];
  138. chatInvitedDates[@(uid)] = @(date);
  139. _chatInvitedDates = chatInvitedDates;
  140. }
  141. }
  142. - (void)removeParticipantWithId:(int32_t)uid
  143. {
  144. NSMutableArray *chatParticipantUids = [[NSMutableArray alloc] initWithArray:_chatParticipantUids];
  145. [chatParticipantUids removeObject:@(uid)];
  146. _chatParticipantUids = chatParticipantUids;
  147. NSMutableDictionary *chatInvitedBy = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedBy];
  148. [chatInvitedBy removeObjectForKey:@(uid)];
  149. _chatInvitedBy = chatInvitedBy;
  150. NSMutableDictionary *chatInvitedDates = [[NSMutableDictionary alloc] initWithDictionary:_chatInvitedDates];
  151. [chatInvitedDates removeObjectForKey:@(uid)];
  152. _chatInvitedDates = chatInvitedDates;
  153. }
  154. - (void)addSecretChatPeerWithId:(int64_t)peerId
  155. {
  156. NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantSecretChatPeerIds];
  157. if (![chatParticipantSecretChatPeerIds containsObject:@(peerId)])
  158. {
  159. [chatParticipantSecretChatPeerIds addObject:@(peerId)];
  160. _chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
  161. }
  162. }
  163. - (void)removeSecretChatPeerWithId:(int64_t)peerId
  164. {
  165. NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantSecretChatPeerIds];
  166. [chatParticipantSecretChatPeerIds removeObject:@(peerId)];
  167. _chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
  168. }
  169. - (void)addChatPeerWithId:(int64_t)peerId
  170. {
  171. NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantChatPeerIds];
  172. if (![chatParticipantChatPeerIds containsObject:@(peerId)])
  173. {
  174. [chatParticipantChatPeerIds addObject:@(peerId)];
  175. _chatParticipantChatPeerIds = chatParticipantChatPeerIds;
  176. }
  177. }
  178. - (void)removeChatPeerWithId:(int64_t)peerId
  179. {
  180. NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] initWithArray:_chatParticipantChatPeerIds];
  181. [chatParticipantChatPeerIds removeObject:@(peerId)];
  182. _chatParticipantChatPeerIds = chatParticipantChatPeerIds;
  183. }
  184. + (TGConversationParticipantsData *)deserializeData:(NSData *)data
  185. {
  186. TGConversationParticipantsData *participantsData = [[TGConversationParticipantsData alloc] init];
  187. int length = (int)data.length;
  188. int ptr = 0;
  189. if (ptr + 12 > length)
  190. {
  191. return nil;
  192. }
  193. int version = 0;
  194. [data getBytes:&version range:NSMakeRange(ptr, 4)];
  195. ptr += 4;
  196. int32_t formatVersion = 0;
  197. if (version == (int)0xabcdef12)
  198. {
  199. [data getBytes:&formatVersion range:NSMakeRange(ptr, 4)];
  200. ptr += 4;
  201. [data getBytes:&version range:NSMakeRange(ptr, 4)];
  202. ptr += 4;
  203. }
  204. int adminId = 0;
  205. [data getBytes:&adminId range:NSMakeRange(ptr, 4)];
  206. ptr += 4;
  207. int count = 0;
  208. [data getBytes:&count range:NSMakeRange(ptr, 4)];
  209. ptr += 4;
  210. NSMutableArray *uids = [[NSMutableArray alloc] init];
  211. NSMutableDictionary *invitedBy = [[NSMutableDictionary alloc] init];
  212. NSMutableDictionary *invitedDates = [[NSMutableDictionary alloc] init];
  213. for (int i = 0; i < count; i++)
  214. {
  215. if (ptr + 4 > length)
  216. {
  217. TGLog(@"***** Invalid participants data");
  218. return nil;
  219. }
  220. int uid = 0;
  221. [data getBytes:&uid range:NSMakeRange(ptr, 4)];
  222. ptr += 4;
  223. if (ptr + 4 > length)
  224. {
  225. TGLog(@"***** Invalid participants data");
  226. return nil;
  227. }
  228. int inviter = 0;
  229. [data getBytes:&inviter range:NSMakeRange(ptr, 4)];
  230. ptr += 4;
  231. if (ptr + 4 > length)
  232. {
  233. TGLog(@"***** Invalid participants data");
  234. return nil;
  235. }
  236. int date = 0;
  237. [data getBytes:&date range:NSMakeRange(ptr, 4)];
  238. ptr += 4;
  239. NSNumber *nUid = [[NSNumber alloc] initWithInt:uid];
  240. [uids addObject:nUid];
  241. [invitedBy setObject:[[NSNumber alloc] initWithInt:inviter] forKey:nUid];
  242. [invitedDates setObject:[[NSNumber alloc] initWithInt:date] forKey:nUid];
  243. }
  244. NSMutableArray *chatParticipantSecretChatPeerIds = [[NSMutableArray alloc] init];
  245. if (formatVersion >= 1)
  246. {
  247. int count = 0;
  248. [data getBytes:&count range:NSMakeRange(ptr, 4)];
  249. ptr += 4;
  250. for (int i = 0; i < count; i++)
  251. {
  252. if (ptr + 8 > length)
  253. {
  254. TGLog(@"***** Invalid participants data");
  255. return nil;
  256. }
  257. int64_t peerId = 0;
  258. [data getBytes:&peerId range:NSMakeRange(ptr, 8)];
  259. ptr += 8;
  260. [chatParticipantSecretChatPeerIds addObject:@(peerId)];
  261. }
  262. }
  263. NSMutableArray *chatParticipantChatPeerIds = [[NSMutableArray alloc] init];
  264. if (formatVersion >= 2)
  265. {
  266. int count = 0;
  267. [data getBytes:&count range:NSMakeRange(ptr, 4)];
  268. ptr += 4;
  269. for (int i = 0; i < count; i++)
  270. {
  271. if (ptr + 8 > length)
  272. {
  273. TGLog(@"***** Invalid participants data");
  274. return nil;
  275. }
  276. int64_t peerId = 0;
  277. [data getBytes:&peerId range:NSMakeRange(ptr, 8)];
  278. ptr += 8;
  279. [chatParticipantChatPeerIds addObject:@(peerId)];
  280. }
  281. }
  282. if (formatVersion >= 3)
  283. {
  284. int32_t length = 0;
  285. [data getBytes:&length range:NSMakeRange(ptr, 4)];
  286. ptr += 4;
  287. NSData *linkData = [data subdataWithRange:NSMakeRange(ptr, length)];
  288. ptr += length;
  289. participantsData.exportedChatInviteString = [[NSString alloc] initWithData:linkData encoding:NSUTF8StringEncoding];
  290. }
  291. participantsData.version = version;
  292. participantsData.chatAdminId = adminId;
  293. participantsData.chatParticipantUids = uids;
  294. participantsData.chatInvitedBy = invitedBy;
  295. participantsData.chatInvitedDates = invitedDates;
  296. participantsData.chatParticipantSecretChatPeerIds = chatParticipantSecretChatPeerIds;
  297. participantsData.chatParticipantChatPeerIds = chatParticipantChatPeerIds;
  298. return participantsData;
  299. }
  300. - (NSData *)serializedData
  301. {
  302. if (_serializedData == nil)
  303. {
  304. NSMutableData *data = [[NSMutableData alloc] init];
  305. int32_t magic = 0xabcdef12;
  306. [data appendBytes:&magic length:4];
  307. int32_t formatVersion = 3;
  308. [data appendBytes:&formatVersion length:4];
  309. [data appendBytes:&_version length:4];
  310. [data appendBytes:&_chatAdminId length:4];
  311. int count = (int)_chatParticipantUids.count;
  312. [data appendBytes:&count length:4];
  313. for (NSNumber *nUid in _chatParticipantUids)
  314. {
  315. int uid = [nUid intValue];
  316. [data appendBytes:&uid length:4];
  317. int invitedBy = [[_chatInvitedBy objectForKey:nUid] intValue];
  318. [data appendBytes:&invitedBy length:4];
  319. int invitedDate = [[_chatInvitedDates objectForKey:nUid] intValue];
  320. [data appendBytes:&invitedDate length:4];
  321. }
  322. int32_t chatParticipantSecretChatPeerIdsCount = (int32_t)_chatParticipantSecretChatPeerIds.count;
  323. [data appendBytes:&chatParticipantSecretChatPeerIdsCount length:4];
  324. for (NSNumber *nPeerId in _chatParticipantSecretChatPeerIds)
  325. {
  326. int64_t peerId = [nPeerId longLongValue];
  327. [data appendBytes:&peerId length:8];
  328. }
  329. int32_t chatParticipantChatPeerIdsCount = (int32_t)_chatParticipantChatPeerIds.count;
  330. [data appendBytes:&chatParticipantChatPeerIdsCount length:4];
  331. for (NSNumber *nPeerId in _chatParticipantChatPeerIds)
  332. {
  333. int64_t peerId = [nPeerId longLongValue];
  334. [data appendBytes:&peerId length:8];
  335. }
  336. int32_t linkLength = (int32_t)_exportedChatInviteString.length;
  337. [data appendBytes:&linkLength length:4];
  338. if (linkLength != 0)
  339. [data appendData:[_exportedChatInviteString dataUsingEncoding:NSUTF8StringEncoding]];
  340. _serializedData = data;
  341. }
  342. return _serializedData;
  343. }
  344. @end
  345. #pragma mark -
  346. @implementation TGConversation
  347. - (id)initWithConversationId:(int64_t)conversationId unreadCount:(int)unreadCount serviceUnreadCount:(int)serviceUnreadCount
  348. {
  349. self = [super init];
  350. if (self != nil)
  351. {
  352. _conversationId = conversationId;
  353. _unreadCount = unreadCount;
  354. _serviceUnreadCount = serviceUnreadCount;
  355. }
  356. return self;
  357. }
  358. - (instancetype)initWithKeyValueCoder:(PSKeyValueCoder *)coder
  359. {
  360. self = [super init];
  361. if (self != nil) {
  362. _conversationId = [coder decodeInt64ForCKey:"i"];
  363. _accessHash = [coder decodeInt64ForCKey:"ah"];
  364. _displayVariant = [coder decodeInt32ForCKey:"dv"];
  365. _kind = (uint8_t)[coder decodeInt32ForCKey:"kind"];
  366. _pts = [coder decodeInt32ForCKey:"pts"];
  367. _variantSortKey = TGConversationSortKeyDecode(coder, "vsort");
  368. _importantSortKey = TGConversationSortKeyDecode(coder, "isort");
  369. _unimportantSortKey = TGConversationSortKeyDecode(coder, "usort");
  370. _maxReadMessageId = [coder decodeInt32ForCKey:"mread"];
  371. _about = [coder decodeStringForCKey:"about"];
  372. _username = [coder decodeStringForCKey:"username"];
  373. _outgoing = [coder decodeInt32ForCKey:"out"];
  374. _unread = [coder decodeInt32ForCKey:"unr"];
  375. _deliveryError = [coder decodeInt32ForCKey:"der"];
  376. _deliveryState = [coder decodeInt32ForCKey:"ds"];
  377. _date = [coder decodeInt32ForCKey:"date"];
  378. _fromUid = [coder decodeInt32ForCKey:"from"];
  379. _text = [coder decodeStringForCKey:"text"];
  380. _media = [TGMessage parseMediaAttachments:[coder decodeDataCorCKey:"media"]];
  381. _unreadCount = [coder decodeInt32ForCKey:"ucount"];
  382. _serviceUnreadCount = [coder decodeInt32ForCKey:"sucount"];
  383. _chatTitle = [coder decodeStringForCKey:"ct"];
  384. _chatPhotoSmall = [coder decodeStringForCKey:"cp.s"];
  385. _chatPhotoMedium = [coder decodeStringForCKey:"cp.m"];
  386. _chatPhotoBig = [coder decodeStringForCKey:"cp.l"];
  387. _chatParticipants = nil;
  388. _chatParticipantCount = 0;
  389. _chatVersion = [coder decodeInt32ForCKey:"ver"];
  390. _chatIsAdmin = [coder decodeInt32ForCKey:"adm"];
  391. _channelRole = [coder decodeInt32ForCKey:"role"];
  392. _channelIsReadOnly = [coder decodeInt32ForCKey:"ro"];
  393. _flags = [coder decodeInt64ForCKey:"flags"];
  394. _leftChat = false;
  395. _kickedFromChat = [coder decodeInt32ForCKey:"kk"];
  396. _isChat = false;
  397. _isChannel = true;
  398. _isDeleted = false;
  399. _encryptedData = nil;
  400. _isBroadcast = false;
  401. }
  402. return self;
  403. }
  404. - (void)encodeWithKeyValueCoder:(PSKeyValueCoder *)coder {
  405. [coder encodeInt64:_conversationId forCKey:"i"];
  406. [coder encodeInt64:_accessHash forCKey:"ah"];
  407. [coder encodeInt32:_displayVariant forCKey:"dv"];
  408. [coder encodeInt32:_kind forCKey:"kind"];
  409. [coder encodeInt32:_pts forCKey:"pts"];
  410. TGConversationSortKeyEncode(coder, "vsort", _variantSortKey);
  411. TGConversationSortKeyEncode(coder, "isort", _importantSortKey);
  412. TGConversationSortKeyEncode(coder, "usort", _unimportantSortKey);
  413. [coder encodeInt32:_maxReadMessageId forCKey:"mread"];
  414. [coder encodeString:_about forCKey:"about"];
  415. [coder encodeString:_username forCKey:"username"];
  416. [coder encodeInt32:_outgoing ? 1 : 0 forCKey:"out"];
  417. [coder encodeInt32:_unread ? 1 : 0 forCKey:"unr"];
  418. [coder encodeInt32:_deliveryError ? 1 : 0 forCKey:"der"];
  419. [coder encodeInt32:_deliveryState forCKey:"ds"];
  420. [coder encodeInt32:_date forCKey:"date"];
  421. [coder encodeInt32:_fromUid forCKey:"from"];
  422. [coder encodeString:_text forCKey:"text"];
  423. [coder encodeData:[TGMessage serializeMediaAttachments:true attachments:_media] forCKey:"media"];
  424. [coder encodeInt32:_unreadCount forCKey:"ucount"];
  425. [coder encodeInt32:_serviceUnreadCount forCKey:"sucount"];
  426. [coder encodeString:_chatTitle forCKey:"ct"];
  427. [coder encodeString:_chatPhotoSmall forCKey:"cp.s"];
  428. [coder encodeString:_chatPhotoMedium forCKey:"cp.m"];
  429. [coder encodeString:_chatPhotoBig forCKey:"cp.l"];
  430. [coder encodeInt32:_chatVersion forCKey:"ver"];
  431. [coder encodeInt32:_chatIsAdmin ? 1 : 0 forCKey:"adm"];
  432. [coder encodeInt32:_channelRole forCKey:"role"];
  433. [coder encodeInt32:_channelIsReadOnly ? 1 : 0 forCKey:"ro"];
  434. [coder encodeInt64:_flags forCKey:"flags"];
  435. [coder encodeInt32:_kickedFromChat forCKey:"kk"];
  436. }
  437. - (id)copyWithZone:(NSZone *)__unused zone
  438. {
  439. TGConversation *conversation = [[TGConversation alloc] init];
  440. conversation.conversationId = _conversationId;
  441. conversation.accessHash = _accessHash;
  442. conversation.displayVariant = _displayVariant;
  443. conversation->_kind = _kind;
  444. conversation.pts = _pts;
  445. conversation.variantSortKey = _variantSortKey;
  446. conversation.importantSortKey = _importantSortKey;
  447. conversation.unimportantSortKey = _unimportantSortKey;
  448. conversation.maxReadMessageId = _maxReadMessageId;
  449. conversation.about = _about;
  450. conversation.username = _username;
  451. conversation.outgoing = _outgoing;
  452. conversation.unread = _unread;
  453. conversation.deliveryError = _deliveryError;
  454. conversation.deliveryState = _deliveryState;
  455. conversation.date = _date;
  456. conversation.fromUid = _fromUid;
  457. conversation.text = _text;
  458. conversation.media = _media;
  459. conversation.unreadCount = _unreadCount;
  460. conversation.serviceUnreadCount = _serviceUnreadCount;
  461. conversation.chatTitle = _chatTitle;
  462. conversation.chatPhotoSmall = _chatPhotoSmall;
  463. conversation.chatPhotoMedium = _chatPhotoMedium;
  464. conversation.chatPhotoBig = _chatPhotoBig;
  465. conversation.chatParticipants = [_chatParticipants copy];
  466. conversation.chatParticipantCount = _chatParticipantCount;
  467. conversation.chatVersion = _chatVersion;
  468. conversation.chatIsAdmin = _chatIsAdmin;
  469. conversation.channelRole = _channelRole;
  470. conversation.leftChat = _leftChat;
  471. conversation.kickedFromChat = _kickedFromChat;
  472. conversation.dialogListData = _dialogListData;
  473. conversation.isChat = _isChat;
  474. conversation.isDeleted = _isDeleted;
  475. conversation.encryptedData = _encryptedData == nil ? nil : [_encryptedData copy];
  476. conversation.isBroadcast = _isBroadcast;
  477. conversation.isChannel = _isChannel;
  478. conversation.channelIsReadOnly = _channelIsReadOnly;
  479. conversation.flags = _flags;
  480. return conversation;
  481. }
  482. - (void)setKind:(uint8_t)kind {
  483. if (_kind != kind || kind != TGConversationSortKeyKind(_variantSortKey)) {
  484. _kind = kind;
  485. _variantSortKey = TGConversationSortKeyUpdateKind(_variantSortKey, kind);
  486. _importantSortKey = TGConversationSortKeyUpdateKind(_importantSortKey, kind);
  487. _unimportantSortKey = TGConversationSortKeyUpdateKind(_unimportantSortKey, kind);
  488. }
  489. }
  490. - (void)setVariantSortKey:(TGConversationSortKey)variantSortKey {
  491. _variantSortKey = variantSortKey;
  492. _date = TGConversationSortKeyTimestamp(variantSortKey);
  493. }
  494. - (void)mergeMessage:(TGMessage *)message
  495. {
  496. _outgoing = message.outgoing;
  497. _date = (int)message.date;
  498. _fromUid = (int)message.fromUid;
  499. _text = message.text;
  500. _media = message.mediaAttachments;
  501. _unread = message.unread;
  502. _deliveryError = message.deliveryState == TGMessageDeliveryStateFailed;
  503. _deliveryState = message.deliveryState;
  504. }
  505. - (NSData *)mediaData
  506. {
  507. if (_mediaData != nil)
  508. return _mediaData;
  509. _mediaData = [TGMessage serializeMediaAttachments:false attachments:_media];
  510. return _mediaData;
  511. }
  512. - (BOOL)isEqualToConversation:(TGConversation *)other
  513. {
  514. 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)
  515. return false;
  516. if (_media.count != other.media.count)
  517. return false;
  518. if (_media != nil && ![self.mediaData isEqualToData:other.mediaData])
  519. return false;
  520. if (_isChat)
  521. {
  522. if (![_chatTitle isEqualToString:other.chatTitle] || _chatVersion != other.chatVersion || _leftChat != other.leftChat || _kickedFromChat != other.kickedFromChat ||
  523. (((_chatParticipants != nil) != (other.chatParticipants != nil)) || (_chatParticipants != nil && ![_chatParticipants.serializedData isEqualToData:other.chatParticipants.serializedData]))
  524. )
  525. return false;
  526. if ((_chatPhotoSmall != nil) != (other.chatPhotoSmall != nil) || (_chatPhotoSmall != nil && ![_chatPhotoSmall isEqualToString:other.chatPhotoSmall]))
  527. return false;
  528. if ((_chatPhotoMedium != nil) != (other.chatPhotoMedium != nil) || (_chatPhotoMedium != nil && ![_chatPhotoMedium isEqualToString:other.chatPhotoMedium]))
  529. return false;
  530. if ((_chatPhotoBig != nil) != (other.chatPhotoBig != nil) || (_chatPhotoBig != nil && ![_chatPhotoBig isEqualToString:other.chatPhotoBig]))
  531. return false;
  532. }
  533. if (_encryptedData != nil || other->_encryptedData != nil)
  534. {
  535. if ((_encryptedData != nil) != (other->_encryptedData != nil) || (_encryptedData != nil && ![_encryptedData isEqualToEncryptedData:other->_encryptedData]))
  536. return false;
  537. }
  538. return true;
  539. }
  540. - (BOOL)isEqualToConversationIgnoringMessage:(TGConversation *)other
  541. {
  542. if (_conversationId != other.conversationId || _isChat != other.isChat)
  543. return false;
  544. if (_isChat)
  545. {
  546. if (![_chatTitle isEqualToString:other.chatTitle] || _chatVersion != other.chatVersion || _leftChat != other.leftChat || _kickedFromChat != other.kickedFromChat ||
  547. (((_chatParticipants != nil) != (other.chatParticipants != nil)) || (_chatParticipants != nil && ![_chatParticipants.serializedData isEqualToData:other.chatParticipants.serializedData]))
  548. )
  549. return false;
  550. if ((_chatPhotoSmall != nil) != (other.chatPhotoSmall != nil) || (_chatPhotoSmall != nil && ![_chatPhotoSmall isEqualToString:other.chatPhotoSmall]))
  551. return false;
  552. if ((_chatPhotoMedium != nil) != (other.chatPhotoMedium != nil) || (_chatPhotoMedium != nil && ![_chatPhotoMedium isEqualToString:other.chatPhotoMedium]))
  553. return false;
  554. if ((_chatPhotoBig != nil) != (other.chatPhotoBig != nil) || (_chatPhotoBig != nil && ![_chatPhotoBig isEqualToString:other.chatPhotoBig]))
  555. return false;
  556. }
  557. return true;
  558. }
  559. - (NSData *)serializeChatPhoto
  560. {
  561. NSMutableData *data = [[NSMutableData alloc] init];
  562. for (int i = 0; i < 3; i++)
  563. {
  564. NSString *value = nil;
  565. if (i == 0)
  566. value = _chatPhotoSmall;
  567. else if (i == 1)
  568. value = _chatPhotoMedium;
  569. else if (i == 2)
  570. value = _chatPhotoBig;
  571. NSData *valueData = [value dataUsingEncoding:NSUTF8StringEncoding];
  572. int length = (int)valueData.length;
  573. [data appendBytes:&length length:4];
  574. if (valueData != nil)
  575. [data appendData:valueData];
  576. }
  577. if (_encryptedData != nil)
  578. [_encryptedData serialize:data];
  579. return data;
  580. }
  581. - (void)deserializeChatPhoto:(NSData *)data
  582. {
  583. int ptr = 0;
  584. for (int i = 0; i < 3; i++)
  585. {
  586. int length = 0;
  587. [data getBytes:&length range:NSMakeRange(ptr, 4)];
  588. ptr += 4;
  589. uint8_t *valueBytes = malloc(length);
  590. [data getBytes:valueBytes range:NSMakeRange(ptr, length)];
  591. ptr += length;
  592. NSString *value = [[NSString alloc] initWithBytesNoCopy:valueBytes length:length encoding:NSUTF8StringEncoding freeWhenDone:true];
  593. if (i == 0)
  594. _chatPhotoSmall = value;
  595. else if (i == 1)
  596. _chatPhotoMedium = value;
  597. else if (i == 2)
  598. _chatPhotoBig = value;
  599. }
  600. if (ptr + 4 <= (int)data.length)
  601. {
  602. _encryptedData = [TGEncryptedConversationData deserialize:data ptr:&ptr];
  603. }
  604. }
  605. - (bool)isEncrypted
  606. {
  607. return _encryptedData != nil;
  608. }
  609. - (void)mergeChannel:(TGConversation *)channel {
  610. _chatTitle = channel.chatTitle;
  611. _chatVersion = channel.chatVersion;
  612. _chatPhotoBig = channel.chatPhotoBig;
  613. _chatPhotoMedium = channel.chatPhotoMedium;
  614. _chatPhotoSmall = channel.chatPhotoSmall;
  615. _accessHash = channel.accessHash;
  616. _username = channel.username;
  617. _chatIsAdmin = channel.chatIsAdmin;
  618. self.channelRole = channel.channelRole;
  619. _channelIsReadOnly = channel.channelIsReadOnly;
  620. _leftChat = channel.leftChat;
  621. _kickedFromChat = channel.kickedFromChat;
  622. self.kind = channel.leftChat ? TGConversationKindTemporaryChannel : TGConversationKindPersistentChannel;
  623. self.isVerified = channel.isVerified;
  624. }
  625. - (bool)currentUserCanSendMessages {
  626. return (_channelRole == TGChannelRoleCreator || _channelRole == TGChannelRolePublisher || !_channelIsReadOnly) && !_leftChat && !_kickedFromChat;
  627. }
  628. + (NSString *)chatTitleForDecoder:(PSKeyValueCoder *)coder {
  629. return [coder decodeStringForCKey:"ct"];
  630. }
  631. - (bool)postAsChannel {
  632. return _flags & TGConversationFlagPostAsChannel;
  633. }
  634. - (void)setPostAsChannel:(bool)postAsChannel {
  635. if (postAsChannel) {
  636. _flags |= TGConversationFlagPostAsChannel;
  637. } else {
  638. _flags &= ~TGConversationFlagPostAsChannel;
  639. }
  640. }
  641. - (bool)displayExpanded {
  642. return _flags & TGConversationFlagDisplayExpanded;
  643. }
  644. - (void)setDisplayExpanded:(bool)displayExpanded {
  645. if (displayExpanded) {
  646. _flags |= TGConversationFlagDisplayExpanded;
  647. } else {
  648. _flags &= ~TGConversationFlagDisplayExpanded;
  649. }
  650. }
  651. - (bool)isVerified {
  652. return _flags & TGConversationFlagVerified;
  653. }
  654. - (void)setIsVerified:(bool)isVerified {
  655. if (isVerified) {
  656. _flags |= TGConversationFlagVerified;
  657. } else {
  658. _flags &= ~TGConversationFlagVerified;
  659. }
  660. }
  661. @end