NekoX/TMessagesProj/src/main/java/org/telegram/messenger/MessagesController.java

4632 lines
229 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* This is the source code of Telegram for Android v. 1.2.3.
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
* Copyright Nikolai Kudashov, 2013.
*/
package org.telegram.messenger;
import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.media.AudioManager;
import android.media.SoundPool;
import android.net.Uri;
import android.os.Build;
import android.os.Vibrator;
import android.provider.BaseColumns;
import android.provider.ContactsContract;
import android.text.Html;
import android.util.Log;
import android.util.SparseArray;
import com.actionbarsherlock.app.SherlockFragmentActivity;
import org.telegram.TL.TLClassStore;
import org.telegram.TL.TLObject;
import org.telegram.TL.TLRPC;
import org.telegram.objects.MessageObject;
import org.telegram.ui.ApplicationLoader;
import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
public class MessagesController implements NotificationCenter.NotificationCenterDelegate {
public ConcurrentHashMap<Integer, TLRPC.Chat> chats = new ConcurrentHashMap<Integer, TLRPC.Chat>(100, 1.0f, 1);
public ConcurrentHashMap<Integer, TLRPC.EncryptedChat> encryptedChats = new ConcurrentHashMap<Integer, TLRPC.EncryptedChat>(10, 1.0f, 1);
public ConcurrentHashMap<Integer, TLRPC.User> users = new ConcurrentHashMap<Integer, TLRPC.User>(100, 1.0f, 1);
public ArrayList<TLRPC.TL_dialog> dialogs = new ArrayList<TLRPC.TL_dialog>();
public ArrayList<TLRPC.TL_dialog> dialogsServerOnly = new ArrayList<TLRPC.TL_dialog>();
public ConcurrentHashMap<Long, TLRPC.TL_dialog> dialogs_dict = new ConcurrentHashMap<Long, TLRPC.TL_dialog>(100, 1.0f, 1);
public SparseArray<MessageObject> dialogMessage = new SparseArray<MessageObject>();
public ConcurrentHashMap<Long, ArrayList<PrintingUser>> printingUsers = new ConcurrentHashMap<Long, ArrayList<PrintingUser>>(100, 1.0f, 2);
public HashMap<Long, CharSequence> printingStrings = new HashMap<Long, CharSequence>();
private HashMap<String, DelayedMessage> delayedMessages = new HashMap<String, DelayedMessage>();
public SparseArray<MessageObject> sendingMessages = new SparseArray<MessageObject>();
public SparseArray<TLRPC.User> hidenAddToContacts = new SparseArray<TLRPC.User>();
private SparseArray<TLRPC.EncryptedChat> acceptingChats = new SparseArray<TLRPC.EncryptedChat>();
private boolean gettingNewDeleteTask = false;
private int currentDeletingTaskTime = 0;
private Long currentDeletingTask = null;
private ArrayList<Integer> currentDeletingTaskMids = null;
public int totalDialogsCount = 0;
public boolean loadingDialogs = false;
public boolean dialogsEndReached = false;
public boolean gettingDifference = false;
public boolean updatingState = false;
public boolean firstGettingTask = false;
public boolean registeringForPush = false;
private long lastSoundPlay = 0;
private long lastStatusUpdateTime = 0;
public boolean loadingContacts = true;
private boolean offlineSended = false;
private String uploadingAvatar = null;
private SoundPool soundPool;
private int sound;
public static SecureRandom random = new SecureRandom();
private Account currentAccount;
static {
try {
File URANDOM_FILE = new File("/dev/urandom");
FileInputStream sUrandomIn = new FileInputStream(URANDOM_FILE);
byte[] buffer = new byte[1024];
sUrandomIn.read(buffer);
sUrandomIn.close();
random.setSeed(buffer);
} catch (Exception e) {
e.printStackTrace();
}
}
public static final int MESSAGE_SEND_STATE_SENDING = 1;
public static final int MESSAGE_SEND_STATE_SENT = 0;
public static final int MESSAGE_SEND_STATE_SEND_ERROR = 2;
public static final int UPDATE_MASK_NAME = 1;
public static final int UPDATE_MASK_AVATAR = 2;
public static final int UPDATE_MASK_STATUS = 4;
public static final int UPDATE_MASK_ALL = UPDATE_MASK_AVATAR | UPDATE_MASK_STATUS | UPDATE_MASK_NAME;
public long openned_dialog_id;
public static class PrintingUser {
public long lastTime;
public int userId;
}
private class DelayedMessage {
public TLRPC.TL_messages_sendMedia sendRequest;
public TLRPC.TL_decryptedMessage sendEncryptedRequest;
public int type;
public TLRPC.FileLocation location;
public TLRPC.TL_video videoLocation;
public MessageObject obj;
public TLRPC.EncryptedChat encryptedChat;
}
public static class Contact {
public int id;
public ArrayList<String> phones = new ArrayList<String>();
public ArrayList<String> phoneTypes = new ArrayList<String>();
public String first_name;
public String last_name;
}
public HashMap<Integer, Contact> contactsBook = new HashMap<Integer, Contact>();
public HashMap<String, ArrayList<Contact>> contactsSectionsDict = new HashMap<String, ArrayList<Contact>>();
public ArrayList<String> sortedContactsSectionsArray = new ArrayList<String>();
public ArrayList<TLRPC.TL_contact> contacts = new ArrayList<TLRPC.TL_contact>();
public SparseArray<TLRPC.TL_contact> contactsDict = new SparseArray<TLRPC.TL_contact>();
public HashMap<String, TLRPC.TL_contact> contactsByPhones = new HashMap<String, TLRPC.TL_contact>();
public HashMap<String, ArrayList<TLRPC.TL_contact>> usersSectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
public ArrayList<String> sortedUsersSectionsArray = new ArrayList<String>();
public static MessagesController Instance = new MessagesController();
public static final int didReceivedNewMessages = 1;
public static final int userPrintUpdate = 2;
public static final int userPrintUpdateAll = 19;
public static final int updateInterfaces = 3;
public static final int dialogsNeedReload = 4;
public static final int closeChats = 5;
public static final int messagesDeleted = 6;
public static final int messagesReaded = 7;
public static final int messagesDidLoaded = 8;
public static final int messageReceivedByAck = 9;
public static final int messageReceivedByServer = 10;
public static final int messageSendError = 11;
public static final int reloadSearchResults = 12;
public static final int contactsDidLoaded = 13;
public static final int contactsBookDidLoaded = 14;
public static final int chatDidCreated = 15;
public static final int chatDidFailCreate = 16;
public static final int chatInfoDidLoaded = 17;
public static final int mediaDidLoaded = 18;
public static final int mediaCountDidLoaded = 20;
public static final int encryptedChatUpdated = 21;
public static final int messagesReadedEncrypted = 22;
public static final int encryptedChatCreated = 23;
public MessagesController() {
MessagesStorage storage = MessagesStorage.Instance;
NotificationCenter.Instance.addObserver(this, FileLoader.FileDidUpload);
NotificationCenter.Instance.addObserver(this, FileLoader.FileDidFailUpload);
NotificationCenter.Instance.addObserver(this, 10);
addSupportUser();
try {
soundPool = new SoundPool(1, AudioManager.STREAM_NOTIFICATION, 0);
sound = soundPool.load(Utilities.applicationContext, R.raw.sound_a, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
public void addSupportUser() {
TLRPC.TL_userForeign user = new TLRPC.TL_userForeign();
user.phone = "333";
user.id = 333000;
user.first_name = "Telegram";
user.last_name = "";
user.status = null;
user.photo = new TLRPC.TL_userProfilePhotoEmpty();
users.put(user.id, user);
}
@Override
public void didReceivedNotification(int id, Object... args) {
if (id == FileLoader.FileDidUpload) {
fileDidUploaded((String)args[0], (TLRPC.TL_inputFile)args[1], (TLRPC.TL_inputEncryptedFileUploaded)args[2]);
} else if (id == FileLoader.FileDidFailUpload) {
fileDidFailedUpload((String) args[0]);
} else if (id == messageReceivedByServer) {
Integer msgId = (Integer)args[0];
MessageObject obj = dialogMessage.get(msgId);
if (obj != null) {
Integer newMsgId = (Integer)args[1];
dialogMessage.remove(msgId);
dialogMessage.put(newMsgId, obj);
obj.messageOwner.id = newMsgId;
obj.messageOwner.send_state = MessagesController.MESSAGE_SEND_STATE_SENT;
long uid;
if (obj.messageOwner.to_id.chat_id != 0) {
uid = -obj.messageOwner.to_id.chat_id;
} else {
if (obj.messageOwner.to_id.user_id == UserConfig.clientUserId) {
obj.messageOwner.to_id.user_id = obj.messageOwner.from_id;
}
uid = obj.messageOwner.to_id.user_id;
}
TLRPC.TL_dialog dialog = dialogs_dict.get(uid);
if (dialog != null) {
if (dialog.top_message == msgId) {
dialog.top_message = newMsgId;
}
}
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
}
}
@Override
protected void finalize() throws Throwable {
super.finalize();
NotificationCenter.Instance.removeObserver(this, FileLoader.FileDidUpload);
NotificationCenter.Instance.removeObserver(this, FileLoader.FileDidFailUpload);
NotificationCenter.Instance.removeObserver(this, messageReceivedByServer);
}
public void cleanUp() {
dialogs_dict.clear();
dialogs.clear();
dialogsServerOnly.clear();
acceptingChats.clear();
users.clear();
chats.clear();
sendingMessages.clear();
delayedMessages.clear();
dialogMessage.clear();
printingUsers.clear();
printingStrings.clear();
totalDialogsCount = 0;
contactsBook.clear();
contactsSectionsDict.clear();
sortedContactsSectionsArray.clear();
contacts.clear();
contactsDict.clear();
usersSectionsDict.clear();
sortedUsersSectionsArray.clear();
contactsByPhones.clear();
hidenAddToContacts.clear();
currentDeletingTaskTime = 0;
currentDeletingTaskMids = null;
gettingNewDeleteTask = false;
currentDeletingTask = null;
loadingContacts = false;
loadingDialogs = false;
dialogsEndReached = false;
gettingDifference = false;
firstGettingTask = false;
updatingState = false;
lastStatusUpdateTime = 0;
offlineSended = false;
registeringForPush = false;
uploadingAvatar = null;
addSupportUser();
}
public void didAddedNewTask(final int minDate) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (currentDeletingTask == null && !gettingNewDeleteTask || currentDeletingTaskTime != 0 && minDate < currentDeletingTaskTime) {
getNewDeleteTask(null);
}
}
});
}
public void getNewDeleteTask(final Long oldTask) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
gettingNewDeleteTask = true;
MessagesStorage.Instance.getNewTask(oldTask);
}
});
}
private void checkDeletingTask() {
int currentServerTime = ConnectionsManager.Instance.getCurrentTime();
if (currentDeletingTask != null && currentDeletingTaskTime != 0 && currentDeletingTaskTime <= currentServerTime) {
currentDeletingTaskTime = 0;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
deleteMessages(currentDeletingTaskMids);
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
getNewDeleteTask(currentDeletingTask);
currentDeletingTaskTime = 0;
currentDeletingTask = null;
}
});
}
});
}
}
public void processLoadedDeleteTask(final Long taskId, final int taskTime, final ArrayList<Integer> messages) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
gettingNewDeleteTask = false;
if (taskId != null) {
currentDeletingTaskTime = taskTime;
currentDeletingTask = taskId;
currentDeletingTaskMids = messages;
checkDeletingTask();
} else {
currentDeletingTaskTime = 0;
currentDeletingTask = null;
currentDeletingTaskMids = null;
}
}
});
}
public void checkAppAccount() {
AccountManager am = AccountManager.get(Utilities.applicationContext);
Account[] accounts = am.getAccountsByType("org.telegram.messenger.account");
boolean recreateAccount = false;
if (UserConfig.currentUser != null) {
if (accounts.length == 1) {
Account acc = accounts[0];
if (!acc.name.equals(UserConfig.currentUser.phone)) {
recreateAccount = true;
} else {
currentAccount = acc;
}
} else {
recreateAccount = true;
}
} else {
if (accounts.length > 0) {
recreateAccount = true;
}
}
if (recreateAccount) {
for (Account c : accounts) {
am.removeAccount(c, null, null);
}
if (UserConfig.currentUser != null) {
currentAccount = new Account(UserConfig.currentUser.phone, "org.telegram.messenger.account");
am.addAccountExplicitly(currentAccount, "", null);
}
}
}
public void processLoadedMedia(final TLRPC.messages_Messages res, final long uid, int offset, int count, int max_id, final boolean fromCache, final int classGuid) {
int lower_part = (int)uid;
if (fromCache && res.messages.isEmpty() && lower_part != 0) {
loadMedia(uid, offset, count, max_id, false, classGuid);
} else {
if (!fromCache) {
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
MessagesStorage.Instance.putMedia(uid, res.messages);
}
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User u : res.users) {
usersLocal.put(u.id, u);
}
final ArrayList<MessageObject> objects = new ArrayList<MessageObject>();
for (TLRPC.Message message : res.messages) {
objects.add(new MessageObject(message, usersLocal));
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
int totalCount;
if (res instanceof TLRPC.TL_messages_messagesSlice) {
totalCount = res.count;
} else {
totalCount = res.messages.size();
}
for (TLRPC.User user : res.users) {
if (fromCache) {
users.putIfAbsent(user.id, user);
} else {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
}
for (TLRPC.Chat chat : res.chats) {
if (fromCache) {
chats.putIfAbsent(chat.id, chat);
} else {
chats.put(chat.id, chat);
}
}
NotificationCenter.Instance.postNotificationName(mediaDidLoaded, uid, totalCount, objects, fromCache, classGuid);
}
});
}
}
public void loadMedia(final long uid, final int offset, final int count, final int max_id, final boolean fromCache, final int classGuid) {
int lower_part = (int)uid;
if (fromCache || lower_part == 0) {
MessagesStorage.Instance.loadMedia(uid, offset, count, max_id, classGuid);
} else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.offset = offset;
req.limit = count;
req.max_id = max_id;
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
req.q = "";
if (uid < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = MessagesController.Instance.users.get(uid);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
}
req.peer.user_id = lower_part;
}
long reqId = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages)response;
processLoadedMedia(res, uid, offset, count, max_id, false, classGuid);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
ConnectionsManager.Instance.bindRequestToGuid(reqId, classGuid);
}
}
public void processLoadedMediaCount(final int count, final long uid, final int classGuid, final boolean fromCache) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
int lower_part = (int)uid;
if (fromCache && count == -1 && lower_part != 0) {
getMediaCount(uid, classGuid, false);
} else {
if (!fromCache) {
MessagesStorage.Instance.putMediaCount(uid, count);
}
if (fromCache && count == -1) {
NotificationCenter.Instance.postNotificationName(mediaCountDidLoaded, uid, 0);
} else {
NotificationCenter.Instance.postNotificationName(mediaCountDidLoaded, uid, count);
}
}
}
});
}
public void getMediaCount(final long uid, final int classGuid, boolean fromCache) {
int lower_part = (int)uid;
if (fromCache || lower_part == 0) {
MessagesStorage.Instance.getMediaCount(uid, classGuid);
} else {
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
req.offset = 0;
req.limit = 1;
req.max_id = 0;
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
req.q = "";
if (uid < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = MessagesController.Instance.users.get(uid);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
}
req.peer.user_id = lower_part;
}
long reqId = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages)response;
if (res instanceof TLRPC.TL_messages_messagesSlice) {
processLoadedMediaCount(res.count, uid, classGuid, false);
} else {
processLoadedMediaCount(res.messages.size(), uid, classGuid, false);
}
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
ConnectionsManager.Instance.bindRequestToGuid(reqId, classGuid);
}
}
public void uploadAndApplyUserAvatar(TLRPC.PhotoSize bigPhoto) {
if (bigPhoto != null) {
uploadingAvatar = Utilities.getCacheDir() + "/" + bigPhoto.location.volume_id + "_" + bigPhoto.location.local_id + ".jpg";
FileLoader.Instance.uploadFile(uploadingAvatar, null, null);
}
}
public void readContacts() {
if (contactsBook.size() != 0) {
return;
}
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
final HashMap<Integer, Contact> contactsMap = new HashMap<Integer, Contact>();
final HashMap<String, ArrayList<Contact>> sectionsDict = new HashMap<String, ArrayList<Contact>>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
ContentResolver cr = Utilities.applicationContext.getContentResolver();
String[] projectioPhones = {
ContactsContract.CommonDataKinds.Phone.CONTACT_ID,
ContactsContract.CommonDataKinds.Phone.NUMBER,
ContactsContract.CommonDataKinds.Phone.TYPE,
ContactsContract.CommonDataKinds.Phone.LABEL
};
String ids = "";
Cursor pCur = cr.query(ContactsContract.CommonDataKinds.Phone.CONTENT_URI, projectioPhones, null, null, null);
if (pCur != null) {
if (pCur.getCount() > 0) {
while (pCur.moveToNext()) {
String number = pCur.getString(1);
if (number == null || number.length() == 0) {
continue;
}
Integer id = pCur.getInt(0);
if (ids.length() != 0) {
ids += ",";
}
ids += id;
int type = pCur.getInt(2);
Contact contact = contactsMap.get(id);
if (contact == null) {
contact = new Contact();
contact.first_name = "";
contact.last_name = "";
contactsMap.put(id, contact);
contact.id = id;
}
number = number.replace(" ", "").replace("(", "").replace(")", "").replace("-", "").replace("+", "");
if (number.startsWith("8")) {
number = "7" + number.substring(1);
}
contact.phones.add(number);
if (type == ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM) {
contact.phoneTypes.add(pCur.getString(3));
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_HOME) {
contact.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneHome));
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE) {
contact.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneMobile));
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_WORK) {
contact.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneWork));
} else if (type == ContactsContract.CommonDataKinds.Phone.TYPE_MAIN) {
contact.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneMain));
} else {
contact.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneOther));
}
}
}
pCur.close();
}
String[] projectionNames = {
ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID,
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME,
ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME,
ContactsContract.Data.DISPLAY_NAME,
ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME
};
pCur = cr.query(ContactsContract.Data.CONTENT_URI, projectionNames, ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " IN (" + ids + ") AND " + ContactsContract.Data.MIMETYPE + " = '" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'", null, null);
if (pCur != null && pCur.getCount() > 0) {
while (pCur.moveToNext()) {
int id = pCur.getInt(0);
String fname = pCur.getString(1);
String sname = pCur.getString(2);
String sname2 = pCur.getString(3);
String mname = pCur.getString(4);
Contact contact = contactsMap.get(id);
if (contact != null) {
contact.first_name = fname;
contact.last_name = sname;
if (contact.first_name == null) {
contact.first_name = "";
}
if (mname != null && mname.length() != 0) {
if (contact.first_name.length() != 0) {
contact.first_name += " " + mname;
} else {
contact.first_name = mname;
}
}
if (contact.last_name == null) {
contact.last_name = "";
}
if (contact.last_name.length() == 0 && contact.first_name.length() == 0 && sname2 != null && sname2.length() != 0) {
contact.first_name = sname2;
}
}
}
pCur.close();
}
ArrayList<TLRPC.TL_inputPhoneContact> toImport = new ArrayList<TLRPC.TL_inputPhoneContact>();
String contactsImportHash = "";
MessageDigest mdEnc = null;
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
}
for (HashMap.Entry<Integer, Contact> pair : contactsMap.entrySet()) {
Contact value = pair.getValue();
int id = pair.getKey();
for (int a = 0; a < value.phones.size(); a++) {
TLRPC.TL_inputPhoneContact imp = new TLRPC.TL_inputPhoneContact();
imp.client_id = id;
imp.first_name = value.first_name;
imp.last_name = value.last_name;
imp.phone = value.phones.get(a);
toImport.add(imp);
String str = imp.client_id + imp.first_name + imp.last_name + imp.phone;
if (mdEnc != null) {
mdEnc.update(str.getBytes());
}
}
String key = value.last_name;
if (key.length() == 0) {
key = value.first_name;
}
if (key.length() == 0) {
key = "#";
if (value.phones.size() != 0) {
value.first_name = "+" + value.phones.get(0);
}
} else {
key = key.toUpperCase();
}
if (key.length() > 1) {
key = key.substring(0, 1);
}
ArrayList<Contact> arr = sectionsDict.get(key);
if (arr == null) {
arr = new ArrayList<Contact>();
sectionsDict.put(key, arr);
sortedSectionsArray.add(key);
}
arr.add(value);
}
for (HashMap.Entry<String, ArrayList<Contact>> entry : sectionsDict.entrySet()) {
Collections.sort(entry.getValue(), new Comparator<Contact>() {
@Override
public int compare(Contact contact, Contact contact2) {
String toComapre1 = contact.last_name;
if (toComapre1.length() == 0) {
toComapre1 = contact.first_name;
}
String toComapre2 = contact2.last_name;
if (toComapre2.length() == 0) {
toComapre2 = contact2.first_name;
}
return toComapre1.compareTo(toComapre2);
}
});
}
Collections.sort(sortedSectionsArray, new Comparator<String>() {
@Override
public int compare(String s, String s2) {
char cv1 = s.charAt(0);
char cv2 = s2.charAt(0);
if (cv1 == '#') {
return 1;
} else if (cv2 == '#') {
return -1;
} else if (cv1 >= 'A' && cv1 <= 'Z' && cv2 >= 'A' && cv2 <= 'Z') {
return s.compareTo(s2);
} else if (cv1 >= 'A' && cv1 <= 'Z' && !(cv2 >= 'A' && cv2 <= 'Z')) {
return 1;
} else if (!(cv1 >= 'A' && cv1 <= 'Z') && cv2 >= 'A' && cv2 <= 'Z') {
return -1;
}
return s.compareTo(s2);
}
});
String importHash = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
if (!toImport.isEmpty() && !UserConfig.importHash.equals(importHash)) {
UserConfig.importHash = importHash;
UserConfig.saveConfig();
importContacts(toImport);
} else {
loadContacts(true);
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
contactsBook = contactsMap;
contactsSectionsDict = sectionsDict;
sortedContactsSectionsArray = sortedSectionsArray;
NotificationCenter.Instance.postNotificationName(contactsBookDidLoaded);
}
});
}
});
}
private void performSyncContacts() {
Utilities.globalQueue.postRunnable(new Runnable() {
@Override
public void run() {
try {
Uri rawContactUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, currentAccount.name).appendQueryParameter(
ContactsContract.RawContacts.ACCOUNT_TYPE, currentAccount.type).build();
Cursor c1 = Utilities.applicationContext.getContentResolver().query(rawContactUri, new String[]{BaseColumns._ID, ContactsContract.RawContacts.SYNC2}, null, null, null);
HashMap<Integer, Long> bookContacts = new HashMap<Integer, Long>();
if (c1 != null) {
while (c1.moveToNext()) {
bookContacts.put(c1.getInt(1), c1.getLong(0));
}
c1.close();
for (TLRPC.TL_contact u : contacts) {
if (!bookContacts.containsKey(u.user_id)) {
TLRPC.User user = users.get(u.user_id);
addContact(currentAccount, user, user.phone);
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
public static long addContact(Account account, TLRPC.User user, String phone) {
if (account == null || user == null || phone == null) {
return -1;
}
ArrayList<ContentProviderOperation> query = new ArrayList<ContentProviderOperation>();
ContentProviderOperation.Builder builder = ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, account.name);
builder.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, account.type);
builder.withValue(ContactsContract.RawContacts.SYNC1, phone);
builder.withValue(ContactsContract.RawContacts.SYNC2, user.id);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, user.first_name);
builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, user.last_name);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.CommonDataKinds.StructuredName.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
builder.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, "+" + phone);
builder.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE);
query.add(builder.build());
builder = ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI);
builder.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0);
builder.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.org.telegram.messenger.android.profile");
builder.withValue(ContactsContract.Data.DATA1, "+" + phone);
builder.withValue(ContactsContract.Data.DATA2, "Telegram Profile");
builder.withValue(ContactsContract.Data.DATA3, "+" + phone);
builder.withValue(ContactsContract.Data.DATA4, user.id);
query.add(builder.build());
try {
ContentProviderResult[] result = Utilities.applicationContext.getContentResolver().applyBatch(ContactsContract.AUTHORITY, query);
return Long.parseLong(result[0].uri.getLastPathSegment());
} catch (Exception e) {
e.printStackTrace();
}
return -1;
}
public void deleteMessages(ArrayList<Integer> messages) {
NotificationCenter.Instance.postNotificationName(messagesDeleted, messages);
for (Integer id : messages) {
MessageObject obj = dialogMessage.get(id);
if (obj != null) {
obj.deleted = true;
}
}
MessagesStorage.Instance.markMessagesAsDeleted(messages, true);
MessagesStorage.Instance.updateDialogsWithDeletedMessages(messages, true);
ArrayList<Integer> toSend = new ArrayList<Integer>();
for (Integer mid : messages) {
if (mid > 0) {
toSend.add(mid);
}
}
if (toSend.isEmpty()) {
return;
}
TLRPC.TL_messages_deleteMessages req = new TLRPC.TL_messages_deleteMessages();
req.id = messages;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void deleteDialog(final long did, int offset, final boolean onlyHistory) {
TLRPC.TL_dialog dialog = dialogs_dict.get(did);
if (dialog != null) {
int lower_part = (int)did;
if (offset == 0) {
if (!onlyHistory) {
dialogs.remove(dialog);
dialogsServerOnly.remove(dialog);
dialogs_dict.remove(did);
totalDialogsCount--;
}
dialogMessage.remove(dialog.top_message);
MessagesStorage.Instance.deleteDialog(did, onlyHistory);
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
if (lower_part != 0) {
TLRPC.TL_messages_deleteHistory req = new TLRPC.TL_messages_deleteHistory();
req.offset = offset;
if (did < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = MessagesController.Instance.users.get(did);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
}
req.peer.user_id = lower_part;
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.TL_messages_affectedHistory res = (TLRPC.TL_messages_affectedHistory)response;
if (res.offset > 0) {
deleteDialog(did, res.offset, onlyHistory);
}
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
} else {
int encId = (int)(did >> 32);
declineSecretChat(encId);
}
}
}
public void loadChatInfo(final int chat_id) {
MessagesStorage.Instance.loadChatInfo(chat_id);
}
public void processChatInfo(final int chat_id, final TLRPC.ChatParticipants info, final ArrayList<TLRPC.User> usersArr, final boolean fromCache) {
if (info == null && fromCache) {
TLRPC.TL_messages_getFullChat req = new TLRPC.TL_messages_getFullChat();
req.chat_id = chat_id;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
return;
}
final TLRPC.TL_messages_chatFull res = (TLRPC.TL_messages_chatFull)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
MessagesStorage.Instance.updateChatInfo(chat_id, res.full_chat.participants, false);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
NotificationCenter.Instance.postNotificationName(chatInfoDidLoaded, chat_id, res.full_chat.participants);
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : usersArr) {
if (fromCache) {
users.putIfAbsent(user.id, user);
} else {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
}
NotificationCenter.Instance.postNotificationName(chatInfoDidLoaded, chat_id, info);
}
});
}
}
public void updateTimerProc() {
long currentTime = System.currentTimeMillis();
checkDeletingTask();
if (UserConfig.clientUserId != 0) {
if (ApplicationLoader.lastPauseTime == 0) {
if (lastStatusUpdateTime != -1 && (lastStatusUpdateTime == 0 || lastStatusUpdateTime <= System.currentTimeMillis() - 55000 || offlineSended)) {
lastStatusUpdateTime = -1;
TLRPC.TL_account_updateStatus req = new TLRPC.TL_account_updateStatus();
req.offline = false;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
lastStatusUpdateTime = System.currentTimeMillis();
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
offlineSended = false;
}
} else if (!offlineSended && ApplicationLoader.lastPauseTime <= System.currentTimeMillis() - 2000) {
TLRPC.TL_account_updateStatus req = new TLRPC.TL_account_updateStatus();
req.offline = true;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
offlineSended = true;
}
}
final ArrayList<Long> uidsToSend = new ArrayList<Long>();
if (!printingUsers.isEmpty()) {
ArrayList<Long> keys = new ArrayList<Long>(printingUsers.keySet());
for (int b = 0; b < keys.size(); b++) {
Long key = keys.get(b);
ArrayList<PrintingUser> arr = printingUsers.get(key);
for (int a = 0; a < arr.size(); a++) {
PrintingUser user = arr.get(a);
if (user.lastTime + 5900 < currentTime) {
if (!uidsToSend.contains(key)) {
uidsToSend.add(key);
}
arr.remove(user);
a--;
}
}
if (arr.isEmpty()) {
printingUsers.remove(key);
keys.remove(b);
b--;
}
}
updatePrintingStrings();
if (!uidsToSend.isEmpty()) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (Long uid : uidsToSend) {
NotificationCenter.Instance.postNotificationName(userPrintUpdate, uid);
}
NotificationCenter.Instance.postNotificationName(userPrintUpdateAll);
}
});
}
}
}
public void updatePrintingStrings() {
final HashMap<Long, CharSequence> newPrintingStrings = new HashMap<Long, CharSequence>();
ArrayList<Long> keys = new ArrayList<Long>(printingUsers.keySet());
for (Long key : keys) {
if (key > 0) {
newPrintingStrings.put(key, Html.fromHtml(String.format("<font color='#006fc8'>%s</font>", Utilities.applicationContext.getString(R.string.Typing))));
} else {
ArrayList<PrintingUser> arr = printingUsers.get(key);
int count = 0;
String label = "";
for (PrintingUser pu : arr) {
TLRPC.User user = MessagesController.Instance.users.get(pu.userId);
if (user != null) {
if (label.length() != 0) {
label += ", ";
}
label += Utilities.formatName(user.first_name, user.last_name);
count++;
}
if (count == 2) {
break;
}
}
if (label.length() != 0) {
if (count > 1) {
if (arr.size() > 2) {
newPrintingStrings.put(key, Html.fromHtml(String.format("<font color='#006fc8'>%s %s %s</font>", label, String.format(Utilities.applicationContext.getString(R.string.AndMoreTyping), arr.size() - 2), Utilities.applicationContext.getString(R.string.AreTyping))));
} else {
newPrintingStrings.put(key, Html.fromHtml(String.format("<font color='#006fc8'>%s %s</font>", label, Utilities.applicationContext.getString(R.string.AreTyping))));
}
} else {
newPrintingStrings.put(key, Html.fromHtml(String.format("<font color='#006fc8'>%s %s</font>", label, Utilities.applicationContext.getString(R.string.IsTyping))));
}
}
}
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
printingStrings = newPrintingStrings;
}
});
}
public void processLoadedContacts(final ArrayList<TLRPC.TL_contact> contactsArr, final ArrayList<TLRPC.User> usersArr, final int from) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (from == 1 && contactsArr.isEmpty()) {
loadContacts(false);
return;
}
if (from == 0 || from == 2 || from == 3) {
MessagesStorage.Instance.putUsersAndChats(usersArr, null, true, true);
MessagesStorage.Instance.putContacts(contactsArr, true);
Collections.sort(contacts, new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact tl_contact, TLRPC.TL_contact tl_contact2) {
if (tl_contact.user_id > tl_contact2.user_id) {
return 1;
} else if (tl_contact.user_id < tl_contact2.user_id) {
return -1;
}
return 0;
}
});
String ids = "";
for (TLRPC.TL_contact aContactsArr : contactsArr) {
if (ids.length() != 0) {
ids += ",";
}
ids += aContactsArr.user_id;
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.saveConfig();
if (from == 2) {
loadContacts(false);
}
}
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User user : usersArr) {
usersDict.put(user.id, user);
}
Collections.sort(contactsArr, new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact tl_contact, TLRPC.TL_contact tl_contact2) {
TLRPC.User user1 = usersDict.get(tl_contact.user_id);
TLRPC.User user2 = usersDict.get(tl_contact2.user_id);
String name1 = user1.last_name;
if (name1 == null || name1.length() == 0) {
name1 = user1.first_name;
}
String name2 = user2.last_name;
if (name2 == null || name2.length() == 0) {
name2 = user2.first_name;
}
return name1.compareTo(name2);
}
});
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
final SparseArray<TLRPC.TL_contact> contactsDictionery = new SparseArray<TLRPC.TL_contact>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
final HashMap<String, TLRPC.TL_contact> contactsPhones = new HashMap<String, TLRPC.TL_contact>();
for (TLRPC.TL_contact value : contactsArr) {
TLRPC.User user = usersDict.get(value.user_id);
contactsDictionery.put(value.user_id, value);
contactsPhones.put(user.phone, value);
String key = user.last_name;
if (key == null || key.length() == 0) {
key = user.first_name;
}
if (key.length() == 0) {
key = "#";
} else {
key = key.toUpperCase();
}
if (key.length() > 1) {
key = key.substring(0, 1);
}
ArrayList<TLRPC.TL_contact> arr = sectionsDict.get(key);
if (arr == null) {
arr = new ArrayList<TLRPC.TL_contact>();
sectionsDict.put(key, arr);
sortedSectionsArray.add(key);
}
arr.add(value);
}
for (HashMap.Entry<String, ArrayList<TLRPC.TL_contact>> entry : sectionsDict.entrySet()) {
Collections.sort(entry.getValue(), new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact contact, TLRPC.TL_contact contact2) {
TLRPC.User user1 = usersDict.get(contact.user_id);
TLRPC.User user2 = usersDict.get(contact2.user_id);
String toComapre1 = user1.last_name;
if (toComapre1 == null || toComapre1.length() == 0) {
toComapre1 = user1.first_name;
}
String toComapre2 = user2.last_name;
if (toComapre2 == null || toComapre2.length() == 0) {
toComapre2 = user2.first_name;
}
return toComapre1.compareTo(toComapre2);
}
});
}
Collections.sort(sortedSectionsArray, new Comparator<String>() {
@Override
public int compare(String s, String s2) {
char cv1 = s.charAt(0);
char cv2 = s2.charAt(0);
if (cv1 == '#') {
return 1;
} else if (cv2 == '#') {
return -1;
} else if (cv1 >= 'A' && cv1 <= 'Z' && cv2 >= 'A' && cv2 <= 'Z') {
return s.compareTo(s2);
} else if (cv1 >= 'A' && cv1 <= 'Z' && !(cv2 >= 'A' && cv2 <= 'Z')) {
return 1;
} else if (!(cv1 >= 'A' && cv1 <= 'Z') && cv2 >= 'A' && cv2 <= 'Z') {
return -1;
}
return s.compareTo(s2);
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : usersArr) {
if (from == 1) {
users.putIfAbsent(user.id, user);
} else {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
}
contacts = contactsArr;
contactsByPhones = contactsPhones;
contactsDict = contactsDictionery;
usersSectionsDict = sectionsDict;
sortedUsersSectionsArray = sortedSectionsArray;
if (from == 0) {
loadingContacts = false;
}
performSyncContacts();
NotificationCenter.Instance.postNotificationName(contactsDidLoaded);
}
});
}
});
}
public void sendTyping(long dialog_id, int classGuid) {
if (dialog_id == 0) {
return;
}
int lower_part = (int)dialog_id;
if (lower_part != 0) {
TLRPC.TL_messages_setTyping req = new TLRPC.TL_messages_setTyping();
if (lower_part < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = users.get(lower_part);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.user_id = user.id;
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
req.peer.user_id = user.id;
}
}
req.typing = true;
long reqId = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
ConnectionsManager.Instance.bindRequestToGuid(reqId, classGuid);
} else {
int encId = (int)(dialog_id >> 32);
TLRPC.EncryptedChat chat = encryptedChats.get(encId);
if (chat.auth_key != null && chat.auth_key.length > 1 && chat instanceof TLRPC.TL_encryptedChat) {
TLRPC.TL_messages_setEncryptedTyping req = new TLRPC.TL_messages_setEncryptedTyping();
req.peer = new TLRPC.TL_inputEncryptedChat();
req.peer.chat_id = chat.id;
req.peer.access_hash = chat.access_hash;
req.typing = true;
long reqId = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
ConnectionsManager.Instance.bindRequestToGuid(reqId, classGuid);
}
}
}
public void loadContacts(boolean fromCache) {
loadingContacts = true;
if (fromCache) {
MessagesStorage.Instance.getContacts();
} else {
TLRPC.TL_contacts_getContacts req = new TLRPC.TL_contacts_getContacts();
req.hash = UserConfig.contactsHash;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.contacts_Contacts res = (TLRPC.contacts_Contacts)response;
if (res instanceof TLRPC.TL_contacts_contactsNotModified) {
return;
}
processLoadedContacts(res.contacts, res.users, 0);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
}
public void importContacts(ArrayList<TLRPC.TL_inputPhoneContact> contactsArr) {
TLRPC.TL_contacts_importContacts req = new TLRPC.TL_contacts_importContacts();
req.contacts = contactsArr;
req.replace = false;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
Log.e("tmessages", "contacts imported");
TLRPC.TL_contacts_importedContacts res = (TLRPC.TL_contacts_importedContacts)response;
MessagesStorage.Instance.putUsersAndChats(res.users, null, true, true);
ArrayList<TLRPC.TL_contact> cArr = new ArrayList<TLRPC.TL_contact>();
for (TLRPC.TL_importedContact c : res.imported) {
TLRPC.TL_contact contact = new TLRPC.TL_contact();
contact.user_id = c.user_id;
cArr.add(contact);
}
processLoadedContacts(cArr, res.users, 2);
} else {
Log.e("tmessages", "import contacts error " + error.text);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
public void loadMessages(final long dialog_id, final int offset, final int count, final int max_id, boolean fromCache, int midDate, final int classGuid) {
int lower_part = (int)dialog_id;
if (fromCache || lower_part == 0) {
MessagesStorage.Instance.getMessages(dialog_id, offset, count, max_id, midDate, classGuid);
} else {
TLRPC.TL_messages_getHistory req = new TLRPC.TL_messages_getHistory();
if (lower_part < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = users.get(lower_part);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.user_id = user.id;
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
req.peer.user_id = user.id;
}
}
req.offset = offset;
req.limit = count;
req.max_id = max_id;
long reqId = ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Messages res = (TLRPC.messages_Messages)response;
processLoadedMessages(res, dialog_id, offset, count, max_id, false, classGuid);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
ConnectionsManager.Instance.bindRequestToGuid(reqId, classGuid);
}
}
public void processLoadedMessages(final TLRPC.messages_Messages messagesRes, final long dialog_id, final int offset, final int count, final int max_id, final boolean isCache, final int classGuid) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
int lower_id = (int)dialog_id;
if (!isCache) {
MessagesStorage.Instance.putMessages(messagesRes, dialog_id);
}
if (lower_id != 0 && isCache && messagesRes.messages.size() == 0) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
loadMessages(dialog_id, offset, count, max_id, false, 0, classGuid);
}
});
return;
}
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User u : messagesRes.users) {
usersLocal.put(u.id, u);
}
final ArrayList<MessageObject> objects = new ArrayList<MessageObject>();
for (TLRPC.Message message : messagesRes.messages) {
message.dialog_id = dialog_id;
objects.add(new MessageObject(message, usersLocal));
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User u : messagesRes.users) {
if (isCache) {
users.putIfAbsent(u.id, u);
} else {
users.put(u.id, u);
if (u.id == UserConfig.clientUserId) {
UserConfig.currentUser = u;
}
}
}
for (TLRPC.Chat c : messagesRes.chats) {
if (isCache) {
chats.putIfAbsent(c.id, c);
} else {
chats.put(c.id, c);
}
}
NotificationCenter.Instance.postNotificationName(messagesDidLoaded, dialog_id, offset, count, objects, isCache);
}
});
}
});
}
public void loadDialogs(final int offset, final int serverOffset, final int count, boolean fromCache) {
if (loadingDialogs) {
return;
}
loadingDialogs = true;
if (fromCache) {
MessagesStorage.Instance.getDialogs(offset, serverOffset, count);
} else {
TLRPC.TL_messages_getDialogs req = new TLRPC.TL_messages_getDialogs();
req.offset = serverOffset;
req.limit = count;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final TLRPC.messages_Dialogs dialogsRes = (TLRPC.messages_Dialogs)response;
processLoadedDialogs(dialogsRes, null, offset, serverOffset, count, false, false);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
}
public void processDialogsUpdate(final TLRPC.messages_Dialogs dialogsRes, ArrayList<TLRPC.EncryptedChat> encChats) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
final HashMap<Long, TLRPC.TL_dialog> new_dialogs_dict = new HashMap<Long, TLRPC.TL_dialog>();
final HashMap<Integer, MessageObject> new_dialogMessage = new HashMap<Integer, MessageObject>();
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User u : dialogsRes.users) {
usersLocal.put(u.id, u);
}
for (TLRPC.Message m : dialogsRes.messages) {
new_dialogMessage.put(m.id, new MessageObject(m, usersLocal));
}
for (TLRPC.TL_dialog d : dialogsRes.dialogs) {
if (d.last_message_date == 0) {
MessageObject mess = new_dialogMessage.get(d.top_message);
if (mess != null) {
d.last_message_date = mess.messageOwner.date;
}
}
if (d.id == 0) {
if (d.peer instanceof TLRPC.TL_peerUser) {
d.id = d.peer.user_id;
} else if (d.peer instanceof TLRPC.TL_peerChat) {
d.id = -d.peer.chat_id;
}
}
new_dialogs_dict.put(d.id, d);
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User u : dialogsRes.users) {
users.putIfAbsent(u.id, u);
}
for (TLRPC.Chat c : dialogsRes.chats) {
chats.putIfAbsent(c.id, c);
}
for (HashMap.Entry<Long, TLRPC.TL_dialog> pair : new_dialogs_dict.entrySet()) {
long key = pair.getKey();
TLRPC.TL_dialog value = pair.getValue();
TLRPC.TL_dialog currentDialog = dialogs_dict.get(key);
if (currentDialog == null) {
dialogs_dict.put(key, value);
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
} else {
currentDialog.unread_count = value.unread_count;
MessageObject oldMsg = dialogMessage.get(currentDialog.top_message);
if (oldMsg == null || currentDialog.top_message > 0) {
if (oldMsg != null && oldMsg.deleted || value.top_message > currentDialog.top_message) {
dialogs_dict.put(key, value);
if (oldMsg != null) {
dialogMessage.remove(oldMsg.messageOwner.id);
}
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
}
} else {
MessageObject newMsg = new_dialogMessage.get(value.top_message);
if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) {
dialogs_dict.put(key, value);
dialogMessage.remove(oldMsg.messageOwner.id);
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
}
}
}
}
dialogs.clear();
dialogsServerOnly.clear();
dialogs.addAll(dialogs_dict.values());
Collections.sort(dialogs, new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) {
if (tl_dialog.last_message_date == tl_dialog2.last_message_date) {
return 0;
} else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) {
return 1;
} else {
return -1;
}
}
});
for (TLRPC.TL_dialog d : dialogs) {
if ((int)d.id != 0) {
dialogsServerOnly.add(d);
}
}
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
}
});
}
public void processLoadedDialogs(final TLRPC.messages_Dialogs dialogsRes, final ArrayList<TLRPC.EncryptedChat> encChats, final int offset, final int serverOffset, final int count, final boolean isCache, final boolean resetEnd) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (isCache && dialogsRes.dialogs.size() == 0) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User u : dialogsRes.users) {
if (isCache) {
users.putIfAbsent(u.id, u);
} else {
users.put(u.id, u);
if (u.id == UserConfig.clientUserId) {
UserConfig.currentUser = u;
}
}
}
loadingDialogs = false;
if (resetEnd) {
dialogsEndReached = false;
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
loadDialogs(offset, serverOffset, count, false);
}
});
return;
}
final HashMap<Long, TLRPC.TL_dialog> new_dialogs_dict = new HashMap<Long, TLRPC.TL_dialog>();
final HashMap<Integer, MessageObject> new_dialogMessage = new HashMap<Integer, MessageObject>();
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<Integer, TLRPC.User>();
int new_totalDialogsCount;
if (!isCache) {
MessagesStorage.Instance.putDialogs(dialogsRes);
}
if (dialogsRes instanceof TLRPC.TL_messages_dialogsSlice) {
TLRPC.TL_messages_dialogsSlice slice = (TLRPC.TL_messages_dialogsSlice)dialogsRes;
new_totalDialogsCount = slice.count;
} else {
new_totalDialogsCount = dialogsRes.dialogs.size();
}
for (TLRPC.User u : dialogsRes.users) {
usersLocal.put(u.id, u);
}
for (TLRPC.Message m : dialogsRes.messages) {
new_dialogMessage.put(m.id, new MessageObject(m, usersLocal));
}
for (TLRPC.TL_dialog d : dialogsRes.dialogs) {
if (d.last_message_date == 0) {
MessageObject mess = new_dialogMessage.get(d.top_message);
if (mess != null) {
d.last_message_date = mess.messageOwner.date;
}
}
if (d.id == 0) {
if (d.peer instanceof TLRPC.TL_peerUser) {
d.id = d.peer.user_id;
} else if (d.peer instanceof TLRPC.TL_peerChat) {
d.id = -d.peer.chat_id;
}
}
new_dialogs_dict.put(d.id, d);
}
final int arg1 = new_totalDialogsCount;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User u : dialogsRes.users) {
if (isCache) {
users.putIfAbsent(u.id, u);
} else {
users.put(u.id, u);
if (u.id == UserConfig.clientUserId) {
UserConfig.currentUser = u;
}
}
}
for (TLRPC.Chat c : dialogsRes.chats) {
if (isCache) {
chats.putIfAbsent(c.id, c);
} else {
chats.put(c.id, c);
}
}
if (encChats != null) {
for (TLRPC.EncryptedChat encryptedChat : encChats) {
encryptedChats.put(encryptedChat.id, encryptedChat);
}
}
loadingDialogs = false;
totalDialogsCount = arg1;
for (HashMap.Entry<Long, TLRPC.TL_dialog> pair : new_dialogs_dict.entrySet()) {
long key = pair.getKey();
TLRPC.TL_dialog value = pair.getValue();
TLRPC.TL_dialog currentDialog = dialogs_dict.get(key);
if (currentDialog == null) {
dialogs_dict.put(key, value);
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
} else {
MessageObject oldMsg = dialogMessage.get(value.top_message);
if (oldMsg == null || currentDialog.top_message > 0) {
if (oldMsg != null && oldMsg.deleted || value.top_message > currentDialog.top_message) {
if (oldMsg != null) {
dialogMessage.remove(oldMsg.messageOwner.id);
}
dialogs_dict.put(key, value);
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
}
} else {
MessageObject newMsg = new_dialogMessage.get(value.top_message);
if (oldMsg.deleted || newMsg == null || newMsg.messageOwner.date > oldMsg.messageOwner.date) {
dialogMessage.remove(oldMsg.messageOwner.id);
dialogs_dict.put(key, value);
dialogMessage.put(value.top_message, new_dialogMessage.get(value.top_message));
}
}
}
}
dialogs.clear();
dialogsServerOnly.clear();
dialogs.addAll(dialogs_dict.values());
Collections.sort(dialogs, new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) {
if (tl_dialog.last_message_date == tl_dialog2.last_message_date) {
return 0;
} else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) {
return 1;
} else {
return -1;
}
}
});
for (TLRPC.TL_dialog d : dialogs) {
if ((int)d.id != 0) {
dialogsServerOnly.add(d);
}
}
dialogsEndReached = (dialogsRes.dialogs.size() == 0 || dialogsRes.dialogs.size() != count) && !isCache;
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
}
});
}
public TLRPC.TL_photo generatePhotoSizes(String path) {
long time = System.currentTimeMillis();
Bitmap bitmap = FileLoader.loadBitmap(path, 800, 800);
ArrayList<TLRPC.PhotoSize> sizes = new ArrayList<TLRPC.PhotoSize>();
TLRPC.PhotoSize size = FileLoader.scaleAndSaveImage(bitmap, 90, 90, 55, true);
if (size != null) {
size.type = "s";
sizes.add(size);
}
size = FileLoader.scaleAndSaveImage(bitmap, 320, 320, 87, false);
if (size != null) {
size.type = "m";
sizes.add(size);
}
size = FileLoader.scaleAndSaveImage(bitmap, 800, 800, 87, false);
if (size != null) {
size.type = "x";
sizes.add(size);
}
if (bitmap != null) {
bitmap.recycle();
}
if (sizes.isEmpty()) {
return null;
} else {
UserConfig.saveConfig();
TLRPC.TL_photo photo = new TLRPC.TL_photo();
photo.user_id = UserConfig.clientUserId;
photo.date = ConnectionsManager.Instance.getCurrentTime();
photo.sizes = sizes;
photo.caption = "";
photo.geo = new TLRPC.TL_geoPointEmpty();
return photo;
}
}
public void markDialogAsRead(final long dialog_id, final int max_id, final int offset, final int max_date, final boolean was) {
int lower_part = (int)dialog_id;
if (lower_part != 0) {
if (max_id == 0 && offset == 0) {
return;
}
TLRPC.TL_messages_readHistory req = new TLRPC.TL_messages_readHistory();
if (lower_part < 0) {
req.peer = new TLRPC.TL_inputPeerChat();
req.peer.chat_id = -lower_part;
} else {
TLRPC.User user = users.get(lower_part);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.peer = new TLRPC.TL_inputPeerForeign();
req.peer.user_id = user.id;
req.peer.access_hash = user.access_hash;
} else {
req.peer = new TLRPC.TL_inputPeerContact();
req.peer.user_id = user.id;
}
}
req.max_id = max_id;
req.offset = offset;
if (offset == 0) {
MessagesStorage.Instance.processPendingRead(dialog_id, max_id, max_date, false);
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
MessagesStorage.Instance.processPendingRead(dialog_id, max_id, max_date, true);
TLRPC.TL_messages_affectedHistory res = (TLRPC.TL_messages_affectedHistory)response;
if (res.offset > 0) {
markDialogAsRead(dialog_id, 0, res.offset, max_date, was);
}
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
if (offset == 0) {
TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id);
if (dialog != null) {
dialog.unread_count = 0;
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
TLRPC.TL_messages_receivedMessages req2 = new TLRPC.TL_messages_receivedMessages();
req2.max_id = max_id;
ConnectionsManager.Instance.performRpc(req2, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
} else {
if (max_date == 0) {
return;
}
int encId = (int)(dialog_id >> 32);
TLRPC.EncryptedChat chat = encryptedChats.get(encId);
if (chat.auth_key != null && chat.auth_key.length > 1 && chat instanceof TLRPC.TL_encryptedChat) {
TLRPC.TL_messages_readEncryptedHistory req = new TLRPC.TL_messages_readEncryptedHistory();
req.peer = new TLRPC.TL_inputEncryptedChat();
req.peer.chat_id = chat.id;
req.peer.access_hash = chat.access_hash;
req.max_date = max_date;
MessagesStorage.Instance.processPendingRead(dialog_id, max_id, max_date, false);
if (chat.ttl > 0 && was) {
int serverTime = Math.max(ConnectionsManager.Instance.getCurrentTime(), max_date);
MessagesStorage.Instance.createTaskForDate(chat.id, serverTime, serverTime, 0);
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
MessagesStorage.Instance.processPendingRead(dialog_id, max_id, max_date, true);
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id);
if (dialog != null) {
dialog.unread_count = 0;
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
}
}
}
public void cancelSendingMessage(MessageObject object) {
String keyToRemvoe = null;
for (HashMap.Entry<String, DelayedMessage> entry : delayedMessages.entrySet()) {
if (entry.getValue().obj.messageOwner.id == object.messageOwner.id) {
keyToRemvoe = entry.getKey();
break;
}
}
if (keyToRemvoe != null) {
ArrayList<Integer> messages = new ArrayList<Integer>();
messages.add(object.messageOwner.id);
FileLoader.Instance.cancelUploadFile(keyToRemvoe);
deleteMessages(messages);
}
}
private long getNextRandomId() {
long val = 0;
while (val == 0) {
val = random.nextLong();
}
return val;
}
public void sendMessage(TLRPC.User user, long peer) {
sendMessage(null, 0, 0, null, null, null, null, user, peer);
}
public void sendMessage(MessageObject message, long peer) {
sendMessage(null, 0, 0, null, null, message, null, null, peer);
}
public void sendMessage(String message, long peer) {
sendMessage(message, 0, 0, null, null, null, null, null, peer);
}
public void sendMessage(TLRPC.FileLocation location, long peer) {
sendMessage(null, 0, 0, null, null, null, location, null, peer);
}
public void sendMessage(double lat, double lon, long peer) {
sendMessage(null, lat, lon, null, null, null, null, null, peer);
}
public void sendMessage(TLRPC.TL_photo photo, long peer) {
sendMessage(null, 0, 0, photo, null, null, null, null, peer);
}
public void sendMessage(TLRPC.TL_video video, long peer) {
sendMessage(null, 0, 0, null, video, null, null, null, peer);
}
public void sendTTLMessage(TLRPC.EncryptedChat encryptedChat) {
TLRPC.TL_messageService newMsg = new TLRPC.TL_messageService();
newMsg.action = new TLRPC.TL_messageActionTTLChange();
newMsg.action.ttl = encryptedChat.ttl;
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.clientUserId;
newMsg.unread = true;
newMsg.dialog_id = ((long)encryptedChat.id) << 32;
newMsg.to_id = new TLRPC.TL_peerUser();
if (encryptedChat.participant_id == UserConfig.clientUserId) {
newMsg.to_id.user_id = encryptedChat.admin_id;
} else {
newMsg.to_id.user_id = encryptedChat.participant_id;
}
newMsg.out = true;
newMsg.date = ConnectionsManager.Instance.getCurrentTime();
newMsg.random_id = getNextRandomId();
UserConfig.saveConfig();
final MessageObject newMsgObj = new MessageObject(newMsg, users);
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SENDING;
final ArrayList<MessageObject> objArr = new ArrayList<MessageObject>();
objArr.add(newMsgObj);
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(newMsg);
MessagesStorage.Instance.putMessages(arr, false, true);
updateInterfaceWithMessages(newMsg.dialog_id, objArr);
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
sendingMessages.put(newMsg.id, newMsgObj);
TLRPC.TL_decryptedMessageService reqSend = new TLRPC.TL_decryptedMessageService();
reqSend.random_id = newMsg.random_id;
reqSend.random_bytes = new byte[Math.max(1, (int)Math.ceil(random.nextDouble() * 16))];
random.nextBytes(reqSend.random_bytes);
reqSend.action = new TLRPC.TL_decryptedMessageActionSetMessageTTL();
reqSend.action.ttl_seconds = encryptedChat.ttl;
performSendEncryptedRequest(reqSend, newMsgObj, encryptedChat, null);
}
private void sendMessage(String message, double lat, double lon, TLRPC.TL_photo photo, TLRPC.TL_video video, MessageObject msgObj, TLRPC.FileLocation location, TLRPC.User user, long peer) {
TLRPC.Message newMsg = null;
int type = -1;
if (message != null) {
newMsg = new TLRPC.TL_message();
newMsg.media = new TLRPC.TL_messageMediaEmpty();
type = 0;
newMsg.message = message;
} else if (lat != 0 && lon != 0) {
newMsg = new TLRPC.TL_message();
newMsg.media = new TLRPC.TL_messageMediaGeo();
newMsg.media.geo = new TLRPC.TL_geoPoint();
newMsg.media.geo.lat = lat;
newMsg.media.geo._long = lon;
newMsg.message = "";
type = 1;
} else if (photo != null) {
newMsg = new TLRPC.TL_message();
newMsg.media = new TLRPC.TL_messageMediaPhoto();
newMsg.media.photo = photo;
type = 2;
newMsg.message = "-1";
TLRPC.FileLocation location1 = photo.sizes.get(photo.sizes.size() - 1).location;
newMsg.attachPath = Utilities.getCacheDir() + "/" + location1.volume_id + "_" + location1.local_id + ".jpg";
} else if (video != null) {
newMsg = new TLRPC.TL_message();
newMsg.media = new TLRPC.TL_messageMediaVideo();
newMsg.media.video = video;
type = 3;
newMsg.message = "-1";
newMsg.attachPath = video.path;
} else if (msgObj != null) {
newMsg = new TLRPC.TL_messageForwarded();
if (msgObj.messageOwner instanceof TLRPC.TL_messageForwarded) {
newMsg.fwd_from_id = msgObj.messageOwner.fwd_from_id;
newMsg.fwd_date = msgObj.messageOwner.fwd_date;
newMsg.media = msgObj.messageOwner.media;
newMsg.message = msgObj.messageOwner.message;
newMsg.fwd_msg_id = msgObj.messageOwner.id;
type = 4;
} else if (msgObj.type == 11) {
newMsg.fwd_from_id = msgObj.messageOwner.from_id;
newMsg.fwd_date = msgObj.messageOwner.date;
newMsg.media = new TLRPC.TL_messageMediaPhoto();
newMsg.media.photo = msgObj.messageOwner.action.photo;
newMsg.message = "";
newMsg.fwd_msg_id = msgObj.messageOwner.id;
type = 5;
} else {
newMsg.fwd_from_id = msgObj.messageOwner.from_id;
newMsg.fwd_date = msgObj.messageOwner.date;
newMsg.media = msgObj.messageOwner.media;
newMsg.message = msgObj.messageOwner.message;
newMsg.fwd_msg_id = msgObj.messageOwner.id;
type = 4;
}
} else if (location != null) {
} else if (user != null) {
newMsg = new TLRPC.TL_message();
newMsg.media = new TLRPC.TL_messageMediaContact();
newMsg.media.phone_number = user.phone;
newMsg.media.first_name = user.first_name;
newMsg.media.last_name = user.last_name;
newMsg.media.user_id = user.id;
newMsg.message = "";
type = 6;
}
if (newMsg == null) {
return;
}
newMsg.local_id = newMsg.id = UserConfig.getNewMessageId();
newMsg.from_id = UserConfig.clientUserId;
newMsg.unread = true;
newMsg.dialog_id = peer;
int lower_id = (int)peer;
TLRPC.EncryptedChat encryptedChat = null;
TLRPC.InputPeer sendToPeer = null;
if (lower_id != 0) {
if (lower_id < 0) {
newMsg.to_id = new TLRPC.TL_peerChat();
newMsg.to_id.chat_id = -lower_id;
sendToPeer = new TLRPC.TL_inputPeerChat();
sendToPeer.chat_id = -lower_id;
} else {
newMsg.to_id = new TLRPC.TL_peerUser();
newMsg.to_id.user_id = lower_id;
TLRPC.User sendToUser = users.get(lower_id);
if (sendToUser instanceof TLRPC.TL_userForeign || sendToUser instanceof TLRPC.TL_userRequest) {
sendToPeer = new TLRPC.TL_inputPeerForeign();
sendToPeer.user_id = sendToUser.id;
sendToPeer.access_hash = sendToUser.access_hash;
} else {
sendToPeer = new TLRPC.TL_inputPeerContact();
sendToPeer.user_id = sendToUser.id;
}
}
} else {
encryptedChat = encryptedChats.get((int)(peer >> 32));
newMsg.to_id = new TLRPC.TL_peerUser();
if (encryptedChat.participant_id == UserConfig.clientUserId) {
newMsg.to_id.user_id = encryptedChat.admin_id;
} else {
newMsg.to_id.user_id = encryptedChat.participant_id;
}
newMsg.ttl = encryptedChat.ttl;
}
newMsg.out = true;
newMsg.date = ConnectionsManager.Instance.getCurrentTime();
newMsg.random_id = getNextRandomId();
UserConfig.saveConfig();
final MessageObject newMsgObj = new MessageObject(newMsg, null);
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SENDING;
final ArrayList<MessageObject> objArr = new ArrayList<MessageObject>();
objArr.add(newMsgObj);
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(newMsg);
MessagesStorage.Instance.putMessages(arr, false, true);
updateInterfaceWithMessages(peer, objArr);
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
sendingMessages.put(newMsg.id, newMsgObj);
if (type == 0) {
if (encryptedChat == null) {
TLRPC.TL_messages_sendMessage reqSend = new TLRPC.TL_messages_sendMessage();
reqSend.message = message;
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
performSendMessageRequest(reqSend, newMsgObj);
} else {
TLRPC.TL_decryptedMessage reqSend = new TLRPC.TL_decryptedMessage();
reqSend.random_id = newMsg.random_id;
reqSend.random_bytes = new byte[Math.max(1, (int)Math.ceil(random.nextDouble() * 16))];
random.nextBytes(reqSend.random_bytes);
reqSend.message = message;
reqSend.media = new TLRPC.TL_decryptedMessageMediaEmpty();
performSendEncryptedRequest(reqSend, newMsgObj, encryptedChat, null);
}
} else if (type == 1 || type == 2 || type == 3 || type == 5 || type == 6) {
if (encryptedChat == null) {
TLRPC.TL_messages_sendMedia reqSend = new TLRPC.TL_messages_sendMedia();
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
if (type == 1) {
reqSend.media = new TLRPC.TL_inputMediaGeoPoint();
reqSend.media.geo_point = new TLRPC.TL_inputGeoPoint();
reqSend.media.geo_point.lat = lat;
reqSend.media.geo_point._long = lon;
performSendMessageRequest(reqSend, newMsgObj);
} else if (type == 2) {
reqSend.media = new TLRPC.TL_inputMediaUploadedPhoto();
DelayedMessage delayedMessage = new DelayedMessage();
delayedMessage.sendRequest = reqSend;
delayedMessage.type = 0;
delayedMessage.obj = newMsgObj;
delayedMessage.location = photo.sizes.get(photo.sizes.size() - 1).location;
performSendDelayedMessage(delayedMessage);
} else if (type == 3) {
reqSend.media = new TLRPC.TL_inputMediaUploadedThumbVideo();
reqSend.media.duration = video.duration;
reqSend.media.w = video.w;
reqSend.media.h = video.h;
DelayedMessage delayedMessage = new DelayedMessage();
delayedMessage.sendRequest = reqSend;
delayedMessage.type = 1;
delayedMessage.obj = newMsgObj;
delayedMessage.location = video.thumb.location;
delayedMessage.videoLocation = video;
performSendDelayedMessage(delayedMessage);
} else if (type == 5) {
reqSend.media = new TLRPC.TL_inputMediaPhoto();
TLRPC.TL_inputPhoto ph = new TLRPC.TL_inputPhoto();
ph.id = msgObj.messageOwner.action.photo.id;
ph.access_hash = msgObj.messageOwner.action.photo.access_hash;
((TLRPC.TL_inputMediaPhoto)reqSend.media).id = ph;
performSendMessageRequest(reqSend, newMsgObj);
} else if (type == 6) {
reqSend.media = new TLRPC.TL_inputMediaContact();
reqSend.media.phone_number = user.phone;
reqSend.media.first_name = user.first_name;
reqSend.media.last_name = user.last_name;
performSendMessageRequest(reqSend, newMsgObj);
}
} else {
TLRPC.TL_decryptedMessage reqSend = new TLRPC.TL_decryptedMessage();
reqSend.random_id = newMsg.random_id;
reqSend.random_bytes = new byte[Math.max(1, (int)Math.ceil(random.nextDouble() * 16))];
random.nextBytes(reqSend.random_bytes);
reqSend.message = "";
if (type == 1) {
reqSend.media = new TLRPC.TL_decryptedMessageMediaGeoPoint();
reqSend.media.lat = lat;
reqSend.media._long = lon;
performSendEncryptedRequest(reqSend, newMsgObj, encryptedChat, null);
} else if (type == 2) {
reqSend.media = new TLRPC.TL_decryptedMessageMediaPhoto();
reqSend.media.iv = new byte[32];
reqSend.media.key = new byte[32];
random.nextBytes(reqSend.media.iv);
random.nextBytes(reqSend.media.key);
TLRPC.PhotoSize small = photo.sizes.get(0);
TLRPC.PhotoSize big = photo.sizes.get(photo.sizes.size() - 1);
reqSend.media.thumb = small.bytes;
reqSend.media.thumb_h = small.h;
reqSend.media.thumb_w = small.w;
reqSend.media.w = big.w;
reqSend.media.h = big.h;
reqSend.media.size = big.size;
DelayedMessage delayedMessage = new DelayedMessage();
delayedMessage.sendEncryptedRequest = reqSend;
delayedMessage.type = 0;
delayedMessage.obj = newMsgObj;
delayedMessage.encryptedChat = encryptedChat;
delayedMessage.location = photo.sizes.get(photo.sizes.size() - 1).location;
performSendDelayedMessage(delayedMessage);
} else if (type == 3) {
reqSend.media = new TLRPC.TL_decryptedMessageMediaVideo();
reqSend.media.iv = new byte[32];
reqSend.media.key = new byte[32];
random.nextBytes(reqSend.media.iv);
random.nextBytes(reqSend.media.key);
reqSend.media.duration = video.duration;
reqSend.media.size = video.size;
reqSend.media.w = video.w;
reqSend.media.h = video.h;
reqSend.media.thumb = video.thumb.bytes;
reqSend.media.thumb_h = video.thumb.h;
reqSend.media.thumb_w = video.thumb.w;
DelayedMessage delayedMessage = new DelayedMessage();
delayedMessage.sendEncryptedRequest = reqSend;
delayedMessage.type = 1;
delayedMessage.obj = newMsgObj;
delayedMessage.encryptedChat = encryptedChat;
delayedMessage.videoLocation = video;
performSendDelayedMessage(delayedMessage);
} else if (type == 5) {
} else if (type == 6) {
reqSend.media = new TLRPC.TL_decryptedMessageMediaContact();
reqSend.media.phone_number = user.phone;
reqSend.media.first_name = user.first_name;
reqSend.media.last_name = user.last_name;
reqSend.media.user_id = user.id;
performSendEncryptedRequest(reqSend, newMsgObj, encryptedChat, null);
}
}
} else if (type == 4) {
TLRPC.TL_messages_forwardMessage reqSend = new TLRPC.TL_messages_forwardMessage();
reqSend.peer = sendToPeer;
reqSend.random_id = newMsg.random_id;
if (msgObj.messageOwner.id >= 0) {
reqSend.id = msgObj.messageOwner.id;
} else {
reqSend.id = msgObj.messageOwner.fwd_msg_id;
}
performSendMessageRequest(reqSend, newMsgObj);
}
}
private void processSendedMessage(TLRPC.Message newMsg, TLRPC.Message sendedMessage, TLRPC.EncryptedFile file, TLRPC.DecryptedMessage decryptedMessage) {
if (sendedMessage != null) {
if (sendedMessage.media instanceof TLRPC.TL_messageMediaPhoto && sendedMessage.media.photo != null && newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) {
for (TLRPC.PhotoSize size : sendedMessage.media.photo.sizes) {
for (TLRPC.PhotoSize size2 : newMsg.media.photo.sizes) {
if (size.type.equals(size2.type)) {
String fileName = size2.location.volume_id + "_" + size2.location.local_id;
String fileName2 = size.location.volume_id + "_" + size.location.local_id;
if (fileName.equals(fileName2)) {
break;
}
File cacheFile = new File(Utilities.getCacheDir(), fileName + ".jpg");
File cacheFile2 = new File(Utilities.getCacheDir(), fileName2 + ".jpg");
cacheFile.renameTo(cacheFile2);
FileLoader.Instance.replaceImageInCache(fileName, fileName2);
size2.location = size.location;
break;
}
}
}
sendedMessage.message = newMsg.message;
sendedMessage.attachPath = newMsg.attachPath;
} else if (sendedMessage.media instanceof TLRPC.TL_messageMediaVideo && sendedMessage.media.video != null && newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) {
TLRPC.PhotoSize size2 = newMsg.media.video.thumb;
TLRPC.PhotoSize size = sendedMessage.media.video.thumb;
String fileName = size2.location.volume_id + "_" + size2.location.local_id;
String fileName2 = size.location.volume_id + "_" + size.location.local_id;
if (fileName.equals(fileName2)) {
return;
}
File cacheFile = new File(Utilities.getCacheDir(), fileName + ".jpg");
File cacheFile2 = new File(Utilities.getCacheDir(), fileName2 + ".jpg");
boolean result = cacheFile.renameTo(cacheFile2);
FileLoader.Instance.replaceImageInCache(fileName, fileName2);
size2.location = size.location;
sendedMessage.message = newMsg.message;
sendedMessage.attachPath = newMsg.attachPath;
}
} else if (file != null) {
if (newMsg.media instanceof TLRPC.TL_messageMediaPhoto && newMsg.media.photo != null) {
TLRPC.PhotoSize size = newMsg.media.photo.sizes.get(newMsg.media.photo.sizes.size() - 1);
String fileName = size.location.volume_id + "_" + size.location.local_id;
size.location = new TLRPC.TL_fileEncryptedLocation();
size.location.key = decryptedMessage.media.key;
size.location.iv = decryptedMessage.media.iv;
size.location.dc_id = file.dc_id;
size.location.volume_id = file.id;
size.location.secret = file.access_hash;
size.location.local_id = file.key_fingerprint;
String fileName2 = size.location.volume_id + "_" + size.location.local_id;
File cacheFile = new File(Utilities.getCacheDir(), fileName + ".jpg");
File cacheFile2 = new File(Utilities.getCacheDir(), fileName2 + ".jpg");
boolean result = cacheFile.renameTo(cacheFile2);
FileLoader.Instance.replaceImageInCache(fileName, fileName2);
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(newMsg);
MessagesStorage.Instance.putMessages(arr, false, true);
} else if (newMsg.media instanceof TLRPC.TL_messageMediaVideo && newMsg.media.video != null) {
TLRPC.Video video = newMsg.media.video;
newMsg.media.video = new TLRPC.TL_videoEncrypted();
newMsg.media.video.duration = video.duration;
newMsg.media.video.thumb = video.thumb;
newMsg.media.video.id = video.id;
newMsg.media.video.dc_id = file.dc_id;
newMsg.media.video.w = video.w;
newMsg.media.video.h = video.h;
newMsg.media.video.date = video.date;
newMsg.media.video.caption = "";
newMsg.media.video.user_id = video.user_id;
newMsg.media.video.size = file.size;
newMsg.media.video.id = file.id;
newMsg.media.video.access_hash = file.access_hash;
newMsg.media.video.key = decryptedMessage.media.key;
newMsg.media.video.iv = decryptedMessage.media.iv;
newMsg.media.video.path = video.path;
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(newMsg);
MessagesStorage.Instance.putMessages(arr, false, true);
}
}
}
private void performSendEncryptedRequest(final TLRPC.DecryptedMessage req, final MessageObject newMsgObj, final TLRPC.EncryptedChat chat, final TLRPC.InputEncryptedFile encryptedFile) {
//TLRPC.decryptedMessageLayer messageLayer = new TLRPC.decryptedMessageLayer();
//messageLayer.layer = 8;
//messageLayer.message = req;
SerializedData data = new SerializedData();
req.serializeToStream(data);
SerializedData toEncrypt = new SerializedData();
toEncrypt.writeInt32(data.length());
toEncrypt.writeRaw(data.toByteArray());
byte[] innerData = toEncrypt.toByteArray();
byte[] messageKeyFull = Utilities.computeSHA1(innerData);
byte[] messageKey = new byte[16];
System.arraycopy(messageKeyFull, messageKeyFull.length - 16, messageKey, 0, 16);
MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false);
SerializedData dataForEncryption = new SerializedData();
dataForEncryption.writeRaw(innerData);
while (dataForEncryption.length() % 16 != 0) {
dataForEncryption.writeByte(0);
}
byte[] encryptedData = Utilities.aesIgeEncryption(dataForEncryption.toByteArray(), keyData.aesKey, keyData.aesIv, true, false);
data = new SerializedData();
data.writeInt64(chat.key_fingerprint);
data.writeRaw(messageKey);
data.writeRaw(encryptedData);
TLObject reqToSend;
if (encryptedFile == null) {
TLRPC.TL_messages_sendEncrypted req2 = new TLRPC.TL_messages_sendEncrypted();
req2.data = data.toByteArray();
req2.random_id = req.random_id;
req2.peer = new TLRPC.TL_inputEncryptedChat();
req2.peer.chat_id = chat.id;
req2.peer.access_hash = chat.access_hash;
reqToSend = req2;
} else {
TLRPC.TL_messages_sendEncryptedFile req2 = new TLRPC.TL_messages_sendEncryptedFile();
req2.data = data.toByteArray();
req2.random_id = req.random_id;
req2.peer = new TLRPC.TL_inputEncryptedChat();
req2.peer.chat_id = chat.id;
req2.peer.access_hash = chat.access_hash;
req2.file = encryptedFile;
reqToSend = req2;
}
ConnectionsManager.Instance.performRpc(reqToSend, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_SentEncryptedMessage res = (TLRPC.messages_SentEncryptedMessage)response;
if (res.file instanceof TLRPC.TL_encryptedFile) {
processSendedMessage(newMsgObj.messageOwner, null, res.file, req);
}
MessagesStorage.Instance.updateMessageStateAndId(newMsgObj.messageOwner.random_id, newMsgObj.messageOwner.id, newMsgObj.messageOwner.id, res.date, true);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SENT;
NotificationCenter.Instance.postNotificationName(messageReceivedByServer, newMsgObj.messageOwner.id, newMsgObj.messageOwner.id);
sendingMessages.remove(newMsgObj.messageOwner.id);
}
});
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
sendingMessages.remove(newMsgObj.messageOwner.id);
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.Instance.postNotificationName(messageSendError, newMsgObj.messageOwner.id);
}
});
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
private void performSendMessageRequest(TLObject req, final MessageObject newMsgObj) {
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
final int oldId = newMsgObj.messageOwner.id;
ArrayList<TLRPC.Message> sendedMessages = new ArrayList<TLRPC.Message>();
if (response instanceof TLRPC.TL_messages_sentMessage) {
TLRPC.TL_messages_sentMessage res = (TLRPC.TL_messages_sentMessage)response;
newMsgObj.messageOwner.id = res.id;
if(UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastDateValue = res.date;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else {
getDifference();
}
} else if (response instanceof TLRPC.messages_StatedMessage) {
TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
sendedMessages.add(res.message);
newMsgObj.messageOwner.id = res.message.id;
processSendedMessage(newMsgObj.messageOwner, res.message, null, null);
if(UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.lastDateValue = res.message.date;
UserConfig.saveConfig();
} else {
getDifference();
}
} else if (response instanceof TLRPC.messages_StatedMessages) {
TLRPC.messages_StatedMessages res = (TLRPC.messages_StatedMessages)response;
if (!res.messages.isEmpty()) {
TLRPC.Message message = res.messages.get(0);
newMsgObj.messageOwner.id = message.id;
sendedMessages.add(message);
processSendedMessage(newMsgObj.messageOwner, message, null, null);
}
if(UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else {
getDifference();
}
}
MessagesStorage.Instance.updateMessageStateAndId(newMsgObj.messageOwner.random_id, oldId, newMsgObj.messageOwner.id, 0, true);
if (!sendedMessages.isEmpty()) {
MessagesStorage.Instance.putMessages(sendedMessages, true, true);
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SENT;
NotificationCenter.Instance.postNotificationName(messageReceivedByServer, oldId, newMsgObj.messageOwner.id);
sendingMessages.remove(oldId);
}
});
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
sendingMessages.remove(newMsgObj.messageOwner.id);
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SEND_ERROR;
NotificationCenter.Instance.postNotificationName(messageSendError, newMsgObj.messageOwner.id);
}
});
}
}
}, null, (req instanceof TLRPC.TL_messages_forwardMessages ? null : new RPCRequest.RPCQuickAckDelegate() {
@Override
public void quickAck() {
final int msg_id = newMsgObj.messageOwner.id;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
newMsgObj.messageOwner.send_state = MESSAGE_SEND_STATE_SENT;
NotificationCenter.Instance.postNotificationName(messageReceivedByAck, msg_id);
}
});
}
}), true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors, ConnectionsManager.DEFAULT_DATACENTER_ID);
}
private void performSendDelayedMessage(final DelayedMessage message) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (message.type == 0) {
String location = Utilities.getCacheDir() + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
delayedMessages.put(location, message);
if (message.sendRequest != null) {
FileLoader.Instance.uploadFile(location, null, null);
} else {
FileLoader.Instance.uploadFile(location, message.sendEncryptedRequest.media.key, message.sendEncryptedRequest.media.iv);
}
} else if (message.type == 1) {
if (message.sendRequest != null) {
if (message.sendRequest.media.thumb == null) {
String location = Utilities.getCacheDir() + "/" + message.location.volume_id + "_" + message.location.local_id + ".jpg";
delayedMessages.put(location, message);
FileLoader.Instance.uploadFile(location, null, null);
} else {
String location = message.videoLocation.path;
if (location == null) {
location = Utilities.getCacheDir() + "/" + message.videoLocation.id + ".mp4";
}
delayedMessages.put(location, message);
FileLoader.Instance.uploadFile(location, null, null);
}
} else {
String location = message.videoLocation.path;
if (location == null) {
location = Utilities.getCacheDir() + "/" + message.videoLocation.id + ".mp4";
}
delayedMessages.put(location, message);
FileLoader.Instance.uploadFile(location, message.sendEncryptedRequest.media.key, message.sendEncryptedRequest.media.iv);
}
}
}
});
}
public void fileDidFailedUpload(final String location) {
if (uploadingAvatar != null && uploadingAvatar.equals(location)) {
uploadingAvatar = null;
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
DelayedMessage obj = delayedMessages.get(location);
if (obj != null) {
obj.obj.messageOwner.send_state = MESSAGE_SEND_STATE_SEND_ERROR;
sendingMessages.remove(obj.obj.messageOwner.id);
NotificationCenter.Instance.postNotificationName(messageSendError, obj.obj.messageOwner.id);
delayedMessages.remove(location);
}
}
});
}
}
public void rebuildContactsWithNewUser(final TLRPC.User user, final long bookId) {
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
final HashMap<Integer, Contact> contactsMapBook = new HashMap<Integer, Contact>(contactsBook);
final HashMap<String, ArrayList<Contact>> sectionsDictBook = new HashMap<String, ArrayList<Contact>>();
final ArrayList<String> sortedSectionsArrayBook = new ArrayList<String>();
Contact newContactBook = new Contact();
newContactBook.first_name = user.first_name;
newContactBook.last_name = user.last_name;
newContactBook.id = (int)bookId;
newContactBook.phones = new ArrayList<String>();
newContactBook.phones.add(user.phone);
newContactBook.phoneTypes = new ArrayList<String>();
newContactBook.phoneTypes.add(Utilities.applicationContext.getString(R.string.PhoneMobile));
contactsMapBook.put((int)bookId, newContactBook);
String contactsImportHash = "";
MessageDigest mdEnc = null;
try {
mdEnc = MessageDigest.getInstance("MD5");
} catch (Exception e) {
e.printStackTrace();
}
for (HashMap.Entry<Integer, Contact> pair : contactsMapBook.entrySet()) {
Contact value = pair.getValue();
int id = pair.getKey();
if (mdEnc != null) {
for (int a = 0; a < value.phones.size(); a++) {
String str = id + value.first_name + value.last_name + value.phones.get(a);
mdEnc.update(str.getBytes());
}
}
String key = value.last_name;
if (key.length() == 0) {
key = value.first_name;
}
if (key.length() == 0) {
key = "#";
if (value.phones.size() != 0) {
value.first_name = "+" + value.phones.get(0);
}
} else {
key = key.toUpperCase();
}
if (key.length() > 1) {
key = key.substring(0, 1);
}
ArrayList<Contact> arr = sectionsDictBook.get(key);
if (arr == null) {
arr = new ArrayList<Contact>();
sectionsDictBook.put(key, arr);
sortedSectionsArrayBook.add(key);
}
arr.add(value);
}
for (HashMap.Entry<String, ArrayList<Contact>> entry : sectionsDictBook.entrySet()) {
Collections.sort(entry.getValue(), new Comparator<Contact>() {
@Override
public int compare(Contact contact, Contact contact2) {
String toComapre1 = contact.last_name;
if (toComapre1.length() == 0) {
toComapre1 = contact.first_name;
}
String toComapre2 = contact2.last_name;
if (toComapre2.length() == 0) {
toComapre2 = contact2.first_name;
}
return toComapre1.compareTo(toComapre2);
}
});
}
Collections.sort(sortedSectionsArrayBook, new Comparator<String>() {
@Override
public int compare(String s, String s2) {
char cv1 = s.charAt(0);
char cv2 = s2.charAt(0);
if (cv1 == '#') {
return 1;
} else if (cv2 == '#') {
return -1;
} else if (cv1 >= 'A' && cv1 <= 'Z' && cv2 >= 'A' && cv2 <= 'Z') {
return s.compareTo(s2);
} else if (cv1 >= 'A' && cv1 <= 'Z' && !(cv2 >= 'A' && cv2 <= 'Z')) {
return 1;
} else if (!(cv1 >= 'A' && cv1 <= 'Z') && cv2 >= 'A' && cv2 <= 'Z') {
return -1;
}
return s.compareTo(s2);
}
});
String importHash = String.format(Locale.US, "%32s", new BigInteger(1, mdEnc.digest()).toString(16)).replace(' ', '0');
//end of phone book update
final ArrayList<TLRPC.TL_contact> contactsArr = new ArrayList<TLRPC.TL_contact>(contacts);
TLRPC.TL_contact newContact = new TLRPC.TL_contact();
newContact.user_id = user.id;
contactsArr.add(newContact);
Collections.sort(contactsArr, new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact tl_contact, TLRPC.TL_contact tl_contact2) {
TLRPC.User user1 = users.get(tl_contact.user_id);
TLRPC.User user2 = users.get(tl_contact2.user_id);
String name1 = user1.last_name;
if (name1 == null || name1.length() == 0) {
name1 = user1.first_name;
}
String name2 = user2.last_name;
if (name2 == null || name2.length() == 0) {
name2 = user2.first_name;
}
return name1.compareTo(name2);
}
});
final HashMap<String, ArrayList<TLRPC.TL_contact>> sectionsDict = new HashMap<String, ArrayList<TLRPC.TL_contact>>();
final SparseArray<TLRPC.TL_contact> contactsDictionery = new SparseArray<TLRPC.TL_contact>();
final ArrayList<String> sortedSectionsArray = new ArrayList<String>();
final HashMap<String, TLRPC.TL_contact> contactsPhones = new HashMap<String, TLRPC.TL_contact>();
for (TLRPC.TL_contact value : contactsArr) {
TLRPC.User user = users.get(value.user_id);
contactsDictionery.put(value.user_id, value);
contactsPhones.put(user.phone, value);
String key = user.last_name;
if (key == null || key.length() == 0) {
key = user.first_name;
}
if (key.length() == 0) {
key = "#";
} else {
key = key.toUpperCase();
}
if (key.length() > 1) {
key = key.substring(0, 1);
}
ArrayList<TLRPC.TL_contact> arr = sectionsDict.get(key);
if (arr == null) {
arr = new ArrayList<TLRPC.TL_contact>();
sectionsDict.put(key, arr);
sortedSectionsArray.add(key);
}
arr.add(value);
}
for (HashMap.Entry<String, ArrayList<TLRPC.TL_contact>> entry : sectionsDict.entrySet()) {
Collections.sort(entry.getValue(), new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact contact, TLRPC.TL_contact contact2) {
TLRPC.User user1 = users.get(contact.user_id);
TLRPC.User user2 = users.get(contact2.user_id);
String toComapre1 = user1.last_name;
if (toComapre1 == null || toComapre1.length() == 0) {
toComapre1 = user1.first_name;
}
String toComapre2 = user2.last_name;
if (toComapre2 == null || toComapre2.length() == 0) {
toComapre2 = user2.first_name;
}
return toComapre1.compareTo(toComapre2);
}
});
}
Collections.sort(sortedSectionsArray, new Comparator<String>() {
@Override
public int compare(String s, String s2) {
char cv1 = s.charAt(0);
char cv2 = s2.charAt(0);
if (cv1 == '#') {
return 1;
} else if (cv2 == '#') {
return -1;
} else if (cv1 >= 'A' && cv1 <= 'Z' && cv2 >= 'A' && cv2 <= 'Z') {
return s.compareTo(s2);
} else if (cv1 >= 'A' && cv1 <= 'Z' && !(cv2 >= 'A' && cv2 <= 'Z')) {
return 1;
} else if (!(cv1 >= 'A' && cv1 <= 'Z') && cv2 >= 'A' && cv2 <= 'Z') {
return -1;
}
return s.compareTo(s2);
}
});
final ArrayList<TLRPC.TL_contact> contactsArrSortedByIds = new ArrayList<TLRPC.TL_contact>(contactsArr);
Collections.sort(contactsArrSortedByIds, new Comparator<TLRPC.TL_contact>() {
@Override
public int compare(TLRPC.TL_contact lhs, TLRPC.TL_contact rhs) {
Integer lid = lhs.user_id;
Integer rid = rhs.user_id;
return lid.compareTo(rid);
}
});
String ids = "";
for (TLRPC.TL_contact aContactsArr : contactsArrSortedByIds) {
if (ids.length() != 0) {
ids += ",";
}
ids += aContactsArr.user_id;
}
UserConfig.contactsHash = Utilities.MD5(ids);
UserConfig.importHash = importHash;
UserConfig.saveConfig();
MessagesStorage.Instance.putContacts(contactsArr, true);
ArrayList<TLRPC.User> users = new ArrayList<TLRPC.User>();
users.add(user);
MessagesStorage.Instance.putUsersAndChats(users, null, true, true);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
contactsBook = contactsMapBook;
contactsSectionsDict = sectionsDictBook;
sortedContactsSectionsArray = sortedSectionsArrayBook;
NotificationCenter.Instance.postNotificationName(contactsBookDidLoaded);
contacts = contactsArr;
contactsByPhones = contactsPhones;
contactsDict = contactsDictionery;
usersSectionsDict = sectionsDict;
sortedUsersSectionsArray = sortedSectionsArray;
NotificationCenter.Instance.postNotificationName(contactsDidLoaded);
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
}
});
}
});
}
public void addContact(TLRPC.User user) {
if (user == null) {
return;
}
long num = addContact(currentAccount, user, user.phone);
rebuildContactsWithNewUser(user, num);
TLRPC.TL_contacts_importContacts req = new TLRPC.TL_contacts_importContacts();
ArrayList<TLRPC.TL_inputPhoneContact> contacts = new ArrayList<TLRPC.TL_inputPhoneContact>();
TLRPC.TL_inputPhoneContact c = new TLRPC.TL_inputPhoneContact();
c.phone = user.phone;
c.first_name = user.first_name;
c.last_name = user.last_name;
c.client_id = num;
contacts.add(c);
req.contacts = contacts;
req.replace = false;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
public void fileDidUploaded(final String location, final TLRPC.TL_inputFile file, final TLRPC.TL_inputEncryptedFileUploaded encryptedFile) {
if (uploadingAvatar != null && uploadingAvatar.equals(location)) {
TLRPC.TL_photos_uploadProfilePhoto req = new TLRPC.TL_photos_uploadProfilePhoto();
req.caption = "";
req.crop = new TLRPC.TL_inputPhotoCropAuto();
req.file = file;
req.geo_point = new TLRPC.TL_inputGeoPointEmpty();
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
DelayedMessage message = delayedMessages.get(location);
if (message != null) {
if (file != null) {
if (message.type == 0) {
message.sendRequest.media.file = file;
performSendMessageRequest(message.sendRequest, message.obj);
} else if (message.type == 1) {
if (message.sendRequest.media.thumb == null) {
message.sendRequest.media.thumb = file;
performSendDelayedMessage(message);
} else {
message.sendRequest.media.file = file;
performSendMessageRequest(message.sendRequest, message.obj);
}
}
} else if (encryptedFile != null) {
if (message.type == 0) {
performSendEncryptedRequest(message.sendEncryptedRequest, message.obj, message.encryptedChat, encryptedFile);
} else if (message.type == 1) {
performSendEncryptedRequest(message.sendEncryptedRequest, message.obj, message.encryptedChat, encryptedFile);
}
}
delayedMessages.remove(location);
}
}
});
}
}
public void createChat(String title, ArrayList<Integer> selectedContacts, final TLRPC.TL_inputFile uploadedAvatar) {
TLRPC.TL_messages_createChat req = new TLRPC.TL_messages_createChat();
req.title = title;
for (Integer uid : selectedContacts) {
TLRPC.User user = MessagesController.Instance.users.get(uid);
TLRPC.InputUser inputUser;
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
inputUser = new TLRPC.TL_inputUserForeign();
inputUser.user_id = user.id;
inputUser.access_hash = user.access_hash;
} else {
inputUser = new TLRPC.TL_inputUserContact();
inputUser.user_id = user.id;
}
req.users.add(inputUser);
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(chatDidFailCreate);
}
});
return;
}
final TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
final ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
messages.add(res.message);
MessagesStorage.Instance.putMessages(messages, true, true);
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
final ArrayList<MessageObject> messagesObj = new ArrayList<MessageObject>();
messagesObj.add(new MessageObject(res.message, users));
TLRPC.Chat chat = res.chats.get(0);
updateInterfaceWithMessages(-chat.id, messagesObj);
NotificationCenter.Instance.postNotificationName(chatDidCreated, chat.id);
if (uploadedAvatar != null) {
changeChatAvatar(chat.id, uploadedAvatar);
}
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void addUserToChat(int chat_id, final int user_id, final TLRPC.ChatParticipants info) {
TLRPC.TL_messages_addChatUser req = new TLRPC.TL_messages_addChatUser();
req.chat_id = chat_id;
req.fwd_limit = 50;
TLRPC.User user = MessagesController.Instance.users.get(user_id);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.user_id = new TLRPC.TL_inputUserForeign();
req.user_id.user_id = user.id;
req.user_id.access_hash = user.access_hash;
} else {
req.user_id = new TLRPC.TL_inputUserContact();
req.user_id.user_id = user.id;
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
return;
}
final TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
final ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
messages.add(res.message);
MessagesStorage.Instance.putMessages(messages, true, true);
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
final ArrayList<MessageObject> messagesObj = new ArrayList<MessageObject>();
messagesObj.add(new MessageObject(res.message, users));
TLRPC.Chat chat = res.chats.get(0);
chats.put(chat.id, chat);
updateInterfaceWithMessages(-chat.id, messagesObj);
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
if (info != null) {
for (TLRPC.TL_chatParticipant p : info.participants) {
if (p.user_id == user_id) {
return;
}
}
TLRPC.TL_chatParticipant newPart = new TLRPC.TL_chatParticipant();
newPart.user_id = user_id;
newPart.inviter_id = UserConfig.clientUserId;
newPart.date = ConnectionsManager.Instance.getCurrentTime();
info.participants.add(0, newPart);
MessagesStorage.Instance.updateChatInfo(info.chat_id, info, true);
NotificationCenter.Instance.postNotificationName(chatInfoDidLoaded, info.chat_id, info);
}
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void deleteUserFromChat(int chat_id, final int user_id, final TLRPC.ChatParticipants info) {
TLRPC.TL_messages_deleteChatUser req = new TLRPC.TL_messages_deleteChatUser();
req.chat_id = chat_id;
TLRPC.User user = MessagesController.Instance.users.get(user_id);
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
req.user_id = new TLRPC.TL_inputUserForeign();
req.user_id.user_id = user.id;
req.user_id.access_hash = user.access_hash;
} else if (user instanceof TLRPC.TL_userSelf) {
req.user_id = new TLRPC.TL_inputUserSelf();
} else {
req.user_id = new TLRPC.TL_inputUserContact();
req.user_id.user_id = user.id;
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
return;
}
final TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
if (user_id != UserConfig.clientUserId) {
final ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
messages.add(res.message);
MessagesStorage.Instance.putMessages(messages, true, true);
}
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
if (user_id != UserConfig.clientUserId) {
final ArrayList<MessageObject> messagesObj = new ArrayList<MessageObject>();
messagesObj.add(new MessageObject(res.message, users));
TLRPC.Chat chat = res.chats.get(0);
chats.put(chat.id, chat);
updateInterfaceWithMessages(-chat.id, messagesObj);
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
}
boolean changed = false;
if (info != null) {
for (int a = 0; a < info.participants.size(); a++) {
TLRPC.TL_chatParticipant p = info.participants.get(a);
if (p.user_id == user_id) {
info.participants.remove(a);
changed = true;
break;
}
}
if (changed) {
MessagesStorage.Instance.updateChatInfo(info.chat_id, info, true);
NotificationCenter.Instance.postNotificationName(chatInfoDidLoaded, info.chat_id, info);
}
}
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void changeChatTitle(int chat_id, String title) {
TLRPC.TL_messages_editChatTitle req = new TLRPC.TL_messages_editChatTitle();
req.chat_id = chat_id;
req.title = title;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
return;
}
final TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
final ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
messages.add(res.message);
MessagesStorage.Instance.putMessages(messages, true, true);
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
final ArrayList<MessageObject> messagesObj = new ArrayList<MessageObject>();
messagesObj.add(new MessageObject(res.message, users));
TLRPC.Chat chat = res.chats.get(0);
chats.put(chat.id, chat);
updateInterfaceWithMessages(-chat.id, messagesObj);
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void changeChatAvatar(int chat_id, TLRPC.TL_inputFile uploadedAvatar) {
TLRPC.TL_messages_editChatPhoto req2 = new TLRPC.TL_messages_editChatPhoto();
req2.chat_id = chat_id;
if (uploadedAvatar != null) {
req2.photo = new TLRPC.TL_inputChatUploadedPhoto();
req2.photo.file = uploadedAvatar;
req2.photo.crop = new TLRPC.TL_inputPhotoCropAuto();
} else {
req2.photo = new TLRPC.TL_inputChatPhotoEmpty();
}
ConnectionsManager.Instance.performRpc(req2, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error != null) {
return;
}
final TLRPC.messages_StatedMessage res = (TLRPC.messages_StatedMessage)response;
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, true, true);
final ArrayList<TLRPC.Message> messages = new ArrayList<TLRPC.Message>();
messages.add(res.message);
MessagesStorage.Instance.putMessages(messages, true, true);
if (UserConfig.lastSeqValue + 1 == res.seq) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastPtsValue = res.pts;
UserConfig.saveConfig();
} else if (UserConfig.lastSeqValue != res.seq) {
getDifference();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
final ArrayList<MessageObject> messagesObj = new ArrayList<MessageObject>();
messagesObj.add(new MessageObject(res.message, users));
TLRPC.Chat chat = res.chats.get(0);
chats.put(chat.id, chat);
updateInterfaceWithMessages(-chat.id, messagesObj);
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void unregistedPush() {
if (!UserConfig.registeredForPush || UserConfig.pushString.length() == 0) {
return;
}
TLRPC.TL_account_unregisterDevice req = new TLRPC.TL_account_unregisterDevice();
req.token = UserConfig.pushString;
req.token_type = 2;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
TLRPC.TL_auth_logOut req2 = new TLRPC.TL_auth_logOut();
ConnectionsManager.Instance.performRpc(req2, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void registerForPush(final String regid) {
if (regid == null || regid.length() == 0 || registeringForPush || UserConfig.clientUserId == 0) {
return;
}
if (UserConfig.registeredForPush && regid.equals(UserConfig.pushString)) {
return;
}
registeringForPush = true;
TLRPC.TL_account_registerDevice req = new TLRPC.TL_account_registerDevice();
try {
req.token_type = 2;
req.token = regid;
req.lang_code = Locale.getDefault().getCountry();
req.device_model = Build.MANUFACTURER + Build.MODEL;
if (req.device_model == null) {
req.device_model = "Android unknown";
}
req.system_version = "SDK " + Build.VERSION.SDK_INT;
PackageInfo pInfo = Utilities.applicationContext.getPackageManager().getPackageInfo(Utilities.applicationContext.getPackageName(), 0);
req.app_version = pInfo.versionName;
if (req.app_version == null) {
req.app_version = "App version unknown";
}
req.app_sandbox = false;
} catch (Exception e) {
e.printStackTrace();
registeringForPush = false;
}
if (req.app_version != null) {
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
Log.e("tmessages", "registered for push");
UserConfig.registeredForPush = true;
UserConfig.pushString = regid;
UserConfig.saveConfig();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
registeringForPush = false;
}
});
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
}
public void loadCurrentState() {
if (updatingState) {
return;
}
updatingState = true;
TLRPC.TL_updates_getState req = new TLRPC.TL_updates_getState();
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
updatingState = false;
if (error == null) {
TLRPC.TL_updates_state res = (TLRPC.TL_updates_state)response;
UserConfig.lastDateValue = res.date;
UserConfig.lastPtsValue = res.pts;
UserConfig.lastSeqValue = res.seq;
UserConfig.lastQtsValue = res.qts;
UserConfig.saveConfig();
} else {
loadCurrentState();
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void getDifference() {
registerForPush(UserConfig.pushString);
if (UserConfig.lastDateValue == 0) {
loadCurrentState();
return;
}
if (gettingDifference) {
return;
}
if (!firstGettingTask) {
getNewDeleteTask(null);
firstGettingTask = true;
}
gettingDifference = true;
TLRPC.TL_updates_getDifference req = new TLRPC.TL_updates_getDifference();
req.pts = UserConfig.lastPtsValue;
req.date = UserConfig.lastDateValue;
req.qts = UserConfig.lastQtsValue;
if (ConnectionsManager.Instance.connectionState == 0) {
ConnectionsManager.Instance.connectionState = 3;
final int stateCopy = ConnectionsManager.Instance.connectionState;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(703, stateCopy);
}
});
}
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
gettingDifference = false;
if (error == null) {
final TLRPC.updates_Difference res = (TLRPC.updates_Difference)response;
final HashMap<Integer, TLRPC.User> usersDict = new HashMap<Integer, TLRPC.User>();
for (TLRPC.User user : res.users) {
usersDict.put(user.id, user);
}
final ArrayList<TLRPC.TL_updateMessageID> msgUpdates = new ArrayList<TLRPC.TL_updateMessageID>();
if (!res.other_updates.isEmpty()) {
for (int a = 0; a < res.other_updates.size(); a++) {
TLRPC.Update upd = res.other_updates.get(a);
if (upd instanceof TLRPC.TL_updateMessageID) {
msgUpdates.add((TLRPC.TL_updateMessageID)upd);
res.other_updates.remove(a);
a--;
}
}
}
MessagesStorage.Instance.storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (!msgUpdates.isEmpty()) {
final HashMap<Integer, Integer> corrected = new HashMap<Integer, Integer>();
for (TLRPC.TL_updateMessageID update : msgUpdates) {
Integer oldId = MessagesStorage.Instance.updateMessageStateAndId(update.random_id, null, update.id, 0, false);
if (oldId != null) {
corrected.put(oldId, update.id);
}
}
if (!corrected.isEmpty()) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (HashMap.Entry<Integer, Integer> entry : corrected.entrySet()) {
Integer oldId = entry.getKey();
sendingMessages.remove(oldId);
Integer newId = entry.getValue();
NotificationCenter.Instance.postNotificationName(messageReceivedByServer, oldId, newId);
}
}
});
}
}
Utilities.stageQueue.postRunnable(new Runnable() {
@Override
public void run() {
if (!res.new_messages.isEmpty() || !res.new_encrypted_messages.isEmpty()) {
final HashMap<Long, ArrayList<MessageObject>> messages = new HashMap<Long, ArrayList<MessageObject>>();
for (TLRPC.EncryptedMessage encryptedMessage : res.new_encrypted_messages) {
TLRPC.Message message = decryptMessage(encryptedMessage);
if (message != null) {
res.new_messages.add(message);
}
}
for (TLRPC.Message message : res.new_messages) {
MessageObject obj = new MessageObject(message, usersDict);
long uid;
if (message.dialog_id != 0) {
uid = message.dialog_id;
} else {
if (message.to_id.chat_id != 0) {
uid = -message.to_id.chat_id;
} else {
if (message.to_id.user_id == UserConfig.clientUserId) {
message.to_id.user_id = message.from_id;
}
uid = message.to_id.user_id;
}
}
ArrayList<MessageObject> arr = messages.get(uid);
if (arr == null) {
arr = new ArrayList<MessageObject>();
messages.put(uid, arr);
}
arr.add(obj);
}
MessagesStorage.Instance.storageQueue.postRunnable(new Runnable() {
@Override
public void run() {
MessagesStorage.Instance.startTransaction(false);
MessagesStorage.Instance.putMessages(res.new_messages, false, false);
MessagesStorage.Instance.putUsersAndChats(res.users, res.chats, false, false);
MessagesStorage.Instance.commitTransaction(false);
}
});
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
for (TLRPC.User user : res.users) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
for (TLRPC.Chat chat : res.chats) {
chats.put(chat.id, chat);
}
for (HashMap.Entry<Long, ArrayList<MessageObject>> pair : messages.entrySet()) {
Long key = pair.getKey();
ArrayList<MessageObject> value = pair.getValue();
updateInterfaceWithMessages(key, value);
}
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
}
if (res != null && !res.other_updates.isEmpty()) {
processUpdateArray(res.other_updates, null, null);
}
if (res instanceof TLRPC.TL_updates_difference) {
UserConfig.lastSeqValue = res.state.seq;
UserConfig.lastDateValue = res.state.date;
UserConfig.lastPtsValue = res.state.pts;
UserConfig.lastQtsValue = res.state.qts;
ConnectionsManager.Instance.connectionState = 0;
final int stateCopy = ConnectionsManager.Instance.connectionState;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(703, stateCopy);
}
});
} else if (res instanceof TLRPC.TL_updates_differenceSlice) {
UserConfig.lastSeqValue = res.intermediate_state.seq;
UserConfig.lastDateValue = res.intermediate_state.date;
UserConfig.lastPtsValue = res.intermediate_state.pts;
UserConfig.lastQtsValue = res.intermediate_state.qts;
getDifference();
} else if (res instanceof TLRPC.TL_updates_differenceEmpty) {
UserConfig.lastSeqValue = res.seq;
UserConfig.lastDateValue = res.date;
ConnectionsManager.Instance.connectionState = 0;
final int stateCopy = ConnectionsManager.Instance.connectionState;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
NotificationCenter.Instance.postNotificationName(703, stateCopy);
}
});
}
UserConfig.saveConfig();
}
});
}
});
if (ConnectionsManager.DEBUG_VERSION) {
Log.e("tmessages", "received defference with date = " + UserConfig.lastDateValue + " pts = " + UserConfig.lastPtsValue + " seq = " + UserConfig.lastSeqValue);
Log.e("tmessages", "messages = " + res.new_messages.size() + " users = " + res.users.size() + " chats = " + res.chats.size() + " other updates = " + res.other_updates.size());
}
} else {
loadCurrentState();
Log.e("tmessages", "get difference error, don't know what to do :(");
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void processUpdates(final TLRPC.Updates updates) {
boolean needGetDiff = false;
boolean needReceivedQueue = false;
if (updates instanceof TLRPC.TL_updateShort) {
ArrayList<TLRPC.Update> arr = new ArrayList<TLRPC.Update>();
arr.add(updates.update);
processUpdateArray(arr, null, null);
} else if (updates instanceof TLRPC.TL_updateShortChatMessage) {
if (UserConfig.lastSeqValue + 1 == updates.seq && chats.get(updates.chat_id) != null && users.get(updates.from_id) != null) {
TLRPC.TL_message message = new TLRPC.TL_message();
message.from_id = updates.from_id;
message.id = updates.id;
message.to_id = new TLRPC.TL_peerChat();
message.to_id.chat_id = updates.chat_id;
message.message = updates.message;
message.date = updates.date;
message.unread = true;
message.media = new TLRPC.TL_messageMediaEmpty();
UserConfig.lastSeqValue = updates.seq;
UserConfig.lastPtsValue = updates.pts;
final MessageObject obj = new MessageObject(message, null);
final ArrayList<MessageObject> objArr = new ArrayList<MessageObject>();
objArr.add(obj);
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(message);
MessagesStorage.Instance.putMessages(arr, false, true);
final boolean printUpdate = updatePrintingUsersWithNewMessages(-updates.chat_id, objArr);
if (printUpdate) {
updatePrintingStrings();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (printUpdate) {
NotificationCenter.Instance.postNotificationName(userPrintUpdate, (long)(-updates.chat_id));
NotificationCenter.Instance.postNotificationName(userPrintUpdateAll);
}
if (obj.messageOwner.from_id != UserConfig.clientUserId) {
long dialog_id;
if (obj.messageOwner.to_id.chat_id != 0) {
dialog_id = -obj.messageOwner.to_id.chat_id;
} else {
dialog_id = obj.messageOwner.to_id.user_id;
}
if (dialog_id != openned_dialog_id) {
showInAppNotification(obj);
}
}
updateInterfaceWithMessages(-updates.chat_id, objArr);
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
} else {
needGetDiff = true;
}
} else if (updates instanceof TLRPC.TL_updateShortMessage) {
if (UserConfig.lastSeqValue + 1 == updates.seq && users.get(updates.from_id) != null) {
TLRPC.TL_message message = new TLRPC.TL_message();
message.from_id = updates.from_id;
message.id = updates.id;
message.to_id = new TLRPC.TL_peerUser();
message.to_id.user_id = updates.from_id;
message.message = updates.message;
message.date = updates.date;
message.unread = true;
message.media = new TLRPC.TL_messageMediaEmpty();
UserConfig.lastSeqValue = updates.seq;
UserConfig.lastPtsValue = updates.pts;
UserConfig.lastDateValue = updates.date;
final MessageObject obj = new MessageObject(message, null);
final ArrayList<MessageObject> objArr = new ArrayList<MessageObject>();
objArr.add(obj);
ArrayList<TLRPC.Message> arr = new ArrayList<TLRPC.Message>();
arr.add(message);
MessagesStorage.Instance.putMessages(arr, false, true);
final boolean printUpdate = updatePrintingUsersWithNewMessages(updates.from_id, objArr);
if (printUpdate) {
updatePrintingStrings();
}
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (printUpdate) {
NotificationCenter.Instance.postNotificationName(userPrintUpdate, (long)(updates.from_id));
NotificationCenter.Instance.postNotificationName(userPrintUpdateAll);
}
if (obj.messageOwner.from_id != UserConfig.clientUserId) {
long dialog_id;
if (obj.messageOwner.to_id.chat_id != 0) {
dialog_id = -obj.messageOwner.to_id.chat_id;
} else {
dialog_id = obj.messageOwner.to_id.user_id;
}
if (dialog_id != openned_dialog_id) {
showInAppNotification(obj);
}
}
updateInterfaceWithMessages(updates.from_id, objArr);
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
} else {
needGetDiff = true;
}
} else if (updates instanceof TLRPC.TL_updatesCombined) {
if (UserConfig.lastSeqValue + 1 == updates.seq_start || updates.seq_start == 0 || UserConfig.lastSeqValue == updates.seq_start) {
MessagesStorage.Instance.putUsersAndChats(updates.users, updates.chats, true, true);
int lastPtsValue = UserConfig.lastPtsValue;
int lastQtsValue = UserConfig.lastQtsValue;
if (!processUpdateArray(updates.updates, updates.users, updates.chats)) {
UserConfig.lastPtsValue = lastPtsValue;
UserConfig.lastQtsValue = lastQtsValue;
needGetDiff = true;
} else {
UserConfig.lastDateValue = updates.date;
UserConfig.lastSeqValue = updates.seq;
if (UserConfig.lastQtsValue != lastQtsValue) {
needReceivedQueue = true;
}
}
} else {
needGetDiff = true;
}
} else if (updates instanceof TLRPC.TL_updates) {
if (UserConfig.lastSeqValue + 1 == updates.seq || updates.seq == 0 || updates.seq == UserConfig.lastSeqValue) {
MessagesStorage.Instance.putUsersAndChats(updates.users, updates.chats, true, true);
int lastPtsValue = UserConfig.lastPtsValue;
int lastQtsValue = UserConfig.lastQtsValue;
if (!processUpdateArray(updates.updates, updates.users, updates.chats)) {
needGetDiff = true;
UserConfig.lastPtsValue = lastPtsValue;
UserConfig.lastQtsValue = lastQtsValue;
} else {
UserConfig.lastDateValue = updates.date;
UserConfig.lastSeqValue = updates.seq;
if (UserConfig.lastQtsValue != lastQtsValue) {
needReceivedQueue = true;
}
}
} else {
needGetDiff = true;
}
} else if (updates instanceof TLRPC.TL_updatesTooLong) {
needGetDiff = true;
}
if (needGetDiff) {
getDifference();
}
if (needReceivedQueue) {
TLRPC.TL_messages_receivedQueue req = new TLRPC.TL_messages_receivedQueue();
req.max_qts = UserConfig.lastQtsValue;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
UserConfig.saveConfig();
}
public boolean processUpdateArray(ArrayList<TLRPC.Update> updates, final ArrayList<TLRPC.User> usersArr, final ArrayList<TLRPC.Chat> chatsArr) {
if (updates.isEmpty()) {
return true;
}
long currentTime = System.currentTimeMillis();
final HashMap<Long, ArrayList<MessageObject>> messages = new HashMap<Long, ArrayList<MessageObject>>(); //to chats+
final ArrayList<TLRPC.Message> messagesArr = new ArrayList<TLRPC.Message>(); //to db+
final ArrayList<Integer> markAsReadMessages = new ArrayList<Integer>(); //to db+ and chats+ and dialogs+
final HashMap<Integer, Integer> markAsReadEncrypted = new HashMap<Integer, Integer>(); //to db+ and chats+ and dialogs+
final ArrayList<Integer> deletedMessages = new ArrayList<Integer>(); //to db+ and chats+ and dialogs+
final ArrayList<Long> printChanges = new ArrayList<Long>(); //to chats+ and dialogs
final ArrayList<TLRPC.ChatParticipants> chatInfoToUpdate = new ArrayList<TLRPC.ChatParticipants>(); //to db+ and chats
final ArrayList<TLRPC.Update> updatesOnMainThread = new ArrayList<TLRPC.Update>(); //to db+ and every interface+
final ArrayList<TLRPC.TL_updateEncryptedMessagesRead> tasks = new ArrayList<TLRPC.TL_updateEncryptedMessagesRead>();
MessageObject lastMessage = null;
boolean usersAdded = false;
boolean checkForUsers = true;
ConcurrentHashMap<Integer, TLRPC.User> usersDict;
ConcurrentHashMap<Integer, TLRPC.Chat> chatsDict;
if (usersArr != null) {
usersDict = new ConcurrentHashMap<Integer, TLRPC.User>();
for (TLRPC.User user : usersArr) {
usersDict.put(user.id, user);
}
} else {
checkForUsers = false;
usersDict = users;
}
if (chatsArr != null) {
chatsDict = new ConcurrentHashMap<Integer, TLRPC.Chat>();
for (TLRPC.Chat chat : chatsArr) {
chatsDict.put(chat.id, chat);
}
} else {
checkForUsers = false;
chatsDict = chats;
}
boolean chatAvatarUpdated = false;
boolean reloadContacts = false;
for (TLRPC.Update update : updates) {
if (update instanceof TLRPC.TL_updateNewMessage) {
TLRPC.TL_updateNewMessage upd = (TLRPC.TL_updateNewMessage)update;
if (checkForUsers) {
if (usersDict.get(upd.message.from_id) == null && users.get(upd.message.from_id) == null || upd.message.to_id.chat_id != 0 && chatsDict.get(upd.message.to_id.chat_id) == null && chats.get(upd.message.to_id.chat_id) == null) {
return false;
}
}
messagesArr.add(upd.message);
MessageObject obj = new MessageObject(upd.message, usersDict);
if (obj.type == 11) {
chatAvatarUpdated = true;
}
long uid;
if (upd.message.to_id.chat_id != 0) {
uid = -upd.message.to_id.chat_id;
} else {
if (upd.message.to_id.user_id == UserConfig.clientUserId) {
upd.message.to_id.user_id = upd.message.from_id;
}
uid = upd.message.to_id.user_id;
}
ArrayList<MessageObject> arr = messages.get(uid);
if (arr == null) {
arr = new ArrayList<MessageObject>();
messages.put(uid, arr);
}
arr.add(obj);
UserConfig.lastPtsValue = update.pts;
if (upd.message.from_id != UserConfig.clientUserId && upd.message.to_id != null) {
if (uid != openned_dialog_id) {
lastMessage = obj;
}
}
} else if (update instanceof TLRPC.TL_updateMessageID) {
//can't be here
} else if (update instanceof TLRPC.TL_updateReadMessages) {
markAsReadMessages.addAll(update.messages);
UserConfig.lastPtsValue = update.pts;
} else if (update instanceof TLRPC.TL_updateDeleteMessages) {
deletedMessages.addAll(update.messages);
UserConfig.lastPtsValue = update.pts;
} else if (update instanceof TLRPC.TL_updateRestoreMessages) {
UserConfig.lastPtsValue = update.pts;
} else if (update instanceof TLRPC.TL_updateUserTyping || update instanceof TLRPC.TL_updateChatUserTyping) {
if (update.user_id != UserConfig.clientUserId) {
long uid = -update.chat_id;
if (uid == 0) {
uid = update.user_id;
}
ArrayList<PrintingUser> arr = printingUsers.get(uid);
if (arr == null) {
arr = new ArrayList<PrintingUser>();
printingUsers.put(uid, arr);
}
boolean exist = false;
for (PrintingUser u : arr) {
if (u.userId == update.user_id) {
exist = true;
u.lastTime = currentTime;
break;
}
}
if (!exist) {
PrintingUser newUser = new PrintingUser();
newUser.userId = update.user_id;
newUser.lastTime = currentTime;
arr.add(newUser);
if (!printChanges.contains(uid)) {
printChanges.add(uid);
}
}
}
} else if (update instanceof TLRPC.TL_updateChatParticipants) {
chatInfoToUpdate.add(update.participants);
} else if (update instanceof TLRPC.TL_updateUserStatus) {
updatesOnMainThread.add(update);
} else if (update instanceof TLRPC.TL_updateUserName) {
updatesOnMainThread.add(update);
} else if (update instanceof TLRPC.TL_updateUserPhoto) {
updatesOnMainThread.add(update);
} else if (update instanceof TLRPC.TL_updateContactRegistered) {
reloadContacts = true;
//updateContactRegistered#2575bbb9 user_id:int date:int = Update;
//updateContactRegistered Импортированный ранее контакт зарегистрировался
} else if (update instanceof TLRPC.TL_updateContactLink) {
reloadContacts = true;
//updateContactLink#51a48a9a user_id:int my_link:contacts.MyLink foreign_link:contacts.ForeignLink = Update;
//updateContactLink Изменилась связь с пользователем
} else if (update instanceof TLRPC.TL_updateActivation) {
//updateActivation#6f690963 user_id:int = Update;
//updateActivation Пользователь активировал свой аккаунт
} else if (update instanceof TLRPC.TL_updateNewAuthorization) {
//updateNewAuthorization#8f06529a auth_key_id:long date:int device:string location:string = Update;
//updateNewAuthorization В аккаунт текущего пользователя был произведен вход с нового неизвестного устройства
} else if (update instanceof TLRPC.TL_updateNewGeoChatMessage) {
//TODO
} else if (update instanceof TLRPC.TL_updateNewEncryptedMessage) {
UserConfig.lastQtsValue = update.qts;
TLRPC.Message message = decryptMessage(((TLRPC.TL_updateNewEncryptedMessage)update).message);
if (message != null) {
int cid = ((TLRPC.TL_updateNewEncryptedMessage)update).message.chat_id;
messagesArr.add(message);
MessageObject obj = new MessageObject(message, usersDict);
if (obj.type == 11) {
chatAvatarUpdated = true;
}
long uid = ((long)cid) << 32;
ArrayList<MessageObject> arr = messages.get(uid);
if (arr == null) {
arr = new ArrayList<MessageObject>();
messages.put(uid, arr);
}
arr.add(obj);
if (message.from_id != UserConfig.clientUserId && message.to_id != null) {
if (uid != openned_dialog_id) {
lastMessage = obj;
}
}
}
} else if (update instanceof TLRPC.TL_updateEncryptedChatTyping) {
long uid = ((long)update.chat_id) << 32;
ArrayList<PrintingUser> arr = printingUsers.get(uid);
if (arr == null) {
arr = new ArrayList<PrintingUser>();
printingUsers.put(uid, arr);
}
boolean exist = false;
for (PrintingUser u : arr) {
if (u.userId == update.user_id) {
exist = true;
u.lastTime = currentTime;
break;
}
}
if (!exist) {
PrintingUser newUser = new PrintingUser();
newUser.userId = update.user_id;
newUser.lastTime = currentTime;
arr.add(newUser);
if (!printChanges.contains(uid)) {
printChanges.add(uid);
}
}
} else if (update instanceof TLRPC.TL_updateEncryptedMessagesRead) {
markAsReadEncrypted.put(update.chat_id, Math.max(update.max_date, update.date));
tasks.add((TLRPC.TL_updateEncryptedMessagesRead)update);
} else if (update instanceof TLRPC.TL_updateEncryption) {
final TLRPC.EncryptedChat newChat = update.chat;
long dialog_id = ((long)newChat.id) << 32;
TLRPC.EncryptedChat existingChat = encryptedChats.get(newChat.id);
if (existingChat == null) {
Semaphore semaphore = new Semaphore(0);
ArrayList<TLObject> result = new ArrayList<TLObject>();
MessagesStorage.Instance.getEncryptedChat(newChat.id, semaphore, result);
try {
semaphore.acquire();
} catch (Exception e) {
e.printStackTrace();
}
if (result.size() == 2) {
existingChat = (TLRPC.EncryptedChat)result.get(0);
TLRPC.User user = (TLRPC.User)result.get(1);
users.putIfAbsent(user.id, user);
}
}
if (newChat instanceof TLRPC.TL_encryptedChatRequested && existingChat == null) {
int user_id = newChat.participant_id;
if (user_id == UserConfig.clientUserId) {
user_id = newChat.admin_id;
}
TLRPC.User user = users.get(user_id);
newChat.user_id = user_id;
final TLRPC.TL_dialog dialog = new TLRPC.TL_dialog();
dialog.id = dialog_id;
dialog.unread_count = 0;
dialog.top_message = 0;
dialog.last_message_date = update.date;
usersAdded = true;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (usersArr != null) {
for (TLRPC.User user : usersArr) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
}
if (chatsArr != null) {
for (TLRPC.Chat chat : chatsArr) {
chats.put(chat.id, chat);
}
}
dialogs_dict.put(dialog.id, dialog);
dialogs.add(dialog);
dialogsServerOnly.clear();
encryptedChats.put(newChat.id, newChat);
Collections.sort(dialogs, new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) {
if (tl_dialog.last_message_date == tl_dialog2.last_message_date) {
return 0;
} else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) {
return 1;
} else {
return -1;
}
}
});
for (TLRPC.TL_dialog d : dialogs) {
if ((int)d.id != 0) {
dialogsServerOnly.add(d);
}
}
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
}
});
MessagesStorage.Instance.putEncryptedChat(newChat, user, dialog);
MessagesController.Instance.acceptSecretChat(newChat);
} else if (newChat instanceof TLRPC.TL_encryptedChat) {
if (existingChat != null && existingChat instanceof TLRPC.TL_encryptedChatWaiting && (existingChat.auth_key == null || existingChat.auth_key.length == 1)) {
newChat.a_or_b = existingChat.a_or_b;
newChat.user_id = existingChat.user_id;
processAcceptedSecretChat(newChat);
}
} else {
final TLRPC.EncryptedChat exist = existingChat;
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (exist != null) {
newChat.user_id = exist.user_id;
newChat.auth_key = exist.auth_key;
encryptedChats.put(newChat.id, newChat);
}
MessagesStorage.Instance.updateEncryptedChat(newChat);
NotificationCenter.Instance.postNotificationName(encryptedChatUpdated, newChat);
}
});
}
}
}
if (!messages.isEmpty()) {
for (HashMap.Entry<Long, ArrayList<MessageObject>> pair : messages.entrySet()) {
Long key = pair.getKey();
ArrayList<MessageObject> value = pair.getValue();
boolean printChanged = updatePrintingUsersWithNewMessages(key, value);
if (printChanged && !printChanges.contains(key)) {
printChanges.add(key);
}
}
}
if (reloadContacts) {
loadContacts(false);
}
if (!printChanges.isEmpty()) {
updatePrintingStrings();
}
final MessageObject lastMessageArg = lastMessage;
final boolean reloadInterfaceForce = chatAvatarUpdated;
if (!messagesArr.isEmpty()) {
MessagesStorage.Instance.putMessages(messagesArr, true, true);
}
final boolean usersAddedConst = usersAdded;
if (!messages.isEmpty() || !markAsReadMessages.isEmpty() || !deletedMessages.isEmpty() || !printChanges.isEmpty() || !chatInfoToUpdate.isEmpty() || !updatesOnMainThread.isEmpty() || !markAsReadEncrypted.isEmpty()) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (!usersAddedConst) {
if (usersArr != null) {
for (TLRPC.User user : usersArr) {
users.put(user.id, user);
if (user.id == UserConfig.clientUserId) {
UserConfig.currentUser = user;
}
}
}
if (chatsArr != null) {
for (TLRPC.Chat chat : chatsArr) {
chats.put(chat.id, chat);
}
}
}
boolean avatarsUpdate = false;
if (!updatesOnMainThread.isEmpty()) {
ArrayList<TLRPC.User> dbUsers = new ArrayList<TLRPC.User>();
ArrayList<TLRPC.User> dbUsersStatus = new ArrayList<TLRPC.User>();
for (TLRPC.Update update : updatesOnMainThread) {
TLRPC.User toDbUser = new TLRPC.User();
toDbUser.id = update.user_id;
TLRPC.User currentUser = users.get(update.user_id);
if (update instanceof TLRPC.TL_updateUserStatus) {
if (!(update.status instanceof TLRPC.TL_userStatusEmpty)) {
if (currentUser != null) {
currentUser.id = update.user_id;
currentUser.status = update.status;
if (update.status instanceof TLRPC.TL_userStatusOnline) {
currentUser.status.was_online = update.status.expires;
} else if (update.status instanceof TLRPC.TL_userStatusOffline) {
currentUser.status.expires = update.status.was_online;
} else {
currentUser.status.was_online = 0;
currentUser.status.expires = 0;
}
}
toDbUser.status = update.status;
dbUsersStatus.add(toDbUser);
}
} else if (update instanceof TLRPC.TL_updateUserName) {
if (currentUser != null) {
currentUser.first_name = update.first_name;
currentUser.last_name = update.last_name;
}
toDbUser.first_name = update.first_name;
toDbUser.last_name = update.last_name;
dbUsers.add(toDbUser);
} else if (update instanceof TLRPC.TL_updateUserPhoto) {
if (currentUser != null) {
currentUser.photo = update.photo;
}
avatarsUpdate = true;
toDbUser.photo = update.photo;
dbUsers.add(toDbUser);
}
}
MessagesStorage.Instance.updateUsers(dbUsersStatus, true, true, true);
MessagesStorage.Instance.updateUsers(dbUsers, false, true, true);
}
if (!messages.isEmpty()) {
for (HashMap.Entry<Long, ArrayList<MessageObject>> entry : messages.entrySet()) {
Long key = entry.getKey();
ArrayList<MessageObject> value = entry.getValue();
updateInterfaceWithMessages(key, value);
}
}
if (!markAsReadMessages.isEmpty()) {
for (Integer id : markAsReadMessages) {
MessageObject obj = dialogMessage.get(id);
if (obj != null) {
obj.messageOwner.unread = false;
}
}
NotificationCenter.Instance.postNotificationName(messagesReaded, markAsReadMessages);
}
if (!markAsReadEncrypted.isEmpty()) {
for (HashMap.Entry<Integer, Integer> entry : markAsReadEncrypted.entrySet()) {
NotificationCenter.Instance.postNotificationName(messagesReadedEncrypted, entry.getKey(), entry.getValue());
long dialog_id = (long)(entry.getKey()) << 32;
TLRPC.TL_dialog dialog = dialogs_dict.get(dialog_id);
if (dialog != null) {
MessageObject message = dialogMessage.get(dialog.top_message);
if (message != null) {
message.messageOwner.unread = false;
}
}
}
}
if (!deletedMessages.isEmpty()) {
NotificationCenter.Instance.postNotificationName(messagesDeleted, deletedMessages);
for (Integer id : deletedMessages) {
MessageObject obj = dialogMessage.get(id);
if (obj != null) {
obj.deleted = true;
}
}
}
if (!printChanges.isEmpty()) {
for (Long uid : printChanges) {
NotificationCenter.Instance.postNotificationName(userPrintUpdate, uid);
}
NotificationCenter.Instance.postNotificationName(userPrintUpdateAll);
}
if (!chatInfoToUpdate.isEmpty()) {
for (TLRPC.ChatParticipants info : chatInfoToUpdate) {
MessagesStorage.Instance.updateChatInfo(info.chat_id, info, true);
NotificationCenter.Instance.postNotificationName(chatInfoDidLoaded, info.chat_id, info);
}
}
if (avatarsUpdate || reloadInterfaceForce) {
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_ALL);
} else {
NotificationCenter.Instance.postNotificationName(updateInterfaces, UPDATE_MASK_NAME | UPDATE_MASK_STATUS);
}
if (lastMessageArg != null) {
showInAppNotification(lastMessageArg);
}
}
});
}
if (!markAsReadMessages.isEmpty() || !markAsReadEncrypted.isEmpty()) {
MessagesStorage.Instance.markMessagesAsRead(markAsReadMessages, markAsReadEncrypted, true);
}
if (!deletedMessages.isEmpty()) {
MessagesStorage.Instance.markMessagesAsDeleted(deletedMessages, true);
}
if (!deletedMessages.isEmpty()) {
MessagesStorage.Instance.updateDialogsWithDeletedMessages(deletedMessages, true);
}
if (!markAsReadMessages.isEmpty()) {
MessagesStorage.Instance.updateDialogsWithReadedMessages(markAsReadMessages, true);
}
if (!tasks.isEmpty()) {
for (TLRPC.TL_updateEncryptedMessagesRead update : tasks) {
MessagesStorage.Instance.createTaskForDate(update.chat_id, update.max_date, update.date, 1);
}
}
return true;
}
private boolean updatePrintingUsersWithNewMessages(long uid, ArrayList<MessageObject> messages) {
if (uid > 0) {
ArrayList<PrintingUser> arr = printingUsers.get(uid);
if (arr != null) {
printingUsers.remove(uid);
return true;
}
} else if (uid < 0) {
ArrayList<Integer> messagesUsers = new ArrayList<Integer>();
for (MessageObject message : messages) {
if (!messagesUsers.contains(message.messageOwner.from_id)) {
messagesUsers.add(message.messageOwner.from_id);
}
}
ArrayList<PrintingUser> arr = printingUsers.get(uid);
boolean changed = false;
if (arr != null) {
for (int a = 0; a < arr.size(); a++) {
PrintingUser user = arr.get(a);
if (messagesUsers.contains(user.userId)) {
arr.remove(a);
a--;
if (arr.isEmpty()) {
printingUsers.remove(uid);
}
changed = true;
}
}
}
if (changed) {
return true;
}
}
return false;
}
private void playNotificationSound() {
if (lastSoundPlay > System.currentTimeMillis() - 1800) {
return;
}
try {
lastSoundPlay = System.currentTimeMillis();
soundPool.play(sound, 1, 1, 1, 0, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
private void showInAppNotification(MessageObject messageObject) {
SharedPreferences preferences = Utilities.applicationContext.getSharedPreferences("Notifications", Context.MODE_PRIVATE);
boolean globalEnabled = preferences.getBoolean("EnableAll", true);
if (!globalEnabled) {
return;
}
boolean inAppSounds = preferences.getBoolean("EnableInAppSounds", true);
boolean inAppVibrate = preferences.getBoolean("EnableInAppVibrate", true);
boolean inAppPreview = preferences.getBoolean("EnableInAppPreview", true);
if ((inAppSounds || inAppVibrate || inAppPreview) && ApplicationLoader.lastPauseTime == 0) {
long dialog_id = messageObject.messageOwner.dialog_id;
int user_id = messageObject.messageOwner.from_id;
int chat_id = 0;
if (dialog_id == 0) {
if (messageObject.messageOwner.to_id.chat_id != 0) {
dialog_id = -messageObject.messageOwner.to_id.chat_id;
chat_id = messageObject.messageOwner.to_id.chat_id;
} else if (messageObject.messageOwner.to_id.user_id != 0) {
if (messageObject.messageOwner.to_id.user_id == UserConfig.clientUserId) {
dialog_id = messageObject.messageOwner.from_id;
} else {
dialog_id = messageObject.messageOwner.to_id.user_id;
}
}
} else {
TLRPC.EncryptedChat chat = encryptedChats.get((int)(dialog_id >> 32));
if (chat == null) {
return;
}
}
if (dialog_id == 0) {
return;
}
TLRPC.User user = users.get(user_id);
if (user == null) {
return;
}
TLRPC.Chat chat;
if (chat_id != 0) {
chat = chats.get(chat_id);
if (chat == null) {
return;
}
}
String key = "notify_" + dialog_id;
boolean value = preferences.getBoolean(key, true);
if (!value) {
return;
}
if (inAppPreview) {
NotificationCenter.Instance.postNotificationName(701, messageObject);
}
if (inAppVibrate) {
Vibrator v = (Vibrator)Utilities.applicationContext.getSystemService(Context.VIBRATOR_SERVICE);
v.vibrate(100);
}
if (inAppSounds) {
playNotificationSound();
}
}
}
private void updateInterfaceWithMessages(long uid, ArrayList<MessageObject> messages) {
int unreadCount = 0;
MessageObject lastMessage = null;
int lastDate = 0;
TLRPC.TL_dialog dialog = dialogs_dict.get(uid);
NotificationCenter.Instance.postNotificationName(didReceivedNewMessages, uid, messages);
for (MessageObject message : messages) {
if (message.messageOwner.unread && message.messageOwner.from_id != UserConfig.clientUserId) {
unreadCount++;
}
if (lastMessage == null || message.messageOwner.date > lastDate) {
lastMessage = message;
lastDate = message.messageOwner.date;
}
}
if (dialog == null) {
dialog = new TLRPC.TL_dialog();
dialog.id = uid;
dialog.unread_count = unreadCount;
dialog.top_message = lastMessage.messageOwner.id;
dialog.last_message_date = lastMessage.messageOwner.date;
dialogs_dict.put(uid, dialog);
dialogs.add(dialog);
dialogMessage.put(lastMessage.messageOwner.id, lastMessage);
} else {
dialogMessage.remove(dialog.top_message);
dialog.unread_count += unreadCount;
dialog.top_message = lastMessage.messageOwner.id;
dialog.last_message_date = lastMessage.messageOwner.date;
dialogMessage.put(lastMessage.messageOwner.id, lastMessage);
}
dialogsServerOnly.clear();
Collections.sort(dialogs, new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) {
if (tl_dialog.last_message_date == tl_dialog2.last_message_date) {
return 0;
} else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) {
return 1;
} else {
return -1;
}
}
});
for (TLRPC.TL_dialog d : dialogs) {
if ((int)d.id != 0) {
dialogsServerOnly.add(d);
}
}
}
public TLRPC.Message decryptMessage(TLRPC.EncryptedMessage message) {
TLRPC.EncryptedChat chat = encryptedChats.get(message.chat_id);
if (chat == null) {
Semaphore semaphore = new Semaphore(0);
ArrayList<TLObject> result = new ArrayList<TLObject>();
MessagesStorage.Instance.getEncryptedChat(message.chat_id, semaphore, result);
try {
semaphore.acquire();
} catch (Exception e) {
e.printStackTrace();
}
if (result.size() == 2) {
chat = (TLRPC.EncryptedChat)result.get(0);
TLRPC.User user = (TLRPC.User)result.get(1);
encryptedChats.put(chat.id, chat);
users.putIfAbsent(user.id, user);
}
}
if (chat == null) {
return null;
}
SerializedData is = new SerializedData(message.bytes);
long fingerprint = is.readInt64();
if (chat.key_fingerprint == fingerprint) {
byte[] messageKey = is.readData(16);
MessageKeyData keyData = Utilities.generateMessageKeyData(chat.auth_key, messageKey, false);
byte[] messageData = is.readData(message.bytes.length - 24);
messageData = Utilities.aesIgeEncryption(messageData, keyData.aesKey, keyData.aesIv, false, false);
is = new SerializedData(messageData);
int len = is.readInt32();
TLObject object = TLClassStore.Instance().TLdeserialize(is, is.readInt32());
if (object != null) {
int from_id = chat.admin_id;
if (from_id == UserConfig.clientUserId) {
from_id = chat.participant_id;
}
if (object instanceof TLRPC.TL_decryptedMessage) {
TLRPC.TL_decryptedMessage decryptedMessage = (TLRPC.TL_decryptedMessage)object;
TLRPC.TL_message newMessage = new TLRPC.TL_message();
newMessage.message = decryptedMessage.message;
newMessage.date = message.date;
newMessage.id = UserConfig.getNewMessageId();
newMessage.from_id = from_id;
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.clientUserId;
newMessage.out = false;
newMessage.unread = true;
newMessage.dialog_id = ((long)chat.id) << 32;
newMessage.ttl = chat.ttl;
if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaEmpty) {
newMessage.media = new TLRPC.TL_messageMediaEmpty();
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaContact) {
newMessage.media = new TLRPC.TL_messageMediaContact();
newMessage.media.last_name = decryptedMessage.media.last_name;
newMessage.media.first_name = decryptedMessage.media.first_name;
newMessage.media.phone_number = decryptedMessage.media.phone_number;
newMessage.media.user_id = decryptedMessage.media.user_id;
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaGeoPoint) {
newMessage.media = new TLRPC.TL_messageMediaGeo();
newMessage.media.geo = new TLRPC.TL_geoPoint();
newMessage.media.geo.lat = decryptedMessage.media.lat;
newMessage.media.geo._long = decryptedMessage.media._long;
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaPhoto) {
newMessage.media = new TLRPC.TL_messageMediaPhoto();
newMessage.media.photo = new TLRPC.TL_photo();
newMessage.media.photo.user_id = newMessage.from_id;
newMessage.media.photo.date = newMessage.date;
newMessage.media.photo.caption = "";
newMessage.media.photo.geo = new TLRPC.TL_geoPointEmpty();
TLRPC.TL_photoCachedSize small = new TLRPC.TL_photoCachedSize();
small.w = decryptedMessage.media.thumb_w;
small.h = decryptedMessage.media.thumb_h;
small.bytes = decryptedMessage.media.thumb;
small.type = "s";
small.location = new TLRPC.TL_fileLocationUnavailable();
newMessage.media.photo.sizes.add(small);
TLRPC.TL_photoSize big = new TLRPC.TL_photoSize();
big.w = decryptedMessage.media.w;
big.h = decryptedMessage.media.h;
big.type = "x";
big.size = message.file.size;
big.location = new TLRPC.TL_fileEncryptedLocation();
big.location.key = decryptedMessage.media.key;
big.location.iv = decryptedMessage.media.iv;
big.location.dc_id = message.file.dc_id;
big.location.volume_id = message.file.id;
big.location.secret = message.file.access_hash;
big.location.local_id = message.file.key_fingerprint;
newMessage.media.photo.sizes.add(big);
} else if (decryptedMessage.media instanceof TLRPC.TL_decryptedMessageMediaVideo) {
newMessage.media = new TLRPC.TL_messageMediaVideo();
newMessage.media.video = new TLRPC.TL_videoEncrypted();
newMessage.media.video.thumb = new TLRPC.TL_photoCachedSize();
newMessage.media.video.thumb.bytes = decryptedMessage.media.thumb;
newMessage.media.video.thumb.w = decryptedMessage.media.thumb_w;
newMessage.media.video.thumb.h = decryptedMessage.media.thumb_h;
newMessage.media.video.thumb.type = "s";
newMessage.media.video.thumb.location = new TLRPC.TL_fileLocationUnavailable();
newMessage.media.video.duration = decryptedMessage.media.duration;
newMessage.media.video.dc_id = message.file.dc_id;
newMessage.media.video.w = decryptedMessage.media.w;
newMessage.media.video.h = decryptedMessage.media.h;
newMessage.media.video.date = message.date;
newMessage.media.video.caption = "";
newMessage.media.video.user_id = from_id;
newMessage.media.video.size = message.file.size;
newMessage.media.video.id = message.file.id;
newMessage.media.video.access_hash = message.file.access_hash;
newMessage.media.video.key = decryptedMessage.media.key;
newMessage.media.video.iv = decryptedMessage.media.iv;
} else {
return null;
}
return newMessage;
} else if (object instanceof TLRPC.TL_decryptedMessageService) {
TLRPC.TL_decryptedMessageService serviceMessage = (TLRPC.TL_decryptedMessageService)object;
if (serviceMessage.action instanceof TLRPC.TL_decryptedMessageActionSetMessageTTL) {
TLRPC.TL_messageService newMessage = new TLRPC.TL_messageService();
newMessage.action = new TLRPC.TL_messageActionTTLChange();
newMessage.action.ttl = chat.ttl = serviceMessage.action.ttl_seconds;
newMessage.local_id = newMessage.id = UserConfig.getNewMessageId();
newMessage.unread = true;
newMessage.date = message.date;
newMessage.id = UserConfig.getNewMessageId();
newMessage.from_id = from_id;
newMessage.to_id = new TLRPC.TL_peerUser();
newMessage.to_id.user_id = UserConfig.clientUserId;
newMessage.out = false;
newMessage.dialog_id = ((long)chat.id) << 32;
MessagesStorage.Instance.updateEncryptedChatTTL(chat);
return newMessage;
}
}
}
}
return null;
}
public void processAcceptedSecretChat(final TLRPC.EncryptedChat encryptedChat) {
BigInteger i_authKey = new BigInteger(1, encryptedChat.g_a_or_b);
i_authKey = i_authKey.modPow(new BigInteger(1, encryptedChat.a_or_b), new BigInteger(1, UserConfig.secretPBytes));
byte[] authKey = i_authKey.toByteArray();
if (authKey.length > 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256);
authKey = correctedAuth;
} else if (authKey.length < 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length);
for (int a = 0; a < 256 - authKey.length; a++) {
authKey[a] = 0;
}
authKey = correctedAuth;
}
for (int a = 0; a < 256; a++) {
authKey[a] = (byte)(authKey[a] ^ encryptedChat.nonce[a]);
}
byte[] authKeyHash = Utilities.computeSHA1(authKey);
byte[] authKeyId = new byte[8];
System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8);
long fingerprint = Utilities.bytesToLong(authKeyId);
if (encryptedChat.key_fingerprint == fingerprint) {
encryptedChat.auth_key = authKey;
MessagesStorage.Instance.updateEncryptedChat(encryptedChat);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
encryptedChats.put(encryptedChat.id, encryptedChat);
NotificationCenter.Instance.postNotificationName(encryptedChatUpdated, encryptedChat);
}
});
} else {
final TLRPC.TL_encryptedChatDiscarded newChat = new TLRPC.TL_encryptedChatDiscarded();
newChat.id = encryptedChat.id;
newChat.user_id = encryptedChat.user_id;
newChat.auth_key = encryptedChat.auth_key;
MessagesStorage.Instance.updateEncryptedChat(newChat);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
encryptedChats.put(newChat.id, newChat);
NotificationCenter.Instance.postNotificationName(encryptedChatUpdated, newChat);
}
});
declineSecretChat(encryptedChat.id);
}
}
public void declineSecretChat(int chat_id) {
TLRPC.TL_messages_discardEncryption req = new TLRPC.TL_messages_discardEncryption();
req.chat_id = chat_id;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void acceptSecretChat(final TLRPC.EncryptedChat encryptedChat) {
if (acceptingChats.get(encryptedChat.id) != null) {
return;
}
acceptingChats.put(encryptedChat.id, encryptedChat);
TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig();
req.random_length = 256;
req.version = UserConfig.lastSecretVersion;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig)response;
if (response instanceof TLRPC.TL_messages_dhConfig) {
UserConfig.secretPBytes = res.p;
UserConfig.secretG = res.g;
UserConfig.lastSecretVersion = res.version;
UserConfig.saveConfig();
}
byte[] salt = new byte[256];
for (int a = 0; a < 256; a++) {
salt[a] = (byte)((byte)(random.nextDouble() * 255) ^ res.random[a]);
}
encryptedChat.a_or_b = salt;
BigInteger i_g_b = BigInteger.valueOf(UserConfig.secretG);
i_g_b = i_g_b.modPow(new BigInteger(1, salt), new BigInteger(1, UserConfig.secretPBytes));
byte[] g_b = i_g_b.toByteArray();
if (g_b.length > 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(g_b, 1, correctedAuth, 0, 256);
g_b = correctedAuth;
}
BigInteger i_authKey = new BigInteger(1, encryptedChat.g_a);
i_authKey = i_authKey.modPow(new BigInteger(1, salt), new BigInteger(1, UserConfig.secretPBytes));
byte[] authKey = i_authKey.toByteArray();
if (authKey.length > 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, authKey.length - 256, correctedAuth, 0, 256);
authKey = correctedAuth;
} else if (authKey.length < 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(authKey, 0, correctedAuth, 256 - authKey.length, authKey.length);
for (int a = 0; a < 256 - authKey.length; a++) {
authKey[a] = 0;
}
authKey = correctedAuth;
}
for (int a = 0; a < 256; a++) {
authKey[a] = (byte)(authKey[a] ^ encryptedChat.nonce[a]);
}
byte[] authKeyHash = Utilities.computeSHA1(authKey);
byte[] authKeyId = new byte[8];
System.arraycopy(authKeyHash, authKeyHash.length - 8, authKeyId, 0, 8);
encryptedChat.auth_key = authKey;
TLRPC.TL_messages_acceptEncryption req2 = new TLRPC.TL_messages_acceptEncryption();
req2.g_b = g_b;
req2.peer = new TLRPC.TL_inputEncryptedChat();
req2.peer.chat_id = encryptedChat.id;
req2.peer.access_hash = encryptedChat.access_hash;
req2.key_fingerprint = Utilities.bytesToLong(authKeyId);
ConnectionsManager.Instance.performRpc(req2, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
acceptingChats.remove(encryptedChat.id);
if (error == null) {
final TLRPC.EncryptedChat newChat = (TLRPC.EncryptedChat)response;
newChat.auth_key = encryptedChat.auth_key;
newChat.user_id = encryptedChat.user_id;
MessagesStorage.Instance.updateEncryptedChat(newChat);
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
encryptedChats.put(newChat.id, newChat);
NotificationCenter.Instance.postNotificationName(encryptedChatUpdated, newChat);
}
});
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
} else {
acceptingChats.remove(encryptedChat.id);
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric);
}
public void startSecretChat(final Context context, final int user_id) {
final ProgressDialog progressDialog = new ProgressDialog(context);
progressDialog.setMessage(context.getString(R.string.Loading));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
progressDialog.show();
TLRPC.TL_messages_getDhConfig req = new TLRPC.TL_messages_getDhConfig();
req.random_length = 256;
req.version = UserConfig.lastSecretVersion;
ConnectionsManager.Instance.performRpc(req, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(TLObject response, TLRPC.TL_error error) {
if (error == null) {
TLRPC.messages_DhConfig res = (TLRPC.messages_DhConfig)response;
if (response instanceof TLRPC.TL_messages_dhConfig) {
UserConfig.secretPBytes = res.p;
UserConfig.secretG = res.g;
UserConfig.lastSecretVersion = res.version;
UserConfig.saveConfig();
}
final byte[] salt = new byte[256];
for (int a = 0; a < 256; a++) {
salt[a] = (byte)((byte)(random.nextDouble() * 255) ^ res.random[a]);
}
BigInteger i_g_a = BigInteger.valueOf(UserConfig.secretG);
i_g_a = i_g_a.modPow(new BigInteger(1, salt), new BigInteger(1, UserConfig.secretPBytes));
byte[] g_a = i_g_a.toByteArray();
if (g_a.length > 256) {
byte[] correctedAuth = new byte[256];
System.arraycopy(g_a, 1, correctedAuth, 0, 256);
g_a = correctedAuth;
}
final TLRPC.User user = MessagesController.Instance.users.get(user_id);
TLRPC.InputUser inputUser;
if (user instanceof TLRPC.TL_userForeign || user instanceof TLRPC.TL_userRequest) {
inputUser = new TLRPC.TL_inputUserForeign();
inputUser.user_id = user.id;
inputUser.access_hash = user.access_hash;
} else {
inputUser = new TLRPC.TL_inputUserContact();
inputUser.user_id = user.id;
}
TLRPC.TL_messages_requestEncryption req2 = new TLRPC.TL_messages_requestEncryption();
req2.g_a = g_a;
req2.user_id = inputUser;
req2.random_id = (int)(random.nextDouble() * Integer.MAX_VALUE);
ConnectionsManager.Instance.performRpc(req2, new RPCRequest.RPCRequestDelegate() {
@Override
public void run(final TLObject response, TLRPC.TL_error error) {
if (error == null) {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (!((SherlockFragmentActivity)context).isFinishing()) {
progressDialog.dismiss();
}
TLRPC.EncryptedChat chat = (TLRPC.EncryptedChat)response;
chat.user_id = chat.participant_id;
encryptedChats.put(chat.id, chat);
chat.a_or_b = salt;
TLRPC.TL_dialog dialog = new TLRPC.TL_dialog();
dialog.id = ((long)chat.id) << 32;
dialog.unread_count = 0;
dialog.top_message = 0;
dialog.last_message_date = ConnectionsManager.Instance.getCurrentTime();
dialogs_dict.put(dialog.id, dialog);
dialogs.add(dialog);
dialogsServerOnly.clear();
Collections.sort(dialogs, new Comparator<TLRPC.TL_dialog>() {
@Override
public int compare(TLRPC.TL_dialog tl_dialog, TLRPC.TL_dialog tl_dialog2) {
if (tl_dialog.last_message_date == tl_dialog2.last_message_date) {
return 0;
} else if (tl_dialog.last_message_date < tl_dialog2.last_message_date) {
return 1;
} else {
return -1;
}
}
});
for (TLRPC.TL_dialog d : dialogs) {
if ((int)d.id != 0) {
dialogsServerOnly.add(d);
}
}
NotificationCenter.Instance.postNotificationName(dialogsNeedReload);
MessagesStorage.Instance.putEncryptedChat(chat, user, dialog);
NotificationCenter.Instance.postNotificationName(encryptedChatCreated, chat);
}
});
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (!((SherlockFragmentActivity)context).isFinishing()) {
progressDialog.dismiss();
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.AppName));
builder.setMessage(String.format(context.getString(R.string.CreateEncryptedChatOutdatedError), user.first_name, user.first_name));
builder.setPositiveButton(Utilities.applicationContext.getString(R.string.OK), null);
builder.show().setCanceledOnTouchOutside(true);
}
}
});
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
} else {
Utilities.RunOnUIThread(new Runnable() {
@Override
public void run() {
if (!((SherlockFragmentActivity)context).isFinishing()) {
progressDialog.dismiss();
}
}
});
}
}
}, null, true, RPCRequest.RPCRequestClassGeneric | RPCRequest.RPCRequestClassFailOnServerErrors);
}
}