mirror of https://github.com/NekoX-Dev/NekoX.git
398 lines
20 KiB
Java
398 lines
20 KiB
Java
/*
|
|
* This is the source code of Telegram for Android v. 2.0.x.
|
|
* 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-2014.
|
|
*/
|
|
|
|
package org.telegram.android.query;
|
|
|
|
import org.telegram.SQLite.SQLiteCursor;
|
|
import org.telegram.SQLite.SQLitePreparedStatement;
|
|
import org.telegram.android.AndroidUtilities;
|
|
import org.telegram.android.ImageLoader;
|
|
import org.telegram.android.MessageObject;
|
|
import org.telegram.android.MessagesController;
|
|
import org.telegram.android.MessagesStorage;
|
|
import org.telegram.android.NotificationCenter;
|
|
import org.telegram.messenger.ByteBufferDesc;
|
|
import org.telegram.messenger.ConnectionsManager;
|
|
import org.telegram.messenger.FileLog;
|
|
import org.telegram.messenger.RPCRequest;
|
|
import org.telegram.messenger.TLObject;
|
|
import org.telegram.messenger.TLRPC;
|
|
|
|
import java.util.ArrayList;
|
|
import java.util.HashMap;
|
|
import java.util.Locale;
|
|
|
|
public class SharedMediaQuery {
|
|
|
|
public final static int MEDIA_PHOTOVIDEO = 0;
|
|
public final static int MEDIA_FILE = 1;
|
|
public final static int MEDIA_AUDIO = 2;
|
|
|
|
public static void loadMedia(final long uid, final int offset, final int count, final int max_id, final int type, final boolean fromCache, final int classGuid) {
|
|
int lower_part = (int)uid;
|
|
if (fromCache || lower_part == 0) {
|
|
loadMediaDatabase(uid, offset, count, max_id, type, classGuid);
|
|
} else {
|
|
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
|
|
req.offset = offset;
|
|
req.limit = count;
|
|
req.max_id = max_id;
|
|
if (type == MEDIA_PHOTOVIDEO) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
|
|
} else if (type == MEDIA_FILE) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterDocument();
|
|
} else if (type == MEDIA_AUDIO) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterAudio();
|
|
}
|
|
req.q = "";
|
|
if (uid < 0) {
|
|
req.peer = new TLRPC.TL_inputPeerChat();
|
|
req.peer.chat_id = -lower_part;
|
|
} else {
|
|
TLRPC.User user = MessagesController.getInstance().getUser(lower_part);
|
|
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.getInstance().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, type, false, classGuid);
|
|
}
|
|
}
|
|
});
|
|
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
|
|
}
|
|
}
|
|
|
|
public static void getMediaCount(final long uid, final int type, final int classGuid, boolean fromCache) {
|
|
int lower_part = (int)uid;
|
|
if (fromCache || lower_part == 0) {
|
|
getMediaCountDatabase(uid, type, classGuid);
|
|
} else {
|
|
TLRPC.TL_messages_search req = new TLRPC.TL_messages_search();
|
|
req.offset = 0;
|
|
req.limit = 1;
|
|
req.max_id = 0;
|
|
if (type == MEDIA_PHOTOVIDEO) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterPhotoVideo();
|
|
} else if (type == MEDIA_FILE) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterDocument();
|
|
} else if (type == MEDIA_AUDIO) {
|
|
req.filter = new TLRPC.TL_inputMessagesFilterAudio();
|
|
}
|
|
req.q = "";
|
|
if (uid < 0) {
|
|
req.peer = new TLRPC.TL_inputPeerChat();
|
|
req.peer.chat_id = -lower_part;
|
|
} else {
|
|
TLRPC.User user = MessagesController.getInstance().getUser(lower_part);
|
|
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.getInstance().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;
|
|
MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
MessagesController.getInstance().putUsers(res.users, false);
|
|
MessagesController.getInstance().putChats(res.chats, false);
|
|
}
|
|
});
|
|
|
|
if (res instanceof TLRPC.TL_messages_messagesSlice) {
|
|
processLoadedMediaCount(res.count, uid, type, classGuid, false);
|
|
} else {
|
|
processLoadedMediaCount(res.messages.size(), uid, type, classGuid, false);
|
|
}
|
|
}
|
|
}
|
|
});
|
|
ConnectionsManager.getInstance().bindRequestToGuid(reqId, classGuid);
|
|
}
|
|
}
|
|
|
|
public static int getMediaType(TLRPC.Message message) {
|
|
if (message == null) {
|
|
return -1;
|
|
}
|
|
if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaVideo) {
|
|
return SharedMediaQuery.MEDIA_PHOTOVIDEO;
|
|
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
|
if (MessageObject.isStickerMessage(message)) {
|
|
return -1;
|
|
} else {
|
|
return SharedMediaQuery.MEDIA_FILE;
|
|
}
|
|
} else if (message.media instanceof TLRPC.TL_messageMediaAudio) {
|
|
return SharedMediaQuery.MEDIA_AUDIO;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
public static boolean canAddMessageToMedia(TLRPC.Message message) {
|
|
if (message instanceof TLRPC.TL_message_secret && message.media instanceof TLRPC.TL_messageMediaPhoto && message.ttl != 0 && message.ttl <= 60) {
|
|
return false;
|
|
} else if (message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaVideo || message.media instanceof TLRPC.TL_messageMediaDocument || message.media instanceof TLRPC.TL_messageMediaAudio) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
private static void processLoadedMedia(final TLRPC.messages_Messages res, final long uid, int offset, int count, int max_id, final int type, 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, type, false, classGuid);
|
|
} else {
|
|
if (!fromCache) {
|
|
ImageLoader.saveMessagesThumbs(res.messages);
|
|
MessagesStorage.getInstance().putUsersAndChats(res.users, res.chats, true, true);
|
|
putMediaDatabase(uid, type, res.messages);
|
|
}
|
|
|
|
final HashMap<Integer, TLRPC.User> usersLocal = new HashMap<>();
|
|
for (TLRPC.User u : res.users) {
|
|
usersLocal.put(u.id, u);
|
|
}
|
|
final ArrayList<MessageObject> objects = new ArrayList<>();
|
|
for (TLRPC.Message message : res.messages) {
|
|
objects.add(new MessageObject(message, usersLocal, true));
|
|
}
|
|
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
int totalCount;
|
|
if (res instanceof TLRPC.TL_messages_messagesSlice) {
|
|
totalCount = res.count;
|
|
} else {
|
|
totalCount = res.messages.size();
|
|
}
|
|
MessagesController.getInstance().putUsers(res.users, fromCache);
|
|
MessagesController.getInstance().putChats(res.chats, fromCache);
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaDidLoaded, uid, totalCount, objects, fromCache, classGuid, type);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
private static void processLoadedMediaCount(final int count, final long uid, final int type, final int classGuid, final boolean fromCache) {
|
|
AndroidUtilities.runOnUIThread(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
int lower_part = (int)uid;
|
|
if (fromCache && count == -1 && lower_part != 0) {
|
|
getMediaCount(uid, type, classGuid, false);
|
|
} else {
|
|
if (!fromCache) {
|
|
putMediaCountDatabase(uid, type, count);
|
|
}
|
|
NotificationCenter.getInstance().postNotificationName(NotificationCenter.mediaCountDidLoaded, uid, (fromCache && count == -1 ? 0 : count), fromCache, type);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void putMediaCountDatabase(final long uid, final int type, final int count) {
|
|
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
SQLitePreparedStatement state2 = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO media_counts_v2 VALUES(?, ?, ?)");
|
|
state2.requery();
|
|
state2.bindLong(1, uid);
|
|
state2.bindInteger(2, type);
|
|
state2.bindInteger(3, count);
|
|
state2.step();
|
|
state2.dispose();
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void getMediaCountDatabase(final long uid, final int type, final int classGuid) {
|
|
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
try {
|
|
int count = -1;
|
|
SQLiteCursor cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT count FROM media_counts_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type));
|
|
if (cursor.next()) {
|
|
count = cursor.intValue(0);
|
|
}
|
|
cursor.dispose();
|
|
int lower_part = (int)uid;
|
|
if (count == -1 && lower_part == 0) {
|
|
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT COUNT(mid) FROM media_v2 WHERE uid = %d AND type = %d LIMIT 1", uid, type));
|
|
if (cursor.next()) {
|
|
count = cursor.intValue(0);
|
|
}
|
|
cursor.dispose();
|
|
|
|
/*cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, send_state, date FROM messages WHERE uid = %d ORDER BY mid ASC LIMIT %d", uid, 1000));
|
|
ArrayList<TLRPC.Message> photos = new ArrayList<>();
|
|
ArrayList<TLRPC.Message> docs = new ArrayList<>();
|
|
while (cursor.next()) {
|
|
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(1));
|
|
if (data != null && cursor.byteBufferValue(1, data.buffer) != 0) {
|
|
TLRPC.Message message = (TLRPC.Message) TLClassStore.Instance().TLdeserialize(data, data.readInt32());
|
|
MessageObject.setIsUnread(message, cursor.intValue(0) != 1);
|
|
message.date = cursor.intValue(2);
|
|
message.send_state = cursor.intValue(1);
|
|
message.dialog_id = uid;
|
|
if (message.ttl > 60 && message.media instanceof TLRPC.TL_messageMediaPhoto || message.media instanceof TLRPC.TL_messageMediaVideo) {
|
|
photos.add(message);
|
|
} else if (message.media instanceof TLRPC.TL_messageMediaDocument) {
|
|
docs.add(message);
|
|
}
|
|
}
|
|
MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data);
|
|
}
|
|
cursor.dispose();
|
|
if (!photos.isEmpty() || !docs.isEmpty()) {
|
|
MessagesStorage.getInstance().getDatabase().beginTransaction();
|
|
if (!photos.isEmpty()) {
|
|
putMediaDatabaseInternal(uid, MEDIA_PHOTOVIDEO, photos);
|
|
}
|
|
if (docs.isEmpty()) {
|
|
putMediaDatabaseInternal(uid, MEDIA_FILE, docs);
|
|
}
|
|
MessagesStorage.getInstance().getDatabase().commitTransaction();
|
|
}*/
|
|
|
|
if (count != -1) {
|
|
putMediaCountDatabase(uid, type, count);
|
|
}
|
|
}
|
|
processLoadedMediaCount(count, uid, type, classGuid, true);
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void loadMediaDatabase(final long uid, final int offset, final int count, final int max_id, final int type, final int classGuid) {
|
|
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
TLRPC.TL_messages_messages res = new TLRPC.TL_messages_messages();
|
|
try {
|
|
ArrayList<Integer> loadedUsers = new ArrayList<>();
|
|
ArrayList<Integer> fromUser = new ArrayList<>();
|
|
|
|
SQLiteCursor cursor;
|
|
|
|
if ((int)uid != 0) {
|
|
if (max_id != 0) {
|
|
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND mid < %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d", uid, max_id, type, count));
|
|
} else {
|
|
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT data, mid FROM media_v2 WHERE uid = %d AND type = %d ORDER BY date DESC, mid DESC LIMIT %d,%d", uid, type, offset, count));
|
|
}
|
|
} else {
|
|
if (max_id != 0) {
|
|
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v2 as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND type = %d ORDER BY m.mid ASC LIMIT %d", uid, max_id, type, count));
|
|
} else {
|
|
cursor = MessagesStorage.getInstance().getDatabase().queryFinalized(String.format(Locale.US, "SELECT m.data, m.mid, r.random_id FROM media_v2 as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND type = %d ORDER BY m.mid ASC LIMIT %d,%d", uid, type, offset, count));
|
|
}
|
|
}
|
|
|
|
while (cursor.next()) {
|
|
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(cursor.byteArrayLength(0));
|
|
if (data != null && cursor.byteBufferValue(0, data.buffer) != 0) {
|
|
TLRPC.Message message = TLRPC.Message.TLdeserialize(data, data.readInt32(false), false);
|
|
message.id = cursor.intValue(1);
|
|
message.dialog_id = uid;
|
|
if ((int)uid == 0) {
|
|
message.random_id = cursor.longValue(2);
|
|
}
|
|
res.messages.add(message);
|
|
fromUser.add(message.from_id);
|
|
}
|
|
MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data);
|
|
}
|
|
cursor.dispose();
|
|
|
|
StringBuilder usersToLoad = new StringBuilder();
|
|
for (int uid : fromUser) {
|
|
if (!loadedUsers.contains(uid)) {
|
|
if (usersToLoad.length() != 0) {
|
|
usersToLoad.append(",");
|
|
}
|
|
usersToLoad.append(uid);
|
|
loadedUsers.add(uid);
|
|
}
|
|
}
|
|
if (usersToLoad.length() != 0) {
|
|
MessagesStorage.getInstance().getUsersInternal(usersToLoad.toString(), res.users);
|
|
}
|
|
} catch (Exception e) {
|
|
res.messages.clear();
|
|
res.chats.clear();
|
|
res.users.clear();
|
|
FileLog.e("tmessages", e);
|
|
} finally {
|
|
processLoadedMedia(res, uid, offset, count, max_id, type, true, classGuid);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
private static void putMediaDatabaseInternal(final long uid, final int type, final ArrayList<TLRPC.Message> messages) {
|
|
try {
|
|
MessagesStorage.getInstance().getDatabase().beginTransaction();
|
|
SQLitePreparedStatement state2 = MessagesStorage.getInstance().getDatabase().executeFast("REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?)");
|
|
for (TLRPC.Message message : messages) {
|
|
if (canAddMessageToMedia(message)) {
|
|
state2.requery();
|
|
ByteBufferDesc data = MessagesStorage.getInstance().getBuffersStorage().getFreeBuffer(message.getObjectSize());
|
|
message.serializeToStream(data);
|
|
state2.bindInteger(1, message.id);
|
|
state2.bindLong(2, uid);
|
|
state2.bindInteger(3, message.date);
|
|
state2.bindInteger(4, type);
|
|
state2.bindByteBuffer(5, data.buffer);
|
|
state2.step();
|
|
MessagesStorage.getInstance().getBuffersStorage().reuseFreeBuffer(data);
|
|
}
|
|
}
|
|
state2.dispose();
|
|
MessagesStorage.getInstance().getDatabase().commitTransaction();
|
|
} catch (Exception e) {
|
|
FileLog.e("tmessages", e);
|
|
}
|
|
}
|
|
|
|
private static void putMediaDatabase(final long uid, final int type, final ArrayList<TLRPC.Message> messages) {
|
|
MessagesStorage.getInstance().getStorageQueue().postRunnable(new Runnable() {
|
|
@Override
|
|
public void run() {
|
|
putMediaDatabaseInternal(uid, type, messages);
|
|
}
|
|
});
|
|
}
|
|
}
|