2013-10-25 17:19:00 +02:00
/ *
2015-10-29 18:10:07 +01:00
* This is the source code of Telegram for Android v . 3 . x . x .
2013-10-25 17:19:00 +02:00
* It is licensed under GNU GPL v . 2 or later .
* You should have received a copy of the license in this archive ( see LICENSE ) .
*
2017-03-31 01:58:05 +02:00
* Copyright Nikolai Kudashov , 2013 - 2017 .
2013-10-25 17:19:00 +02:00
* /
2015-09-24 22:52:02 +02:00
package org.telegram.messenger ;
2013-10-25 17:19:00 +02:00
2014-08-22 16:24:33 +02:00
import android.content.Context ;
import android.content.SharedPreferences ;
2014-10-08 22:22:22 +02:00
import android.text.TextUtils ;
2013-10-25 17:19:00 +02:00
import android.util.SparseArray ;
2015-09-24 22:52:02 +02:00
import android.util.SparseIntArray ;
2013-10-25 17:19:00 +02:00
2014-02-28 23:28:25 +01:00
import org.telegram.PhoneFormat.PhoneFormat ;
2013-10-25 17:19:00 +02:00
import org.telegram.SQLite.SQLiteCursor ;
import org.telegram.SQLite.SQLiteDatabase ;
import org.telegram.SQLite.SQLitePreparedStatement ;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.query.BotQuery ;
2016-03-16 13:26:32 +01:00
import org.telegram.messenger.query.MessagesQuery ;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.query.SharedMediaQuery ;
import org.telegram.tgnet.ConnectionsManager ;
import org.telegram.tgnet.NativeByteBuffer ;
2017-03-31 01:58:05 +02:00
import org.telegram.tgnet.RequestDelegate ;
2015-09-24 22:52:02 +02:00
import org.telegram.tgnet.TLObject ;
import org.telegram.tgnet.TLRPC ;
2013-10-25 17:19:00 +02:00
import java.io.File ;
import java.util.ArrayList ;
2014-08-29 23:06:04 +02:00
import java.util.Collections ;
2014-09-14 01:40:36 +02:00
import java.util.Comparator ;
2013-10-25 17:19:00 +02:00
import java.util.HashMap ;
import java.util.Locale ;
2014-08-22 16:24:33 +02:00
import java.util.Map ;
2013-10-25 17:19:00 +02:00
import java.util.concurrent.Semaphore ;
2016-06-24 12:27:15 +02:00
import java.util.concurrent.atomic.AtomicLong ;
2013-10-25 17:19:00 +02:00
public class MessagesStorage {
2014-10-31 20:02:29 +01:00
private DispatchQueue storageQueue = new DispatchQueue ( " storageQueue " ) ;
2013-10-25 17:19:00 +02:00
private SQLiteDatabase database ;
private File cacheFile ;
2016-06-24 12:27:15 +02:00
private AtomicLong lastTaskId = new AtomicLong ( System . currentTimeMillis ( ) ) ;
2013-11-04 13:31:01 +01:00
public static int lastDateValue = 0 ;
public static int lastPtsValue = 0 ;
public static int lastQtsValue = 0 ;
public static int lastSeqValue = 0 ;
public static int lastSecretVersion = 0 ;
public static byte [ ] secretPBytes = null ;
public static int secretG = 0 ;
2013-10-25 17:19:00 +02:00
2014-06-13 17:03:06 +02:00
private int lastSavedSeq = 0 ;
private int lastSavedPts = 0 ;
private int lastSavedDate = 0 ;
private int lastSavedQts = 0 ;
2014-03-22 23:31:55 +01:00
private static volatile MessagesStorage Instance = null ;
2016-06-24 12:27:15 +02:00
2014-03-22 23:31:55 +01:00
public static MessagesStorage getInstance ( ) {
MessagesStorage localInstance = Instance ;
if ( localInstance = = null ) {
synchronized ( MessagesStorage . class ) {
localInstance = Instance ;
if ( localInstance = = null ) {
Instance = localInstance = new MessagesStorage ( ) ;
}
}
}
return localInstance ;
}
2013-10-25 17:19:00 +02:00
public MessagesStorage ( ) {
storageQueue . setPriority ( Thread . MAX_PRIORITY ) ;
2017-03-31 01:58:05 +02:00
openDatabase ( true ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-31 20:02:29 +01:00
public SQLiteDatabase getDatabase ( ) {
return database ;
}
public DispatchQueue getStorageQueue ( ) {
return storageQueue ;
}
2017-03-31 01:58:05 +02:00
public void openDatabase ( boolean first ) {
2015-10-29 18:10:07 +01:00
cacheFile = new File ( ApplicationLoader . getFilesDirFixed ( ) , " cache4.db " ) ;
2013-12-26 17:46:13 +01:00
2013-10-25 17:19:00 +02:00
boolean createTable = false ;
//cacheFile.delete();
if ( ! cacheFile . exists ( ) ) {
createTable = true ;
}
try {
database = new SQLiteDatabase ( cacheFile . getPath ( ) ) ;
2014-03-04 07:23:08 +01:00
database . executeFast ( " PRAGMA secure_delete = ON " ) . stepThis ( ) . dispose ( ) ;
2014-03-22 23:31:55 +01:00
database . executeFast ( " PRAGMA temp_store = 1 " ) . stepThis ( ) . dispose ( ) ;
2013-10-25 17:19:00 +02:00
if ( createTable ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( " create new database " ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE messages_holes(uid INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, start)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_end_messages_holes ON messages_holes(uid, end); " ) . stepThis ( ) . dispose ( ) ;
2014-06-20 02:18:13 +02:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE media_holes_v2(uid INTEGER, type INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, type, start)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_end_media_holes_v2 ON media_holes_v2(uid, type, end); " ) . stepThis ( ) . dispose ( ) ;
2015-08-13 11:23:31 +02:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE messages(mid INTEGER PRIMARY KEY, uid INTEGER, read_state INTEGER, send_state INTEGER, date INTEGER, data BLOB, out INTEGER, ttl INTEGER, media INTEGER, replydata BLOB, imp INTEGER) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_mid_idx_messages ON messages(uid, mid); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1; " ) . stepThis ( ) . dispose ( ) ;
2014-11-18 06:01:04 +01:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, PRIMARY KEY (uid, type)); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS type_date_idx_download_queue ON download_queue(type, date); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE user_phones_v6(uid INTEGER, phone TEXT, sphone TEXT, deleted INTEGER, PRIMARY KEY (uid, phone)) " ) . stepThis ( ) . dispose ( ) ;
2014-02-04 19:36:55 +01:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS sphone_deleted_idx_user_phones ON user_phones_v6(sphone, deleted); " ) . stepThis ( ) . dispose ( ) ;
2017-03-31 01:58:05 +02:00
database . executeFast ( " CREATE TABLE dialogs(did INTEGER PRIMARY KEY, date INTEGER, unread_count INTEGER, last_mid INTEGER, inbox_max INTEGER, outbox_max INTEGER, last_mid_i INTEGER, unread_count_i INTEGER, pts INTEGER, date_i INTEGER, pinned INTEGER) " ) . stepThis ( ) . dispose ( ) ;
2013-10-25 17:19:00 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS date_idx_dialogs ON dialogs(date); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS last_mid_idx_dialogs ON dialogs(last_mid); " ) . stepThis ( ) . dispose ( ) ;
2014-08-30 21:30:42 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS unread_count_idx_dialogs ON dialogs(unread_count); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS last_mid_i_idx_dialogs ON dialogs(last_mid_i); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS unread_count_i_idx_dialogs ON dialogs(unread_count_i); " ) . stepThis ( ) . dispose ( ) ;
2013-12-20 20:25:49 +01:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE randoms(random_id INTEGER, mid INTEGER, PRIMARY KEY (random_id, mid)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS mid_idx_randoms ON randoms(mid); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE enc_tasks_v2(mid INTEGER PRIMARY KEY, date INTEGER) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS date_idx_enc_tasks_v2 ON enc_tasks_v2(date); " ) . stepThis ( ) . dispose ( ) ;
2014-10-22 22:01:07 +02:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE messages_seq(mid INTEGER PRIMARY KEY, seq_in INTEGER, seq_out INTEGER); " ) . stepThis ( ) . dispose ( ) ;
2014-10-22 22:01:07 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS seq_idx_messages_seq ON messages_seq(seq_in, seq_out); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL) " ) . stepThis ( ) . dispose ( ) ;
2015-02-01 19:51:02 +01:00
database . executeFast ( " CREATE TABLE media_v2(mid INTEGER PRIMARY KEY, uid INTEGER, date INTEGER, type INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media ON media_v2(uid, mid, type, date); " ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
database . executeFast ( " CREATE TABLE bot_keyboard(uid INTEGER PRIMARY KEY, mid INTEGER, info BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS bot_keyboard_idx_mid ON bot_keyboard(mid); " ) . stepThis ( ) . dispose ( ) ;
2016-03-16 13:26:32 +01:00
database . executeFast ( " CREATE TABLE chat_settings_v2(uid INTEGER PRIMARY KEY, info BLOB, pinned INTEGER) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_settings_pinned_idx ON chat_settings_v2(uid, pinned) WHERE pinned != 0; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE chat_pinned(uid INTEGER PRIMARY KEY, pinned INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_pinned_mid_idx ON chat_pinned(uid, pinned) WHERE pinned != 0; " ) . stepThis ( ) . dispose ( ) ;
2016-05-25 23:49:47 +02:00
database . executeFast ( " CREATE TABLE chat_hints(did INTEGER, type INTEGER, rating REAL, date INTEGER, PRIMARY KEY(did, type)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_hints_rating_idx ON chat_hints(rating); " ) . stepThis ( ) . dispose ( ) ;
2017-03-31 01:58:05 +02:00
database . executeFast ( " CREATE TABLE botcache(id TEXT PRIMARY KEY, date INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS botcache_date_idx ON botcache(date); " ) . stepThis ( ) . dispose ( ) ;
2016-03-16 13:26:32 +01:00
database . executeFast ( " CREATE TABLE users_data(uid INTEGER PRIMARY KEY, about TEXT) " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE users(uid INTEGER PRIMARY KEY, name TEXT, status INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE chats(uid INTEGER PRIMARY KEY, name TEXT, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
2017-03-31 01:58:05 +02:00
database . executeFast ( " CREATE TABLE enc_chats(uid INTEGER PRIMARY KEY, user INTEGER, name TEXT, data BLOB, g BLOB, authkey BLOB, ttl INTEGER, layer INTEGER, seq_in INTEGER, seq_out INTEGER, use_count INTEGER, exchange_id INTEGER, key_date INTEGER, fprint INTEGER, fauthkey BLOB, khash BLOB, in_seq_no INTEGER, admin_id INTEGER) " ) . stepThis ( ) . dispose ( ) ;
2015-11-26 22:04:02 +01:00
database . executeFast ( " CREATE TABLE channel_users_v2(did INTEGER, uid INTEGER, date INTEGER, data BLOB, PRIMARY KEY(did, uid)) " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE contacts(uid INTEGER PRIMARY KEY, mutual INTEGER) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE wallpapers(uid INTEGER PRIMARY KEY, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE blocked_users(uid INTEGER PRIMARY KEY) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE dialog_settings(did INTEGER PRIMARY KEY, flags INTEGER); " ) . stepThis ( ) . dispose ( ) ;
2016-01-11 18:19:48 +01:00
database . executeFast ( " CREATE TABLE web_recent_v3(id TEXT, type INTEGER, image_url TEXT, thumb_url TEXT, local_url TEXT, width INTEGER, height INTEGER, size INTEGER, date INTEGER, document BLOB, PRIMARY KEY (id, type)); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE stickers_v2(id INTEGER PRIMARY KEY, data BLOB, date INTEGER, hash TEXT); " ) . stepThis ( ) . dispose ( ) ;
2016-10-11 13:57:01 +02:00
database . executeFast ( " CREATE TABLE stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash TEXT); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " CREATE TABLE hashtag_recent_v2(id TEXT PRIMARY KEY, date INTEGER); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE webpage_pending(id INTEGER, mid INTEGER, PRIMARY KEY (id, mid)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE user_contacts_v6(uid INTEGER PRIMARY KEY, fname TEXT, sname TEXT) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE sent_files_v2(uid TEXT, type INTEGER, data BLOB, PRIMARY KEY (uid, type)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE search_recent(did INTEGER PRIMARY KEY, date INTEGER); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE media_counts_v2(uid INTEGER, type INTEGER, count INTEGER, PRIMARY KEY(uid, type)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE keyvalue(id TEXT PRIMARY KEY, value TEXT) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE bot_info(uid INTEGER PRIMARY KEY, info BLOB) " ) . stepThis ( ) . dispose ( ) ;
2016-06-24 12:27:15 +02:00
database . executeFast ( " CREATE TABLE pending_tasks(id INTEGER PRIMARY KEY, data BLOB); " ) . stepThis ( ) . dispose ( ) ;
2016-10-11 13:57:01 +02:00
database . executeFast ( " CREATE TABLE requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end)); " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
2015-02-01 19:51:02 +01:00
//version
2017-03-31 01:58:05 +02:00
database . executeFast ( " PRAGMA user_version = 41 " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
//database.executeFast("CREATE TABLE secret_holes(uid INTEGER, seq_in INTEGER, seq_out INTEGER, data BLOB, PRIMARY KEY (uid, seq_in, seq_out));").stepThis().dispose();
//database.executeFast("CREATE TABLE attach_data(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id))").stepThis().dispose();
2013-11-04 13:31:01 +01:00
} else {
2017-03-31 01:58:05 +02:00
int version = database . executeInt ( " PRAGMA user_version " ) ;
FileLog . e ( " current db version = " + version ) ;
if ( version = = 0 ) {
throw new Exception ( " malformed " ) ;
}
2014-08-27 00:26:25 +02:00
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT seq, pts, date, qts, lsv, sg, pbytes FROM params WHERE id = 1 " ) ;
2014-08-22 16:24:33 +02:00
if ( cursor . next ( ) ) {
2014-08-27 00:26:25 +02:00
lastSeqValue = cursor . intValue ( 0 ) ;
lastPtsValue = cursor . intValue ( 1 ) ;
lastDateValue = cursor . intValue ( 2 ) ;
lastQtsValue = cursor . intValue ( 3 ) ;
lastSecretVersion = cursor . intValue ( 4 ) ;
secretG = cursor . intValue ( 5 ) ;
if ( cursor . isNull ( 6 ) ) {
secretPBytes = null ;
} else {
secretPBytes = cursor . byteArrayValue ( 6 ) ;
if ( secretPBytes ! = null & & secretPBytes . length = = 1 ) {
secretPBytes = null ;
}
2014-08-22 16:24:33 +02:00
}
2013-11-04 13:31:01 +01:00
}
2014-08-22 16:24:33 +02:00
cursor . dispose ( ) ;
2014-08-27 00:26:25 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-27 00:26:25 +02:00
try {
database . executeFast ( " CREATE TABLE IF NOT EXISTS params(id INTEGER PRIMARY KEY, seq INTEGER, pts INTEGER, date INTEGER, qts INTEGER, lsv INTEGER, sg INTEGER, pbytes BLOB) " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
database . executeFast ( " INSERT INTO params VALUES(1, 0, 0, 0, 0, 0, 0, NULL) " ) . stepThis ( ) . dispose ( ) ;
2014-08-27 00:26:25 +02:00
} catch ( Exception e2 ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e2 ) ;
2014-08-22 16:24:33 +02:00
}
2014-08-27 00:26:25 +02:00
}
2017-03-31 01:58:05 +02:00
if ( version < 41 ) {
2014-10-08 22:22:22 +02:00
updateDbToLastVersion ( version ) ;
2014-08-27 00:26:25 +02:00
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
if ( first & & e . getMessage ( ) . contains ( " malformed " ) ) {
cleanupInternal ( ) ;
openDatabase ( false ) ;
}
2014-08-27 00:26:25 +02:00
}
2014-08-29 23:06:04 +02:00
loadUnreadMessages ( ) ;
2016-06-24 12:27:15 +02:00
loadPendingTasks ( ) ;
2014-08-27 00:26:25 +02:00
}
2017-03-31 01:58:05 +02:00
private void updateDbToLastVersion ( final int currentVersion ) {
2014-08-27 00:26:25 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-10-11 13:30:32 +02:00
int version = currentVersion ;
if ( version < 4 ) {
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS user_photos(uid INTEGER, id INTEGER, data BLOB, PRIMARY KEY (uid, id)) " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " DROP INDEX IF EXISTS read_state_out_idx_messages; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS ttl_idx_messages; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS date_idx_messages; " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS mid_out_idx_messages ON messages(mid, out); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS task_idx_messages ON messages(uid, out, read_state, ttl, date, send_state); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_date_mid_idx_messages ON messages(uid, date, mid); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS user_contacts_v6(uid INTEGER PRIMARY KEY, fname TEXT, sname TEXT) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS user_phones_v6(uid INTEGER, phone TEXT, sphone TEXT, deleted INTEGER, PRIMARY KEY (uid, phone)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS sphone_deleted_idx_user_phones ON user_phones_v6(sphone, deleted); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS mid_idx_randoms ON randoms(mid); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS sent_files_v2(uid TEXT, type INTEGER, data BLOB, PRIMARY KEY (uid, type)) " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS blocked_users(uid INTEGER PRIMARY KEY) " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS download_queue(uid INTEGER, type INTEGER, date INTEGER, data BLOB, PRIMARY KEY (uid, type)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS type_date_idx_download_queue ON download_queue(type, date); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS dialog_settings(did INTEGER PRIMARY KEY, flags INTEGER); " ) . stepThis ( ) . dispose ( ) ;
2014-08-30 21:30:42 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS send_state_idx_messages ON messages(mid, send_state, date) WHERE mid < 0 AND send_state = 1; " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS unread_count_idx_dialogs ON dialogs(unread_count); " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2014-10-08 22:22:22 +02:00
database . executeFast ( " UPDATE messages SET send_state = 2 WHERE mid < 0 AND send_state = 1 " ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2017-03-31 01:58:05 +02:00
fixNotificationSettings ( ) ;
2014-10-11 13:30:32 +02:00
database . executeFast ( " PRAGMA user_version = 4 " ) . stepThis ( ) . dispose ( ) ;
version = 4 ;
2014-10-08 22:22:22 +02:00
}
2015-05-21 23:27:27 +02:00
if ( version = = 4 ) {
2014-10-08 22:22:22 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS enc_tasks_v2(mid INTEGER PRIMARY KEY, date INTEGER) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS date_idx_enc_tasks_v2 ON enc_tasks_v2(date); " ) . stepThis ( ) . dispose ( ) ;
database . beginTransaction ( ) ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT date, data FROM enc_tasks WHERE 1 " ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO enc_tasks_v2 VALUES(?, ?) " ) ;
if ( cursor . next ( ) ) {
int date = cursor . intValue ( 0 ) ;
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
int length = data . limit ( ) ;
2014-10-08 22:22:22 +02:00
for ( int a = 0 ; a < length / 4 ; a + + ) {
2014-08-30 21:30:42 +02:00
state . requery ( ) ;
2015-05-03 13:48:36 +02:00
state . bindInteger ( 1 , data . readInt32 ( false ) ) ;
2014-10-08 22:22:22 +02:00
state . bindInteger ( 2 , date ) ;
2014-08-30 21:30:42 +02:00
state . step ( ) ;
}
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2014-08-22 16:24:33 +02:00
}
}
2014-10-08 22:22:22 +02:00
state . dispose ( ) ;
cursor . dispose ( ) ;
database . commitTransaction ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS date_idx_enc_tasks; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP TABLE IF EXISTS enc_tasks; " ) . stepThis ( ) . dispose ( ) ;
2014-10-09 17:55:05 +02:00
database . executeFast ( " ALTER TABLE messages ADD COLUMN media INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
2014-10-08 22:22:22 +02:00
database . executeFast ( " PRAGMA user_version = 6 " ) . stepThis ( ) . dispose ( ) ;
2014-10-11 13:30:32 +02:00
version = 6 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 6 ) {
2014-10-17 20:29:13 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS messages_seq(mid INTEGER PRIMARY KEY, seq_in INTEGER, seq_out INTEGER); " ) . stepThis ( ) . dispose ( ) ;
2014-10-22 22:01:07 +02:00
database . executeFast ( " CREATE INDEX IF NOT EXISTS seq_idx_messages_seq ON messages_seq(seq_in, seq_out); " ) . stepThis ( ) . dispose ( ) ;
2014-10-11 13:30:32 +02:00
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN layer INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
2014-10-16 22:02:44 +02:00
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN seq_in INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN seq_out INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
2014-10-14 10:13:16 +02:00
database . executeFast ( " PRAGMA user_version = 7 " ) . stepThis ( ) . dispose ( ) ;
2014-10-11 13:30:32 +02:00
version = 7 ;
2014-10-08 22:22:22 +02:00
}
2014-10-29 15:28:54 +01:00
/ * if ( version = = 7 & & version < 8 ) {
2014-10-28 18:07:44 +01:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS secret_holes(uid INTEGER, seq_in INTEGER, seq_out INTEGER, data BLOB, PRIMARY KEY (uid, seq_in, seq_out)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 8 " ) . stepThis ( ) . dispose ( ) ;
version = 8 ;
2014-10-29 15:28:54 +01:00
} * /
2015-05-21 23:27:27 +02:00
if ( version = = 7 | | version = = 8 | | version = = 9 ) {
2014-12-01 18:56:31 +01:00
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN use_count INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN exchange_id INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN key_date INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN fprint INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN fauthkey BLOB default NULL " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN khash BLOB default NULL " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 10 " ) . stepThis ( ) . dispose ( ) ;
version = 10 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 10 ) {
2015-01-02 23:15:07 +01:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS web_recent_v3(id TEXT, type INTEGER, image_url TEXT, thumb_url TEXT, local_url TEXT, width INTEGER, height INTEGER, size INTEGER, date INTEGER, PRIMARY KEY (id, type)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 11 " ) . stepThis ( ) . dispose ( ) ;
version = 11 ;
}
2017-03-31 01:58:05 +02:00
if ( version = = 11 | | version = = 12 ) {
2015-02-01 19:51:02 +01:00
database . executeFast ( " DROP INDEX IF EXISTS uid_mid_idx_media; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS mid_idx_media; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS uid_date_mid_idx_media; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP TABLE IF EXISTS media; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP TABLE IF EXISTS media_counts; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS media_v2(mid INTEGER PRIMARY KEY, uid INTEGER, date INTEGER, type INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS media_counts_v2(uid INTEGER, type INTEGER, count INTEGER, PRIMARY KEY(uid, type)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_mid_type_date_idx_media ON media_v2(uid, mid, type, date); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS keyvalue(id TEXT PRIMARY KEY, value TEXT) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 13 " ) . stepThis ( ) . dispose ( ) ;
version = 13 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 13 ) {
2015-03-19 00:09:45 +01:00
database . executeFast ( " ALTER TABLE messages ADD COLUMN replydata BLOB default NULL " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 14 " ) . stepThis ( ) . dispose ( ) ;
version = 14 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 14 ) {
2015-03-26 18:34:47 +01:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS hashtag_recent_v2(id TEXT PRIMARY KEY, date INTEGER); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 15 " ) . stepThis ( ) . dispose ( ) ;
version = 15 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 15 ) {
2015-04-09 20:00:14 +02:00
database . executeFast ( " CREATE TABLE IF NOT EXISTS webpage_pending(id INTEGER, mid INTEGER, PRIMARY KEY (id, mid)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 16 " ) . stepThis ( ) . dispose ( ) ;
version = 16 ;
}
2015-05-21 23:27:27 +02:00
if ( version = = 16 ) {
2015-05-03 13:48:36 +02:00
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN inbox_max INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN outbox_max INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 17 " ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
version = 17 ;
}
if ( version = = 17 ) {
database . executeFast ( " CREATE TABLE bot_info(uid INTEGER PRIMARY KEY, info BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 18 " ) . stepThis ( ) . dispose ( ) ;
version = 18 ;
}
if ( version = = 18 ) {
database . executeFast ( " DROP TABLE IF EXISTS stickers; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS stickers_v2(id INTEGER PRIMARY KEY, data BLOB, date INTEGER, hash TEXT); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 19 " ) . stepThis ( ) . dispose ( ) ;
version = 19 ;
}
if ( version = = 19 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS bot_keyboard(uid INTEGER PRIMARY KEY, mid INTEGER, info BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS bot_keyboard_idx_mid ON bot_keyboard(mid); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 20 " ) . stepThis ( ) . dispose ( ) ;
2015-08-13 11:23:31 +02:00
version = 20 ;
}
if ( version = = 20 ) {
database . executeFast ( " CREATE TABLE search_recent(did INTEGER PRIMARY KEY, date INTEGER); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 21 " ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
version = 21 ;
}
if ( version = = 21 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS chat_settings_v2(uid INTEGER PRIMARY KEY, info BLOB) " ) . stepThis ( ) . dispose ( ) ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT uid, participants FROM chat_settings WHERE uid < 0 " ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chat_settings_v2 VALUES(?, ?) " ) ;
while ( cursor . next ( ) ) {
int chat_id = cursor . intValue ( 0 ) ;
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
2015-09-24 22:52:02 +02:00
TLRPC . ChatParticipants participants = TLRPC . ChatParticipants . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-09-24 22:52:02 +02:00
if ( participants ! = null ) {
TLRPC . TL_chatFull chatFull = new TLRPC . TL_chatFull ( ) ;
chatFull . id = chat_id ;
chatFull . chat_photo = new TLRPC . TL_photoEmpty ( ) ;
chatFull . notify_settings = new TLRPC . TL_peerNotifySettingsEmpty ( ) ;
chatFull . exported_invite = new TLRPC . TL_chatInviteEmpty ( ) ;
chatFull . participants = participants ;
NativeByteBuffer data2 = new NativeByteBuffer ( chatFull . getObjectSize ( ) ) ;
chatFull . serializeToStream ( data2 ) ;
state . requery ( ) ;
state . bindInteger ( 1 , chat_id ) ;
state . bindByteBuffer ( 2 , data2 ) ;
state . step ( ) ;
data2 . reuse ( ) ;
}
}
}
state . dispose ( ) ;
cursor . dispose ( ) ;
database . executeFast ( " DROP TABLE IF EXISTS chat_settings; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN last_mid_i INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN unread_count_i INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN pts INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN date_i INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS last_mid_i_idx_dialogs ON dialogs(last_mid_i); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS unread_count_i_idx_dialogs ON dialogs(unread_count_i); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " ALTER TABLE messages ADD COLUMN imp INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS messages_holes(uid INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, start)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_end_messages_holes ON messages_holes(uid, end); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 22 " ) . stepThis ( ) . dispose ( ) ;
version = 22 ;
}
if ( version = = 22 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS media_holes_v2(uid INTEGER, type INTEGER, start INTEGER, end INTEGER, PRIMARY KEY(uid, type, start)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS uid_end_media_holes_v2 ON media_holes_v2(uid, type, end); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 23 " ) . stepThis ( ) . dispose ( ) ;
2015-10-29 18:10:07 +01:00
version = 23 ;
}
2017-03-31 01:58:05 +02:00
if ( version = = 23 | | version = = 24 ) {
2015-10-29 18:10:07 +01:00
database . executeFast ( " DELETE FROM media_holes_v2 WHERE uid != 0 AND type >= 0 AND start IN (0, 1) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 25 " ) . stepThis ( ) . dispose ( ) ;
2015-11-26 22:04:02 +01:00
version = 25 ;
}
if ( version = = 25 | | version = = 26 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS channel_users_v2(did INTEGER, uid INTEGER, date INTEGER, data BLOB, PRIMARY KEY(did, uid)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 27 " ) . stepThis ( ) . dispose ( ) ;
2016-01-11 18:19:48 +01:00
version = 27 ;
}
if ( version = = 27 ) {
database . executeFast ( " ALTER TABLE web_recent_v3 ADD COLUMN document BLOB default NULL " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 28 " ) . stepThis ( ) . dispose ( ) ;
version = 28 ;
}
2017-03-31 01:58:05 +02:00
if ( version = = 28 | | version = = 29 ) {
2016-03-06 02:49:31 +01:00
database . executeFast ( " DELETE FROM sent_files_v2 WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM download_queue WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 30 " ) . stepThis ( ) . dispose ( ) ;
2016-03-16 13:26:32 +01:00
version = 30 ;
}
if ( version = = 30 ) {
database . executeFast ( " ALTER TABLE chat_settings_v2 ADD COLUMN pinned INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_settings_pinned_idx ON chat_settings_v2(uid, pinned) WHERE pinned != 0; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS chat_pinned(uid INTEGER PRIMARY KEY, pinned INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_pinned_mid_idx ON chat_pinned(uid, pinned) WHERE pinned != 0; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS users_data(uid INTEGER PRIMARY KEY, about TEXT) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 31 " ) . stepThis ( ) . dispose ( ) ;
2016-05-25 23:49:47 +02:00
version = 31 ;
}
if ( version = = 31 ) {
database . executeFast ( " DROP TABLE IF EXISTS bot_recent; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE TABLE IF NOT EXISTS chat_hints(did INTEGER, type INTEGER, rating REAL, date INTEGER, PRIMARY KEY(did, type)) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS chat_hints_rating_idx ON chat_hints(rating); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 32 " ) . stepThis ( ) . dispose ( ) ;
2016-06-24 12:27:15 +02:00
version = 32 ;
}
if ( version = = 32 ) {
database . executeFast ( " DROP INDEX IF EXISTS uid_mid_idx_imp_messages; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DROP INDEX IF EXISTS uid_date_mid_imp_idx_messages; " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 33 " ) . stepThis ( ) . dispose ( ) ;
version = 33 ;
}
if ( version = = 33 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS pending_tasks(id INTEGER PRIMARY KEY, data BLOB); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 34 " ) . stepThis ( ) . dispose ( ) ;
2016-10-11 13:57:01 +02:00
version = 34 ;
}
if ( version = = 34 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS stickers_featured(id INTEGER PRIMARY KEY, data BLOB, unread BLOB, date INTEGER, hash TEXT); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 35 " ) . stepThis ( ) . dispose ( ) ;
version = 35 ;
}
if ( version = = 35 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS requested_holes(uid INTEGER, seq_out_start INTEGER, seq_out_end INTEGER, PRIMARY KEY (uid, seq_out_start, seq_out_end)); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 36 " ) . stepThis ( ) . dispose ( ) ;
version = 36 ;
}
if ( version = = 36 ) {
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN in_seq_no INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 37 " ) . stepThis ( ) . dispose ( ) ;
2017-03-31 01:58:05 +02:00
version = 37 ;
}
if ( version = = 37 ) {
database . executeFast ( " CREATE TABLE IF NOT EXISTS botcache(id TEXT PRIMARY KEY, date INTEGER, data BLOB) " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " CREATE INDEX IF NOT EXISTS botcache_date_idx ON botcache(date); " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 38 " ) . stepThis ( ) . dispose ( ) ;
version = 38 ;
}
if ( version = = 38 ) {
database . executeFast ( " ALTER TABLE dialogs ADD COLUMN pinned INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 39 " ) . stepThis ( ) . dispose ( ) ;
version = 39 ;
}
if ( version = = 39 ) {
database . executeFast ( " ALTER TABLE enc_chats ADD COLUMN admin_id INTEGER default 0 " ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " PRAGMA user_version = 40 " ) . stepThis ( ) . dispose ( ) ;
version = 40 ;
}
if ( version = = 40 ) {
fixNotificationSettings ( ) ;
database . executeFast ( " PRAGMA user_version = 41 " ) . stepThis ( ) . dispose ( ) ;
//version = 41;
2015-05-03 13:48:36 +02:00
}
2014-08-27 00:26:25 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-11-04 13:31:01 +01:00
}
2013-10-25 17:19:00 +02:00
}
2014-08-27 00:26:25 +02:00
} ) ;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
private void cleanupInternal ( ) {
lastDateValue = 0 ;
lastSeqValue = 0 ;
lastPtsValue = 0 ;
lastQtsValue = 0 ;
lastSecretVersion = 0 ;
lastSavedSeq = 0 ;
lastSavedPts = 0 ;
lastSavedDate = 0 ;
lastSavedQts = 0 ;
secretPBytes = null ;
secretG = 0 ;
if ( database ! = null ) {
database . close ( ) ;
database = null ;
}
if ( cacheFile ! = null ) {
cacheFile . delete ( ) ;
cacheFile = null ;
}
}
2016-06-24 12:27:15 +02:00
public void cleanup ( final boolean isLogin ) {
2014-06-13 17:03:06 +02:00
storageQueue . cleanupQueue ( ) ;
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2017-03-31 01:58:05 +02:00
cleanupInternal ( ) ;
openDatabase ( false ) ;
2014-07-23 01:27:00 +02:00
if ( isLogin ) {
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . getDifference ( ) ;
}
} ) ;
}
2013-10-25 17:19:00 +02:00
}
} ) ;
}
2013-11-04 13:31:01 +01:00
public void saveSecretParams ( final int lsv , final int sg , final byte [ ] pbytes ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " UPDATE params SET lsv = ?, sg = ?, pbytes = ? WHERE id = 1 " ) ;
state . bindInteger ( 1 , lsv ) ;
state . bindInteger ( 2 , sg ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( pbytes ! = null ? pbytes . length : 1 ) ;
2013-11-04 13:31:01 +01:00
if ( pbytes ! = null ) {
2015-09-24 22:52:02 +02:00
data . writeBytes ( pbytes ) ;
2013-11-04 13:31:01 +01:00
}
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 3 , data ) ;
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
}
}
} ) ;
}
private void fixNotificationSettings ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
HashMap < Long , Long > ids = new HashMap < > ( ) ;
SharedPreferences preferences = ApplicationLoader . applicationContext . getSharedPreferences ( " Notifications " , Context . MODE_PRIVATE ) ;
Map < String , ? > values = preferences . getAll ( ) ;
for ( Map . Entry < String , ? > entry : values . entrySet ( ) ) {
String key = entry . getKey ( ) ;
if ( key . startsWith ( " notify2_ " ) ) {
Integer value = ( Integer ) entry . getValue ( ) ;
if ( value = = 2 | | value = = 3 ) {
key = key . replace ( " notify2_ " , " " ) ;
long flags ;
if ( value = = 2 ) {
flags = 1 ;
} else {
Integer time = ( Integer ) values . get ( " notifyuntil_ " + key ) ;
if ( time ! = null ) {
flags = ( ( long ) time < < 32 ) | 1 ;
} else {
flags = 1 ;
}
}
try {
ids . put ( Long . parseLong ( key ) , flags ) ;
} catch ( Exception e ) {
e . printStackTrace ( ) ;
}
} else if ( value = = 3 ) {
}
}
}
try {
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO dialog_settings VALUES(?, ?) " ) ;
for ( HashMap . Entry < Long , Long > entry : ids . entrySet ( ) ) {
state . requery ( ) ;
state . bindLong ( 1 , entry . getKey ( ) ) ;
state . bindLong ( 2 , entry . getValue ( ) ) ;
state . step ( ) ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
} catch ( Throwable e ) {
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public long createPendingTask ( final NativeByteBuffer data ) {
if ( data = = null ) {
return 0 ;
}
final long id = lastTaskId . getAndAdd ( 1 ) ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO pending_tasks VALUES(?, ?) " ) ;
state . bindLong ( 1 , id ) ;
state . bindByteBuffer ( 2 , data ) ;
state . step ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-06-24 12:27:15 +02:00
} finally {
data . reuse ( ) ;
}
}
} ) ;
return id ;
}
public void removePendingTask ( final long id ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM pending_tasks WHERE id = " + id ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-06-24 12:27:15 +02:00
}
}
} ) ;
}
private void loadPendingTasks ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT id, data FROM pending_tasks WHERE 1 " ) ;
while ( cursor . next ( ) ) {
final long taskId = cursor . longValue ( 0 ) ;
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
int type = data . readInt32 ( false ) ;
switch ( type ) {
2016-10-11 13:57:01 +02:00
case 0 : {
2016-06-24 12:27:15 +02:00
final TLRPC . Chat chat = TLRPC . Chat . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
if ( chat ! = null ) {
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . loadUnknownChannel ( chat , taskId ) ;
}
} ) ;
}
break ;
2016-10-11 13:57:01 +02:00
}
case 1 : {
2016-06-24 12:27:15 +02:00
final int channelId = data . readInt32 ( false ) ;
final int newDialogType = data . readInt32 ( false ) ;
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2017-03-31 01:58:05 +02:00
MessagesController . getInstance ( ) . getChannelDifference ( channelId , newDialogType , taskId , null ) ;
2016-06-24 12:27:15 +02:00
}
} ) ;
break ;
2016-10-11 13:57:01 +02:00
}
2017-03-31 01:58:05 +02:00
case 2 :
case 5 : {
2016-06-24 12:27:15 +02:00
final TLRPC . TL_dialog dialog = new TLRPC . TL_dialog ( ) ;
dialog . id = data . readInt64 ( false ) ;
dialog . top_message = data . readInt32 ( false ) ;
dialog . read_inbox_max_id = data . readInt32 ( false ) ;
dialog . read_outbox_max_id = data . readInt32 ( false ) ;
dialog . unread_count = data . readInt32 ( false ) ;
dialog . last_message_date = data . readInt32 ( false ) ;
dialog . pts = data . readInt32 ( false ) ;
dialog . flags = data . readInt32 ( false ) ;
2017-03-31 01:58:05 +02:00
if ( type = = 5 ) {
dialog . pinned = data . readBool ( false ) ;
dialog . pinnedNum = data . readInt32 ( false ) ;
}
2016-06-24 12:27:15 +02:00
final TLRPC . InputPeer peer = TLRPC . InputPeer . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . checkLastDialogMessage ( dialog , peer , taskId ) ;
}
} ) ;
break ;
2016-10-11 13:57:01 +02:00
}
case 3 : {
long random_id = data . readInt64 ( false ) ;
TLRPC . InputPeer peer = TLRPC . InputPeer . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
TLRPC . TL_inputMediaGame game = ( TLRPC . TL_inputMediaGame ) TLRPC . InputMedia . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
SendMessagesHelper . getInstance ( ) . sendGame ( peer , game , random_id , taskId ) ;
break ;
}
2017-03-31 01:58:05 +02:00
case 4 : {
final long did = data . readInt64 ( false ) ;
final boolean pin = data . readBool ( false ) ;
final TLRPC . InputPeer peer = TLRPC . InputPeer . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . pinDialog ( did , pin , peer , taskId ) ;
}
} ) ;
break ;
}
case 6 : {
final int channelId = data . readInt32 ( false ) ;
final int newDialogType = data . readInt32 ( false ) ;
final TLRPC . InputChannel inputChannel = TLRPC . InputChannel . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . getChannelDifference ( channelId , newDialogType , taskId , inputChannel ) ;
}
} ) ;
break ;
}
case 7 : {
final int channelId = data . readInt32 ( false ) ;
int constructor = data . readInt32 ( false ) ;
TLObject request = TLRPC . TL_messages_deleteMessages . TLdeserialize ( data , constructor , false ) ;
if ( request = = null ) {
request = TLRPC . TL_channels_deleteMessages . TLdeserialize ( data , constructor , false ) ;
}
if ( request = = null ) {
removePendingTask ( taskId ) ;
} else {
final TLObject finalRequest = request ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . deleteMessages ( null , null , null , channelId , true , taskId , finalRequest ) ;
}
} ) ;
}
break ;
}
2016-06-24 12:27:15 +02:00
}
data . reuse ( ) ;
}
}
cursor . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-06-24 12:27:15 +02:00
}
}
} ) ;
}
2015-09-24 22:52:02 +02:00
public void saveChannelPts ( final int channelId , final int pts ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET pts = ? WHERE did = ? " ) ;
state . bindInteger ( 1 , pts ) ;
state . bindInteger ( 2 , - channelId ) ;
2013-11-04 13:31:01 +01:00
state . step ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-11-04 13:31:01 +01:00
}
}
} ) ;
}
public void saveDiffParams ( final int seq , final int pts , final int date , final int qts ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-06-13 17:03:06 +02:00
if ( lastSavedSeq = = seq & & lastSavedPts = = pts & & lastSavedDate = = date & & lastQtsValue = = qts ) {
return ;
}
2013-11-04 13:31:01 +01:00
SQLitePreparedStatement state = database . executeFast ( " UPDATE params SET seq = ?, pts = ?, date = ?, qts = ? WHERE id = 1 " ) ;
state . bindInteger ( 1 , seq ) ;
state . bindInteger ( 2 , pts ) ;
state . bindInteger ( 3 , date ) ;
state . bindInteger ( 4 , qts ) ;
state . step ( ) ;
state . dispose ( ) ;
2014-06-13 17:03:06 +02:00
lastSavedSeq = seq ;
lastSavedPts = pts ;
lastSavedDate = date ;
lastSavedQts = qts ;
2013-11-04 13:31:01 +01:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-11-04 13:31:01 +01:00
}
}
} ) ;
}
2015-02-01 19:51:02 +01:00
public void setDialogFlags ( final long did , final long flags ) {
2014-08-22 16:24:33 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-08-30 21:30:42 +02:00
database . executeFast ( String . format ( Locale . US , " REPLACE INTO dialog_settings VALUES(%d, %d) " , did , flags ) ) . stepThis ( ) . dispose ( ) ;
2014-08-22 16:24:33 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
2014-08-29 23:06:04 +02:00
public void loadUnreadMessages ( ) {
2014-07-10 13:30:55 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-06-24 12:27:15 +02:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > encryptedChatIds = new ArrayList < > ( ) ;
2015-01-02 23:15:07 +01:00
final HashMap < Long , Integer > pushDialogs = new HashMap < > ( ) ;
2014-08-30 21:30:42 +02:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT d.did, d.unread_count, s.flags FROM dialogs as d LEFT JOIN dialog_settings as s ON d.did = s.did WHERE d.unread_count != 0 " ) ;
2014-10-08 22:22:22 +02:00
StringBuilder ids = new StringBuilder ( ) ;
2017-03-31 01:58:05 +02:00
int currentTime = ConnectionsManager . getInstance ( ) . getCurrentTime ( ) ;
2014-07-10 13:30:55 +02:00
while ( cursor . next ( ) ) {
2017-03-31 01:58:05 +02:00
long flags = cursor . longValue ( 2 ) ;
boolean muted = ( flags & 1 ) ! = 0 ;
int mutedUntil = ( int ) ( flags > > 32 ) ;
if ( cursor . isNull ( 2 ) | | ! muted | | mutedUntil ! = 0 & & mutedUntil < currentTime ) {
2014-08-30 21:30:42 +02:00
long did = cursor . longValue ( 0 ) ;
int count = cursor . intValue ( 1 ) ;
pushDialogs . put ( did , count ) ;
if ( ids . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
ids . append ( " , " ) ;
2014-08-30 21:30:42 +02:00
}
2014-10-08 22:22:22 +02:00
ids . append ( did ) ;
2016-06-24 12:27:15 +02:00
int lower_id = ( int ) did ;
int high_id = ( int ) ( did > > 32 ) ;
if ( lower_id ! = 0 ) {
if ( lower_id < 0 ) {
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
}
} else {
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
}
}
} else {
if ( ! encryptedChatIds . contains ( high_id ) ) {
encryptedChatIds . add ( high_id ) ;
}
}
2014-08-22 16:24:33 +02:00
}
2014-07-10 13:30:55 +02:00
}
cursor . dispose ( ) ;
2014-08-22 16:24:33 +02:00
2016-10-11 13:57:01 +02:00
ArrayList < Long > replyMessages = new ArrayList < > ( ) ;
HashMap < Integer , ArrayList < TLRPC . Message > > replyMessageOwners = new HashMap < > ( ) ;
2015-01-02 23:15:07 +01:00
final ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
final ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
final ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
final ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
2014-08-29 23:06:04 +02:00
if ( ids . length ( ) > 0 ) {
2016-10-11 13:57:01 +02:00
cursor = database . queryFinalized ( " SELECT read_state, data, send_state, mid, date, uid, replydata FROM messages WHERE uid IN ( " + ids . toString ( ) + " ) AND out = 0 AND read_state IN(0,2) ORDER BY date DESC LIMIT 50 " ) ;
2014-08-22 16:24:33 +02:00
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-05-03 13:48:36 +02:00
MessageObject . setUnreadFlags ( message , cursor . intValue ( 0 ) ) ;
2014-08-22 16:24:33 +02:00
message . id = cursor . intValue ( 3 ) ;
message . date = cursor . intValue ( 4 ) ;
message . dialog_id = cursor . longValue ( 5 ) ;
messages . add ( message ) ;
2016-06-24 12:27:15 +02:00
int lower_id = ( int ) message . dialog_id ;
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2014-08-22 16:24:33 +02:00
message . send_state = cursor . intValue ( 2 ) ;
2016-06-24 12:27:15 +02:00
if ( message . to_id . channel_id = = 0 & & ! MessageObject . isUnread ( message ) & & lower_id ! = 0 | | message . id > 0 ) { //TODO check
2014-08-22 16:24:33 +02:00
message . send_state = 0 ;
}
if ( lower_id = = 0 & & ! cursor . isNull ( 5 ) ) {
message . random_id = cursor . longValue ( 5 ) ;
}
2016-10-11 13:57:01 +02:00
try {
2017-03-31 01:58:05 +02:00
if ( message . reply_to_msg_id ! = 0 & & (
message . action instanceof TLRPC . TL_messageActionPinMessage | |
message . action instanceof TLRPC . TL_messageActionPaymentSent | |
message . action instanceof TLRPC . TL_messageActionGameScore ) ) {
2016-10-11 13:57:01 +02:00
if ( ! cursor . isNull ( 6 ) ) {
data = cursor . byteBufferValue ( 6 ) ;
if ( data ! = null ) {
message . replyMessage = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
if ( message . replyMessage ! = null ) {
addUsersAndChatsFromMessage ( message . replyMessage , usersToLoad , chatsToLoad ) ;
}
}
}
if ( message . replyMessage = = null ) {
long messageId = message . reply_to_msg_id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
if ( ! replyMessages . contains ( messageId ) ) {
replyMessages . add ( messageId ) ;
}
ArrayList < TLRPC . Message > arrayList = replyMessageOwners . get ( message . reply_to_msg_id ) ;
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
replyMessageOwners . put ( message . reply_to_msg_id , arrayList ) ;
}
arrayList . add ( message ) ;
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-10-11 13:57:01 +02:00
}
2014-08-22 16:24:33 +02:00
}
}
cursor . dispose ( ) ;
2016-10-11 13:57:01 +02:00
if ( ! replyMessages . isEmpty ( ) ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date, uid FROM messages WHERE mid IN(%s) " , TextUtils . join ( " , " , replyMessages ) ) ) ;
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = cursor . longValue ( 3 ) ;
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
ArrayList < TLRPC . Message > arrayList = replyMessageOwners . get ( message . id ) ;
if ( arrayList ! = null ) {
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
arrayList . get ( a ) . replyMessage = message ;
}
}
}
}
cursor . dispose ( ) ;
}
2014-08-22 16:24:33 +02:00
if ( ! encryptedChatIds . isEmpty ( ) ) {
2015-11-26 22:04:02 +01:00
getEncryptedChatsInternal ( TextUtils . join ( " , " , encryptedChatIds ) , encryptedChats , usersToLoad ) ;
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
if ( ! usersToLoad . isEmpty ( ) ) {
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
if ( ! chatsToLoad . isEmpty ( ) ) {
getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , chats ) ;
2015-10-29 18:10:07 +01:00
for ( int a = 0 ; a < chats . size ( ) ; a + + ) {
TLRPC . Chat chat = chats . get ( a ) ;
2015-11-26 22:04:02 +01:00
if ( chat ! = null & & ( chat . left | | chat . migrated_to ! = null ) ) {
long did = - chat . id ;
2015-12-09 19:27:52 +01:00
database . executeFast ( " UPDATE dialogs SET unread_count = 0, unread_count_i = 0 WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
2015-11-26 22:04:02 +01:00
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET read_state = 3 WHERE uid = %d AND mid > 0 AND read_state IN(0,2) AND out = 0 " , did ) ) . stepThis ( ) . dispose ( ) ;
2015-10-29 18:10:07 +01:00
chats . remove ( a ) ;
a - - ;
pushDialogs . remove ( ( long ) - chat . id ) ;
for ( int b = 0 ; b < messages . size ( ) ; b + + ) {
TLRPC . Message message = messages . get ( b ) ;
if ( message . dialog_id = = - chat . id ) {
messages . remove ( b ) ;
b - - ;
}
}
}
}
2014-08-22 16:24:33 +02:00
}
}
2014-08-29 23:06:04 +02:00
Collections . reverse ( messages ) ;
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-07-10 13:30:55 +02:00
@Override
public void run ( ) {
2014-08-22 16:24:33 +02:00
NotificationsController . getInstance ( ) . processLoadedUnreadMessages ( pushDialogs , messages , users , chats , encryptedChats ) ;
2014-07-10 13:30:55 +02:00
}
} ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-07-10 13:30:55 +02:00
}
}
} ) ;
}
2013-10-25 17:19:00 +02:00
public void putWallpapers ( final ArrayList < TLRPC . WallPaper > wallPapers ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-07-03 00:39:05 +02:00
int num = 0 ;
2013-10-25 17:19:00 +02:00
database . executeFast ( " DELETE FROM wallpapers WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO wallpapers VALUES(?, ?) " ) ;
for ( TLRPC . WallPaper wallPaper : wallPapers ) {
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( wallPaper . getObjectSize ( ) ) ;
2013-10-25 17:19:00 +02:00
wallPaper . serializeToStream ( data ) ;
state . bindInteger ( 1 , num ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 2 , data ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
num + + ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2013-10-25 17:19:00 +02:00
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2015-01-02 23:15:07 +01:00
public void loadWebRecent ( final int type ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-01-11 18:19:48 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT id, image_url, thumb_url, local_url, width, height, size, date, document FROM web_recent_v3 WHERE type = " + type + " ORDER BY date DESC " ) ;
2015-01-02 23:15:07 +01:00
final ArrayList < MediaController . SearchImage > arrayList = new ArrayList < > ( ) ;
while ( cursor . next ( ) ) {
MediaController . SearchImage searchImage = new MediaController . SearchImage ( ) ;
searchImage . id = cursor . stringValue ( 0 ) ;
searchImage . imageUrl = cursor . stringValue ( 1 ) ;
searchImage . thumbUrl = cursor . stringValue ( 2 ) ;
searchImage . localUrl = cursor . stringValue ( 3 ) ;
searchImage . width = cursor . intValue ( 4 ) ;
searchImage . height = cursor . intValue ( 5 ) ;
searchImage . size = cursor . intValue ( 6 ) ;
searchImage . date = cursor . intValue ( 7 ) ;
2016-01-11 18:19:48 +01:00
if ( ! cursor . isNull ( 8 ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 8 ) ;
if ( data ! = null ) {
2016-01-11 18:19:48 +01:00
searchImage . document = TLRPC . Document . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-01-11 18:19:48 +01:00
}
}
2015-01-02 23:15:07 +01:00
searchImage . type = type ;
arrayList . add ( searchImage ) ;
}
cursor . dispose ( ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . recentImagesDidLoaded , type , arrayList ) ;
}
} ) ;
2016-01-11 18:19:48 +01:00
} catch ( Throwable e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-01-11 18:19:48 +01:00
}
}
} ) ;
}
public void addRecentLocalFile ( final String imageUrl , final String localUrl , final TLRPC . Document document ) {
if ( imageUrl = = null | | imageUrl . length ( ) = = 0 | | ( ( localUrl = = null | | localUrl . length ( ) = = 0 ) & & document = = null ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( document ! = null ) {
SQLitePreparedStatement state = database . executeFast ( " UPDATE web_recent_v3 SET document = ? WHERE image_url = ? " ) ;
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( document . getObjectSize ( ) ) ;
document . serializeToStream ( data ) ;
state . bindByteBuffer ( 1 , data ) ;
state . bindString ( 2 , imageUrl ) ;
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
} else {
SQLitePreparedStatement state = database . executeFast ( " UPDATE web_recent_v3 SET local_url = ? WHERE image_url = ? " ) ;
state . requery ( ) ;
state . bindString ( 1 , localUrl ) ;
state . bindString ( 2 , imageUrl ) ;
state . step ( ) ;
state . dispose ( ) ;
}
2015-01-02 23:15:07 +01:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-01-02 23:15:07 +01:00
}
}
} ) ;
}
2015-03-26 18:34:47 +01:00
public void clearWebRecent ( final int type ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM web_recent_v3 WHERE type = " + type ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-03-26 18:34:47 +01:00
}
}
} ) ;
}
2015-01-02 23:15:07 +01:00
public void putWebRecent ( final ArrayList < MediaController . SearchImage > arrayList ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . beginTransaction ( ) ;
2016-01-11 18:19:48 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO web_recent_v3 VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2015-01-02 23:15:07 +01:00
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
2016-01-11 18:19:48 +01:00
if ( a = = 200 ) {
2015-01-02 23:15:07 +01:00
break ;
}
MediaController . SearchImage searchImage = arrayList . get ( a ) ;
state . requery ( ) ;
state . bindString ( 1 , searchImage . id ) ;
state . bindInteger ( 2 , searchImage . type ) ;
2016-01-11 18:19:48 +01:00
state . bindString ( 3 , searchImage . imageUrl ! = null ? searchImage . imageUrl : " " ) ;
state . bindString ( 4 , searchImage . thumbUrl ! = null ? searchImage . thumbUrl : " " ) ;
state . bindString ( 5 , searchImage . localUrl ! = null ? searchImage . localUrl : " " ) ;
2015-01-02 23:15:07 +01:00
state . bindInteger ( 6 , searchImage . width ) ;
state . bindInteger ( 7 , searchImage . height ) ;
state . bindInteger ( 8 , searchImage . size ) ;
state . bindInteger ( 9 , searchImage . date ) ;
2016-01-11 18:19:48 +01:00
NativeByteBuffer data = null ;
if ( searchImage . document ! = null ) {
data = new NativeByteBuffer ( searchImage . document . getObjectSize ( ) ) ;
searchImage . document . serializeToStream ( data ) ;
state . bindByteBuffer ( 10 , data ) ;
} else {
state . bindNull ( 10 ) ;
}
2015-01-02 23:15:07 +01:00
state . step ( ) ;
2016-01-11 18:19:48 +01:00
if ( data ! = null ) {
data . reuse ( ) ;
}
2015-01-02 23:15:07 +01:00
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
2016-01-11 18:19:48 +01:00
if ( arrayList . size ( ) > = 200 ) {
2015-01-02 23:15:07 +01:00
database . beginTransaction ( ) ;
2016-01-11 18:19:48 +01:00
for ( int a = 200 ; a < arrayList . size ( ) ; a + + ) {
2015-01-02 23:15:07 +01:00
database . executeFast ( " DELETE FROM web_recent_v3 WHERE id = ' " + arrayList . get ( a ) . id + " ' " ) . stepThis ( ) . dispose ( ) ;
}
database . commitTransaction ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-01-02 23:15:07 +01:00
}
}
} ) ;
}
2013-10-25 17:19:00 +02:00
public void getWallpapers ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT data FROM wallpapers WHERE 1 " ) ;
2015-05-21 23:27:27 +02:00
final ArrayList < TLRPC . WallPaper > wallPapers = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . WallPaper wallPaper = TLRPC . WallPaper . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2013-10-25 17:19:00 +02:00
wallPapers . add ( wallPaper ) ;
}
}
cursor . dispose ( ) ;
2015-05-21 23:27:27 +02:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . wallpapersDidLoaded , wallPapers ) ;
}
} ) ;
2014-08-22 16:24:33 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
public void getBlockedUsers ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-01-02 23:15:07 +01:00
ArrayList < Integer > ids = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
2015-03-19 00:09:45 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT * FROM blocked_users WHERE 1 " ) ;
2014-10-08 22:22:22 +02:00
StringBuilder usersToLoad = new StringBuilder ( ) ;
2014-08-22 16:24:33 +02:00
while ( cursor . next ( ) ) {
int user_id = cursor . intValue ( 0 ) ;
ids . add ( user_id ) ;
if ( usersToLoad . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
usersToLoad . append ( " , " ) ;
2014-08-22 16:24:33 +02:00
}
2014-10-08 22:22:22 +02:00
usersToLoad . append ( user_id ) ;
2014-08-22 16:24:33 +02:00
}
cursor . dispose ( ) ;
if ( usersToLoad . length ( ) ! = 0 ) {
2014-10-23 17:30:35 +02:00
getUsersInternal ( usersToLoad . toString ( ) , users ) ;
2014-08-22 16:24:33 +02:00
}
MessagesController . getInstance ( ) . processLoadedBlockedUsers ( ids , users , true ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
public void deleteBlockedUser ( final int id ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM blocked_users WHERE uid = " + id ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
public void putBlockedUsers ( final ArrayList < Integer > ids , final boolean replace ) {
if ( ids = = null | | ids . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( replace ) {
database . executeFast ( " DELETE FROM blocked_users WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
}
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO blocked_users VALUES(?) " ) ;
for ( Integer id : ids ) {
state . requery ( ) ;
state . bindInteger ( 1 , id ) ;
state . step ( ) ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2016-03-16 13:26:32 +01:00
public void deleteUserChannelHistory ( final int channelId , final int uid ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-03-16 13:26:32 +01:00
long did = - channelId ;
final ArrayList < Integer > mids = new ArrayList < > ( ) ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT data FROM messages WHERE uid = " + did ) ;
ArrayList < File > filesToDelete = new ArrayList < > ( ) ;
try {
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-16 13:26:32 +01:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( message ! = null & & message . from_id = = uid & & message . id ! = 1 ) {
mids . add ( message . id ) ;
2016-03-06 02:49:31 +01:00
if ( message . media instanceof TLRPC . TL_messageMediaPhoto ) {
2015-02-26 02:32:51 +01:00
for ( TLRPC . PhotoSize photoSize : message . media . photo . sizes ) {
File file = FileLoader . getPathToAttach ( photoSize ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
} else if ( message . media instanceof TLRPC . TL_messageMediaDocument ) {
File file = FileLoader . getPathToAttach ( message . media . document ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
file = FileLoader . getPathToAttach ( message . media . document . thumb ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
}
2016-03-16 13:26:32 +01:00
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-16 13:26:32 +01:00
}
cursor . dispose ( ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
MessagesController . getInstance ( ) . markChannelDialogMessageAsDeleted ( mids , channelId ) ;
}
} ) ;
markMessagesAsDeletedInternal ( mids , channelId ) ;
2017-03-31 01:58:05 +02:00
updateDialogsWithDeletedMessagesInternal ( mids , null , channelId ) ;
2016-03-16 13:26:32 +01:00
FileLoader . getInstance ( ) . deleteFiles ( filesToDelete , 0 ) ;
if ( ! mids . isEmpty ( ) ) {
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . messagesDeleted , mids , channelId ) ;
}
} ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-16 13:26:32 +01:00
}
}
} ) ;
}
public void deleteDialog ( final long did , final int messagesOnly ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-06-24 12:27:15 +02:00
if ( messagesOnly = = 3 ) {
int lastMid = - 1 ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT last_mid FROM dialogs WHERE did = " + did ) ;
if ( cursor . next ( ) ) {
lastMid = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( lastMid ! = 0 ) {
return ;
}
}
2016-03-16 13:26:32 +01:00
if ( ( int ) did = = 0 | | messagesOnly = = 2 ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT data FROM messages WHERE uid = " + did ) ;
ArrayList < File > filesToDelete = new ArrayList < > ( ) ;
try {
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-16 13:26:32 +01:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( message ! = null & & message . media ! = null ) {
if ( message . media instanceof TLRPC . TL_messageMediaPhoto ) {
for ( TLRPC . PhotoSize photoSize : message . media . photo . sizes ) {
File file = FileLoader . getPathToAttach ( photoSize ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
} else if ( message . media instanceof TLRPC . TL_messageMediaDocument ) {
File file = FileLoader . getPathToAttach ( message . media . document ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
file = FileLoader . getPathToAttach ( message . media . document . thumb ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
}
}
2015-02-26 02:32:51 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-02-26 02:32:51 +01:00
}
cursor . dispose ( ) ;
2015-12-09 19:27:52 +01:00
FileLoader . getInstance ( ) . deleteFiles ( filesToDelete , messagesOnly ) ;
}
2016-06-24 12:27:15 +02:00
if ( messagesOnly = = 0 | | messagesOnly = = 3 ) {
2015-12-09 19:27:52 +01:00
database . executeFast ( " DELETE FROM dialogs WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM chat_settings_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2016-03-16 13:26:32 +01:00
database . executeFast ( " DELETE FROM chat_pinned WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2015-12-09 19:27:52 +01:00
database . executeFast ( " DELETE FROM channel_users_v2 WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM search_recent WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
2016-06-24 12:27:15 +02:00
int lower_id = ( int ) did ;
int high_id = ( int ) ( did > > 32 ) ;
2015-12-09 19:27:52 +01:00
if ( lower_id ! = 0 ) {
if ( high_id = = 1 ) {
database . executeFast ( " DELETE FROM chats WHERE uid = " + lower_id ) . stepThis ( ) . dispose ( ) ;
} else if ( lower_id < 0 ) {
//database.executeFast("DELETE FROM chats WHERE uid = " + (-lower_id)).stepThis().dispose();
}
} else {
database . executeFast ( " DELETE FROM enc_chats WHERE uid = " + high_id ) . stepThis ( ) . dispose ( ) ;
//database.executeFast("DELETE FROM secret_holes WHERE uid = " + high_id).stepThis().dispose();
}
} else if ( messagesOnly = = 2 ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT last_mid_i, last_mid FROM dialogs WHERE did = " + did ) ;
2016-06-24 12:27:15 +02:00
int messageId = - 1 ;
2015-12-09 19:27:52 +01:00
if ( cursor . next ( ) ) {
long last_mid_i = cursor . longValue ( 0 ) ;
long last_mid = cursor . longValue ( 1 ) ;
SQLiteCursor cursor2 = database . queryFinalized ( " SELECT data FROM messages WHERE uid = " + did + " AND mid IN ( " + last_mid_i + " , " + last_mid + " ) " ) ;
try {
while ( cursor2 . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor2 . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-12-09 19:27:52 +01:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( message ! = null ) {
2016-06-24 12:27:15 +02:00
messageId = message . id ;
2015-12-09 19:27:52 +01:00
}
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-12-09 19:27:52 +01:00
}
cursor2 . dispose ( ) ;
database . executeFast ( " DELETE FROM messages WHERE uid = " + did + " AND mid != " + last_mid_i + " AND mid != " + last_mid ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM messages_holes WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM bot_keyboard WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_counts_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_holes_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
BotQuery . clearBotKeyboard ( did , null ) ;
SQLitePreparedStatement state5 = database . executeFast ( " REPLACE INTO messages_holes VALUES(?, ?, ?) " ) ;
SQLitePreparedStatement state6 = database . executeFast ( " REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?) " ) ;
2016-06-24 12:27:15 +02:00
if ( messageId ! = - 1 ) {
createFirstHoles ( did , state5 , state6 , messageId ) ;
}
2015-12-09 19:27:52 +01:00
state5 . dispose ( ) ;
state6 . dispose ( ) ;
}
cursor . dispose ( ) ;
return ;
2015-02-26 02:32:51 +01:00
}
2015-12-09 19:27:52 +01:00
database . executeFast ( " UPDATE dialogs SET unread_count = 0, unread_count_i = 0 WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
2013-10-25 17:19:00 +02:00
database . executeFast ( " DELETE FROM messages WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
database . executeFast ( " DELETE FROM bot_keyboard WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2015-02-01 19:51:02 +01:00
database . executeFast ( " DELETE FROM media_counts_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( " DELETE FROM messages_holes WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_holes_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
BotQuery . clearBotKeyboard ( did , null ) ;
2015-09-24 22:52:02 +02:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . needReloadRecentDialogsSearch ) ;
}
} ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-12-20 20:25:49 +01:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public void getDialogPhotos ( final int did , final int offset , final int count , final long max_id , final int classGuid ) {
2014-02-04 19:36:55 +01:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor ;
2013-12-20 20:25:49 +01:00
2014-02-04 19:36:55 +01:00
if ( max_id ! = 0 ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM user_photos WHERE uid = %d AND id < %d ORDER BY id DESC LIMIT %d " , did , max_id , count ) ) ;
2014-02-04 19:36:55 +01:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM user_photos WHERE uid = %d ORDER BY id DESC LIMIT %d,%d " , did , offset , count ) ) ;
2014-02-04 19:36:55 +01:00
}
2013-12-20 20:25:49 +01:00
2014-02-04 19:36:55 +01:00
final TLRPC . photos_Photos res = new TLRPC . photos_Photos ( ) ;
2013-12-20 20:25:49 +01:00
2014-02-04 19:36:55 +01:00
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Photo photo = TLRPC . Photo . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2014-02-04 19:36:55 +01:00
res . photos . add ( photo ) ;
}
}
cursor . dispose ( ) ;
Utilities . stageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2016-06-24 12:27:15 +02:00
MessagesController . getInstance ( ) . processLoadedUserPhotos ( res , did , offset , count , max_id , true , classGuid ) ;
2014-02-04 19:36:55 +01:00
}
} ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-12-20 20:25:49 +01:00
}
}
2014-02-11 15:32:09 +01:00
} ) ;
2014-02-04 19:36:55 +01:00
}
2013-12-20 20:25:49 +01:00
2014-02-04 19:36:55 +01:00
public void clearUserPhotos ( final int uid ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM user_photos WHERE uid = " + uid ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-12-20 20:25:49 +01:00
}
2014-02-04 19:36:55 +01:00
}
} ) ;
2013-12-20 20:25:49 +01:00
}
2014-08-22 16:24:33 +02:00
public void clearUserPhoto ( final int uid , final long pid ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM user_photos WHERE uid = " + uid + " AND id = " + pid ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public void putDialogPhotos ( final int did , final TLRPC . photos_Photos photos ) {
2013-12-20 20:25:49 +01:00
if ( photos = = null | | photos . photos . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO user_photos VALUES(?, ?, ?) " ) ;
for ( TLRPC . Photo photo : photos . photos ) {
if ( photo instanceof TLRPC . TL_photoEmpty ) {
continue ;
}
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( photo . getObjectSize ( ) ) ;
2013-12-20 20:25:49 +01:00
photo . serializeToStream ( data ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 1 , did ) ;
2013-12-20 20:25:49 +01:00
state . bindLong ( 2 , photo . id ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 3 , data ) ;
2013-12-20 20:25:49 +01:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2013-12-20 20:25:49 +01:00
}
state . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2017-07-23 14:56:38 +02:00
public void emptyMessagesMedia ( final ArrayList < Integer > mids ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
ArrayList < File > filesToDelete = new ArrayList < > ( ) ;
final ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date, uid FROM messages WHERE mid IN (%s) " , TextUtils . join ( " , " , mids ) ) ) ;
while ( cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
if ( message . media ! = null ) {
if ( message . media . document ! = null ) {
File file = FileLoader . getPathToAttach ( message . media . document , true ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
file = FileLoader . getPathToAttach ( message . media . document . thumb , true ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
message . media . document = new TLRPC . TL_documentEmpty ( ) ;
} else if ( message . media . photo ! = null ) {
for ( TLRPC . PhotoSize photoSize : message . media . photo . sizes ) {
File file = FileLoader . getPathToAttach ( photoSize , true ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
message . media . photo = new TLRPC . TL_photoEmpty ( ) ;
} else {
continue ;
}
message . media . flags = message . media . flags & ~ 1 ;
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = cursor . longValue ( 3 ) ;
messages . add ( message ) ;
}
}
}
cursor . dispose ( ) ;
if ( ! messages . isEmpty ( ) ) {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?) " ) ;
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
state . requery ( ) ;
state . bindLong ( 1 , message . id ) ;
state . bindLong ( 2 , message . dialog_id ) ;
state . bindInteger ( 3 , MessageObject . getUnreadFlags ( message ) ) ;
state . bindInteger ( 4 , message . send_state ) ;
state . bindInteger ( 5 , message . date ) ;
state . bindByteBuffer ( 6 , data ) ;
state . bindInteger ( 7 , ( MessageObject . isOut ( message ) ? 1 : 0 ) ) ;
state . bindInteger ( 8 , message . ttl ) ;
if ( ( message . flags & TLRPC . MESSAGE_FLAG_HAS_VIEWS ) ! = 0 ) {
state . bindInteger ( 9 , message . views ) ;
} else {
state . bindInteger ( 9 , getMessageMediaType ( message ) ) ;
}
state . bindInteger ( 10 , 0 ) ;
state . step ( ) ;
data . reuse ( ) ;
}
state . dispose ( ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . updateMessageMedia , messages . get ( a ) ) ;
}
}
} ) ;
}
FileLoader . getInstance ( ) . deleteFiles ( filesToDelete , 0 ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
public void getNewTask ( final ArrayList < Integer > oldTask , final int channelId ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( oldTask ! = null ) {
2014-10-08 22:22:22 +02:00
String ids = TextUtils . join ( " , " , oldTask ) ;
database . executeFast ( String . format ( Locale . US , " DELETE FROM enc_tasks_v2 WHERE mid IN(%s) " , ids ) ) . stepThis ( ) . dispose ( ) ;
2013-10-25 17:19:00 +02:00
}
int date = 0 ;
2017-07-23 14:56:38 +02:00
int channelId = - 1 ;
2013-10-25 17:19:00 +02:00
ArrayList < Integer > arr = null ;
2014-10-08 22:22:22 +02:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT mid, date FROM enc_tasks_v2 WHERE date = (SELECT min(date) FROM enc_tasks_v2) " ) ;
while ( cursor . next ( ) ) {
2017-07-23 14:56:38 +02:00
long mid = cursor . longValue ( 0 ) ;
if ( channelId = = - 1 ) {
channelId = ( int ) ( mid > > 32 ) ;
if ( channelId < 0 ) {
channelId = 0 ;
}
}
2013-10-25 17:19:00 +02:00
date = cursor . intValue ( 1 ) ;
2014-10-08 22:22:22 +02:00
if ( arr = = null ) {
2015-01-02 23:15:07 +01:00
arr = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
}
2017-07-23 14:56:38 +02:00
arr . add ( ( int ) mid ) ;
2013-10-25 17:19:00 +02:00
}
cursor . dispose ( ) ;
2017-07-23 14:56:38 +02:00
MessagesController . getInstance ( ) . processLoadedDeleteTask ( date , arr , channelId ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2017-07-23 14:56:38 +02:00
public void createTaskForMid ( final int messageId , final int channelId , final int time , final int readTime , final int ttl , final boolean inner ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
int minDate = ( time > readTime ? time : readTime ) + ttl ;
SparseArray < ArrayList < Long > > messages = new SparseArray < > ( ) ;
final ArrayList < Long > midsArray = new ArrayList < > ( ) ;
long mid = messageId ;
if ( channelId ! = 0 ) {
mid | = ( ( long ) channelId ) < < 32 ;
}
midsArray . add ( mid ) ;
messages . put ( minDate , midsArray ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
if ( ! inner ) {
MessagesStorage . getInstance ( ) . markMessagesContentAsRead ( midsArray , 0 ) ;
}
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . messagesReadContent , midsArray ) ;
}
} ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO enc_tasks_v2 VALUES(?, ?) " ) ;
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
int key = messages . keyAt ( a ) ;
ArrayList < Long > arr = messages . get ( key ) ;
for ( int b = 0 ; b < arr . size ( ) ; b + + ) {
state . requery ( ) ;
state . bindLong ( 1 , arr . get ( b ) ) ;
state . bindInteger ( 2 , key ) ;
state . step ( ) ;
}
}
state . dispose ( ) ;
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET ttl = 0 WHERE mid = %d " , mid ) ) . stepThis ( ) . dispose ( ) ;
MessagesController . getInstance ( ) . didAddedNewTask ( minDate , messages ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
2017-07-23 17:27:09 +02:00
public void createTaskForSecretChat ( final int chatId , final int time , final int readTime , final int isOut , final ArrayList < Long > random_ids ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
int minDate = Integer . MAX_VALUE ;
2017-07-23 14:56:38 +02:00
SparseArray < ArrayList < Long > > messages = new SparseArray < > ( ) ;
2016-03-06 02:49:31 +01:00
final ArrayList < Long > midsArray = new ArrayList < > ( ) ;
2014-10-08 22:22:22 +02:00
StringBuilder mids = new StringBuilder ( ) ;
2015-05-21 23:27:27 +02:00
SQLiteCursor cursor ;
2014-10-09 17:55:05 +02:00
if ( random_ids = = null ) {
2017-07-23 17:27:09 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid, ttl FROM messages WHERE uid = %d AND out = %d AND read_state != 0 AND ttl > 0 AND date <= %d AND send_state = 0 AND media != 1 " , ( ( long ) chatId ) < < 32 , isOut , time ) ) ;
2014-10-09 17:55:05 +02:00
} else {
String ids = TextUtils . join ( " , " , random_ids ) ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.mid, m.ttl FROM messages as m INNER JOIN randoms as r ON m.mid = r.mid WHERE r.random_id IN (%s) " , ids ) ) ;
}
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
2014-10-23 17:30:35 +02:00
int ttl = cursor . intValue ( 1 ) ;
2017-07-23 14:56:38 +02:00
long mid = cursor . intValue ( 0 ) ;
2016-03-06 02:49:31 +01:00
if ( random_ids ! = null ) {
2017-07-23 14:56:38 +02:00
midsArray . add ( mid ) ;
2016-03-06 02:49:31 +01:00
}
2014-10-23 17:30:35 +02:00
if ( ttl < = 0 ) {
continue ;
}
2016-10-11 13:57:01 +02:00
int date = ( time > readTime ? time : readTime ) + ttl ;
2013-10-25 17:19:00 +02:00
minDate = Math . min ( minDate , date ) ;
2017-07-23 14:56:38 +02:00
ArrayList < Long > arr = messages . get ( date ) ;
2013-10-25 17:19:00 +02:00
if ( arr = = null ) {
2015-01-02 23:15:07 +01:00
arr = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
messages . put ( date , arr ) ;
}
if ( mids . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
mids . append ( " , " ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-08 22:22:22 +02:00
mids . append ( mid ) ;
2013-10-25 17:19:00 +02:00
arr . add ( mid ) ;
}
cursor . dispose ( ) ;
2016-03-06 02:49:31 +01:00
if ( random_ids ! = null ) {
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
2017-07-23 14:56:38 +02:00
MessagesStorage . getInstance ( ) . markMessagesContentAsRead ( midsArray , 0 ) ;
2016-03-06 02:49:31 +01:00
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . messagesReadContent , midsArray ) ;
}
} ) ;
}
2013-10-25 17:19:00 +02:00
if ( messages . size ( ) ! = 0 ) {
database . beginTransaction ( ) ;
2014-10-08 22:22:22 +02:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO enc_tasks_v2 VALUES(?, ?) " ) ;
2013-10-25 17:19:00 +02:00
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
int key = messages . keyAt ( a ) ;
2017-07-23 14:56:38 +02:00
ArrayList < Long > arr = messages . get ( key ) ;
2016-03-06 02:49:31 +01:00
for ( int b = 0 ; b < arr . size ( ) ; b + + ) {
2014-10-08 22:22:22 +02:00
state . requery ( ) ;
2017-07-23 14:56:38 +02:00
state . bindLong ( 1 , arr . get ( b ) ) ;
2014-10-08 22:22:22 +02:00
state . bindInteger ( 2 , key ) ;
state . step ( ) ;
2013-10-25 17:19:00 +02:00
}
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
2014-10-08 22:22:22 +02:00
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET ttl = 0 WHERE mid IN(%s) " , mids . toString ( ) ) ) . stepThis ( ) . dispose ( ) ;
2014-10-10 19:16:39 +02:00
MessagesController . getInstance ( ) . didAddedNewTask ( minDate , messages ) ;
2013-10-25 17:19:00 +02:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
private void updateDialogsWithReadMessagesInternal ( final ArrayList < Integer > messages , final SparseArray < Long > inbox , final SparseArray < Long > outbox ) {
2013-10-25 17:19:00 +02:00
try {
2015-01-02 23:15:07 +01:00
HashMap < Long , Integer > dialogsToUpdate = new HashMap < > ( ) ;
2015-03-19 00:09:45 +01:00
2013-10-25 17:19:00 +02:00
if ( messages ! = null & & ! messages . isEmpty ( ) ) {
2014-10-08 22:22:22 +02:00
String ids = TextUtils . join ( " , " , messages ) ;
2014-02-28 23:28:25 +01:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT uid, read_state, out FROM messages WHERE mid IN(%s) " , ids ) ) ;
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
2014-02-28 23:28:25 +01:00
int out = cursor . intValue ( 2 ) ;
if ( out ! = 0 ) {
continue ;
}
int read_state = cursor . intValue ( 1 ) ;
if ( read_state ! = 0 ) {
continue ;
}
2013-10-25 17:19:00 +02:00
long uid = cursor . longValue ( 0 ) ;
Integer currentCount = dialogsToUpdate . get ( uid ) ;
if ( currentCount = = null ) {
dialogsToUpdate . put ( uid , 1 ) ;
} else {
dialogsToUpdate . put ( uid , currentCount + 1 ) ;
}
}
cursor . dispose ( ) ;
2016-06-24 12:27:15 +02:00
} else {
if ( inbox ! = null & & inbox . size ( ) ! = 0 ) {
for ( int b = 0 ; b < inbox . size ( ) ; b + + ) {
int key = inbox . keyAt ( b ) ;
long messageId = inbox . get ( key ) ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(mid) FROM messages WHERE uid = %d AND mid > %d AND read_state IN(0,2) AND out = 0 " , key , messageId ) ) ;
if ( cursor . next ( ) ) {
int count = cursor . intValue ( 0 ) ;
dialogsToUpdate . put ( ( long ) key , count ) ;
}
cursor . dispose ( ) ;
2013-10-25 17:19:00 +02:00
2016-06-24 12:27:15 +02:00
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET inbox_max = max((SELECT inbox_max FROM dialogs WHERE did = ?), ?) WHERE did = ? " ) ;
state . requery ( ) ;
state . bindLong ( 1 , key ) ;
state . bindInteger ( 2 , ( int ) messageId ) ;
state . bindLong ( 3 , key ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
if ( outbox ! = null & & outbox . size ( ) ! = 0 ) {
for ( int b = 0 ; b < outbox . size ( ) ; b + + ) {
int key = outbox . keyAt ( b ) ;
long messageId = outbox . get ( key ) ;
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET outbox_max = max((SELECT outbox_max FROM dialogs WHERE did = ?), ?) WHERE did = ? " ) ;
state . requery ( ) ;
state . bindLong ( 1 , key ) ;
state . bindInteger ( 2 , ( int ) messageId ) ;
state . bindLong ( 3 , key ) ;
state . step ( ) ;
state . dispose ( ) ;
}
2013-10-25 17:19:00 +02:00
}
2015-12-09 19:27:52 +01:00
}
2014-02-28 23:28:25 +01:00
2015-12-09 19:27:52 +01:00
if ( ! dialogsToUpdate . isEmpty ( ) ) {
2013-10-25 17:19:00 +02:00
database . beginTransaction ( ) ;
2014-02-28 23:28:25 +01:00
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET unread_count = ? WHERE did = ? " ) ;
for ( HashMap . Entry < Long , Integer > entry : dialogsToUpdate . entrySet ( ) ) {
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
2014-02-28 23:28:25 +01:00
state . bindInteger ( 1 , entry . getValue ( ) ) ;
state . bindLong ( 2 , entry . getKey ( ) ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
}
2014-02-28 23:28:25 +01:00
if ( ! dialogsToUpdate . isEmpty ( ) ) {
2014-03-22 23:31:55 +01:00
MessagesController . getInstance ( ) . processDialogsUpdateRead ( dialogsToUpdate ) ;
2013-10-25 17:19:00 +02:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
2016-06-24 12:27:15 +02:00
public void updateDialogsWithReadMessages ( final SparseArray < Long > inbox , final SparseArray < Long > outbox , boolean useQueue ) {
2015-09-24 22:52:02 +02:00
if ( inbox . size ( ) = = 0 ) {
2013-10-25 17:19:00 +02:00
return ;
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2016-06-24 12:27:15 +02:00
updateDialogsWithReadMessagesInternal ( null , inbox , outbox ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2016-06-24 12:27:15 +02:00
updateDialogsWithReadMessagesInternal ( null , inbox , outbox ) ;
2013-10-25 17:19:00 +02:00
}
}
2015-09-24 22:52:02 +02:00
public void updateChatParticipants ( final TLRPC . ChatParticipants participants ) {
2016-05-25 23:49:47 +02:00
if ( participants = = null ) {
return ;
}
2015-09-24 22:52:02 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-03-16 13:26:32 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT info, pinned FROM chat_settings_v2 WHERE uid = " + participants . chat_id ) ;
2015-09-24 22:52:02 +02:00
TLRPC . ChatFull info = null ;
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-09-24 22:52:02 +02:00
info = TLRPC . ChatFull . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
info . pinned_msg_id = cursor . intValue ( 1 ) ;
2015-09-24 22:52:02 +02:00
}
}
cursor . dispose ( ) ;
if ( info instanceof TLRPC . TL_chatFull ) {
info . participants = participants ;
final TLRPC . ChatFull finalInfo = info ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
2016-03-16 13:26:32 +01:00
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . chatInfoDidLoaded , finalInfo , 0 , false , null ) ;
2015-09-24 22:52:02 +02:00
}
} ) ;
2016-03-16 13:26:32 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chat_settings_v2 VALUES(?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( info . getObjectSize ( ) ) ;
info . serializeToStream ( data ) ;
state . bindInteger ( 1 , info . id ) ;
state . bindByteBuffer ( 2 , data ) ;
2016-03-16 13:26:32 +01:00
state . bindInteger ( 3 , info . pinned_msg_id ) ;
2015-09-24 22:52:02 +02:00
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} ) ;
}
2015-11-26 22:04:02 +01:00
public void updateChannelUsers ( final int channel_id , final ArrayList < TLRPC . ChannelParticipant > participants ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
long did = - channel_id ;
database . executeFast ( " DELETE FROM channel_users_v2 WHERE did = " + did ) . stepThis ( ) . dispose ( ) ;
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO channel_users_v2 VALUES(?, ?, ?, ?) " ) ;
NativeByteBuffer data ;
int date = ( int ) ( System . currentTimeMillis ( ) / 1000 ) ;
for ( int a = 0 ; a < participants . size ( ) ; a + + ) {
TLRPC . ChannelParticipant participant = participants . get ( a ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , participant . user_id ) ;
state . bindInteger ( 3 , date ) ;
data = new NativeByteBuffer ( participant . getObjectSize ( ) ) ;
participant . serializeToStream ( data ) ;
state . bindByteBuffer ( 4 , data ) ;
data . reuse ( ) ;
state . step ( ) ;
date - - ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
loadChatInfo ( channel_id , null , false , true ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
}
}
} ) ;
}
public void saveBotCache ( final String key , final TLObject result ) {
if ( result = = null | | TextUtils . isEmpty ( key ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
int currentDate = ConnectionsManager . getInstance ( ) . getCurrentTime ( ) ;
if ( result instanceof TLRPC . TL_messages_botCallbackAnswer ) {
currentDate + = ( ( TLRPC . TL_messages_botCallbackAnswer ) result ) . cache_time ;
} else if ( result instanceof TLRPC . TL_messages_botResults ) {
currentDate + = ( ( TLRPC . TL_messages_botResults ) result ) . cache_time ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO botcache VALUES(?, ?, ?) " ) ;
NativeByteBuffer data = new NativeByteBuffer ( result . getObjectSize ( ) ) ;
result . serializeToStream ( data ) ;
state . bindString ( 1 , key ) ;
state . bindInteger ( 2 , currentDate ) ;
state . bindByteBuffer ( 3 , data ) ;
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
public void getBotCache ( final String key , final RequestDelegate requestDelegate ) {
if ( key = = null | | requestDelegate = = null ) {
return ;
}
final int currentDate = ConnectionsManager . getInstance ( ) . getCurrentTime ( ) ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
TLObject result = null ;
try {
database . executeFast ( " DELETE FROM botcache WHERE date < " + currentDate ) . stepThis ( ) . dispose ( ) ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM botcache WHERE id = '%s' " , key ) ) ;
if ( cursor . next ( ) ) {
try {
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
int constructor = data . readInt32 ( false ) ;
if ( constructor = = TLRPC . TL_messages_botCallbackAnswer . constructor ) {
result = TLRPC . TL_messages_botCallbackAnswer . TLdeserialize ( data , constructor , false ) ;
} else {
result = TLRPC . TL_messages_botResults . TLdeserialize ( data , constructor , false ) ;
}
data . reuse ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
cursor . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
} finally {
requestDelegate . run ( result , null ) ;
2015-11-26 22:04:02 +01:00
}
}
} ) ;
2017-03-31 01:58:05 +02:00
2015-11-26 22:04:02 +01:00
}
2015-09-24 22:52:02 +02:00
public void updateChatInfo ( final TLRPC . ChatFull info , final boolean ifExist ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( ifExist ) {
2015-09-24 22:52:02 +02:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT uid FROM chat_settings_v2 WHERE uid = " + info . id ) ;
2016-05-25 23:49:47 +02:00
boolean exist = cursor . next ( ) ;
2013-10-25 17:19:00 +02:00
cursor . dispose ( ) ;
2016-05-25 23:49:47 +02:00
if ( ! exist ) {
2013-10-25 17:19:00 +02:00
return ;
}
}
2016-03-16 13:26:32 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chat_settings_v2 VALUES(?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( info . getObjectSize ( ) ) ;
2013-10-25 17:19:00 +02:00
info . serializeToStream ( data ) ;
2015-09-24 22:52:02 +02:00
state . bindInteger ( 1 , info . id ) ;
state . bindByteBuffer ( 2 , data ) ;
2016-03-16 13:26:32 +01:00
state . bindInteger ( 3 , info . pinned_msg_id ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
state . dispose ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
if ( info instanceof TLRPC . TL_channelFull ) {
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT date, pts, last_mid, inbox_max, outbox_max, pinned FROM dialogs WHERE did = " + ( - info . id ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
2016-06-24 12:27:15 +02:00
int inbox_max = cursor . intValue ( 3 ) ;
if ( inbox_max < = info . read_inbox_max_id ) {
2016-05-25 23:49:47 +02:00
int inbox_diff = info . read_inbox_max_id - inbox_max ;
2016-06-24 12:27:15 +02:00
if ( inbox_diff < info . unread_count ) {
info . unread_count = inbox_diff ;
2016-05-25 23:49:47 +02:00
}
int dialog_date = cursor . intValue ( 0 ) ;
2016-06-24 12:27:15 +02:00
int pts = cursor . intValue ( 1 ) ;
long last_mid = cursor . longValue ( 2 ) ;
int outbox_max = cursor . intValue ( 4 ) ;
2017-03-31 01:58:05 +02:00
int pinned = cursor . intValue ( 5 ) ;
2016-05-25 23:49:47 +02:00
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2016-05-25 23:49:47 +02:00
state . bindLong ( 1 , - info . id ) ;
state . bindInteger ( 2 , dialog_date ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 3 , info . unread_count ) ;
2016-05-25 23:49:47 +02:00
state . bindLong ( 4 , last_mid ) ;
state . bindInteger ( 5 , info . read_inbox_max_id ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 6 , Math . max ( outbox_max , info . read_outbox_max_id ) ) ;
state . bindLong ( 7 , 0 ) ;
state . bindInteger ( 8 , 0 ) ;
2016-05-25 23:49:47 +02:00
state . bindInteger ( 9 , pts ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 10 , 0 ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 11 , pinned ) ;
2016-05-25 23:49:47 +02:00
state . step ( ) ;
state . dispose ( ) ;
}
2015-09-24 22:52:02 +02:00
}
cursor . dispose ( ) ;
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2016-03-16 13:26:32 +01:00
public void updateChannelPinnedMessage ( final int channelId , final int messageId ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT info, pinned FROM chat_settings_v2 WHERE uid = " + channelId ) ;
TLRPC . ChatFull info = null ;
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-16 13:26:32 +01:00
info = TLRPC . ChatFull . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
info . pinned_msg_id = cursor . intValue ( 1 ) ;
}
}
cursor . dispose ( ) ;
if ( info instanceof TLRPC . TL_channelFull ) {
info . pinned_msg_id = messageId ;
info . flags | = 32 ;
final TLRPC . ChatFull finalInfo = info ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . chatInfoDidLoaded , finalInfo , 0 , false , null ) ;
}
} ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chat_settings_v2 VALUES(?, ?, ?) " ) ;
NativeByteBuffer data = new NativeByteBuffer ( info . getObjectSize ( ) ) ;
info . serializeToStream ( data ) ;
state . bindInteger ( 1 , channelId ) ;
state . bindByteBuffer ( 2 , data ) ;
state . bindInteger ( 3 , info . pinned_msg_id ) ;
state . step ( ) ;
state . dispose ( ) ;
data . reuse ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-16 13:26:32 +01:00
}
}
} ) ;
}
2015-11-26 22:04:02 +01:00
public void updateChatInfo ( final int chat_id , final int user_id , final int what , final int invited_id , final int version ) {
2014-02-04 19:36:55 +01:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-03-16 13:26:32 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT info, pinned FROM chat_settings_v2 WHERE uid = " + chat_id ) ;
2015-09-24 22:52:02 +02:00
TLRPC . ChatFull info = null ;
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
2014-02-04 19:36:55 +01:00
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-09-24 22:52:02 +02:00
info = TLRPC . ChatFull . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
info . pinned_msg_id = cursor . intValue ( 1 ) ;
2014-02-04 19:36:55 +01:00
}
}
cursor . dispose ( ) ;
2015-09-24 22:52:02 +02:00
if ( info instanceof TLRPC . TL_chatFull ) {
2015-11-26 22:04:02 +01:00
if ( what = = 1 ) {
2015-09-24 22:52:02 +02:00
for ( int a = 0 ; a < info . participants . participants . size ( ) ; a + + ) {
2015-11-26 22:04:02 +01:00
TLRPC . ChatParticipant participant = info . participants . participants . get ( a ) ;
2014-02-04 19:36:55 +01:00
if ( participant . user_id = = user_id ) {
2015-09-24 22:52:02 +02:00
info . participants . participants . remove ( a ) ;
2014-02-04 19:36:55 +01:00
break ;
}
}
2015-11-26 22:04:02 +01:00
} else if ( what = = 0 ) {
for ( TLRPC . ChatParticipant part : info . participants . participants ) {
2014-07-31 02:50:12 +02:00
if ( part . user_id = = user_id ) {
return ;
}
}
2014-02-04 19:36:55 +01:00
TLRPC . TL_chatParticipant participant = new TLRPC . TL_chatParticipant ( ) ;
participant . user_id = user_id ;
participant . inviter_id = invited_id ;
2014-03-22 23:31:55 +01:00
participant . date = ConnectionsManager . getInstance ( ) . getCurrentTime ( ) ;
2015-09-24 22:52:02 +02:00
info . participants . participants . add ( participant ) ;
2015-11-26 22:04:02 +01:00
} else if ( what = = 2 ) {
for ( int a = 0 ; a < info . participants . participants . size ( ) ; a + + ) {
TLRPC . ChatParticipant participant = info . participants . participants . get ( a ) ;
if ( participant . user_id = = user_id ) {
TLRPC . ChatParticipant newParticipant ;
if ( invited_id = = 1 ) {
newParticipant = new TLRPC . TL_chatParticipantAdmin ( ) ;
newParticipant . user_id = participant . user_id ;
newParticipant . date = participant . date ;
newParticipant . inviter_id = participant . inviter_id ;
} else {
newParticipant = new TLRPC . TL_chatParticipant ( ) ;
newParticipant . user_id = participant . user_id ;
newParticipant . date = participant . date ;
newParticipant . inviter_id = participant . inviter_id ;
}
info . participants . participants . set ( a , newParticipant ) ;
break ;
}
}
2014-02-04 19:36:55 +01:00
}
2015-09-24 22:52:02 +02:00
info . participants . version = version ;
2014-02-04 19:36:55 +01:00
2015-09-24 22:52:02 +02:00
final TLRPC . ChatFull finalInfo = info ;
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-02-04 19:36:55 +01:00
@Override
public void run ( ) {
2016-03-16 13:26:32 +01:00
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . chatInfoDidLoaded , finalInfo , 0 , false , null ) ;
2014-02-04 19:36:55 +01:00
}
} ) ;
2016-03-16 13:26:32 +01:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chat_settings_v2 VALUES(?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( info . getObjectSize ( ) ) ;
2014-02-04 19:36:55 +01:00
info . serializeToStream ( data ) ;
state . bindInteger ( 1 , chat_id ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 2 , data ) ;
2016-03-16 13:26:32 +01:00
state . bindInteger ( 3 , info . pinned_msg_id ) ;
2014-02-04 19:36:55 +01:00
state . step ( ) ;
state . dispose ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-02-04 19:36:55 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-02-04 19:36:55 +01:00
}
}
} ) ;
}
2015-11-26 22:04:02 +01:00
public boolean isMigratedChat ( final int chat_id ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
final boolean result [ ] = new boolean [ 1 ] ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT info FROM chat_settings_v2 WHERE uid = " + chat_id ) ;
TLRPC . ChatFull info = null ;
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-11-26 22:04:02 +01:00
info = TLRPC . ChatFull . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-11-26 22:04:02 +01:00
}
}
cursor . dispose ( ) ;
result [ 0 ] = info instanceof TLRPC . TL_channelFull & & info . migrated_from_chat_id ! = 0 ;
if ( semaphore ! = null ) {
semaphore . release ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-11-26 22:04:02 +01:00
} finally {
if ( semaphore ! = null ) {
semaphore . release ( ) ;
}
}
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-11-26 22:04:02 +01:00
}
return result [ 0 ] ;
}
public void loadChatInfo ( final int chat_id , final Semaphore semaphore , final boolean force , final boolean byChannelUsers ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2016-04-22 15:49:00 +02:00
MessageObject pinnedMessageObject = null ;
TLRPC . ChatFull info = null ;
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
try {
2016-03-16 13:26:32 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT info, pinned FROM chat_settings_v2 WHERE uid = " + chat_id ) ;
2013-10-25 17:19:00 +02:00
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-09-24 22:52:02 +02:00
info = TLRPC . ChatFull . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
info . pinned_msg_id = cursor . intValue ( 1 ) ;
2013-10-25 17:19:00 +02:00
}
}
cursor . dispose ( ) ;
2015-09-24 22:52:02 +02:00
if ( info instanceof TLRPC . TL_chatFull ) {
2014-10-08 22:22:22 +02:00
StringBuilder usersToLoad = new StringBuilder ( ) ;
2015-09-24 22:52:02 +02:00
for ( int a = 0 ; a < info . participants . participants . size ( ) ; a + + ) {
2015-11-26 22:04:02 +01:00
TLRPC . ChatParticipant c = info . participants . participants . get ( a ) ;
2015-09-24 22:52:02 +02:00
if ( usersToLoad . length ( ) ! = 0 ) {
usersToLoad . append ( " , " ) ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
usersToLoad . append ( c . user_id ) ;
2013-10-25 17:19:00 +02:00
}
if ( usersToLoad . length ( ) ! = 0 ) {
2014-10-23 17:30:35 +02:00
getUsersInternal ( usersToLoad . toString ( ) , loadedUsers ) ;
2013-10-25 17:19:00 +02:00
}
2015-11-26 22:04:02 +01:00
} else if ( info instanceof TLRPC . TL_channelFull ) {
cursor = database . queryFinalized ( " SELECT us.data, us.status, cu.data, cu.date FROM channel_users_v2 as cu LEFT JOIN users as us ON us.uid = cu.uid WHERE cu.did = " + ( - chat_id ) + " ORDER BY cu.date DESC " ) ;
info . participants = new TLRPC . TL_chatParticipants ( ) ;
while ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
TLRPC . User user = null ;
TLRPC . ChannelParticipant participant = null ;
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
user = TLRPC . User . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
}
data = cursor . byteBufferValue ( 2 ) ;
if ( data ! = null ) {
participant = TLRPC . ChannelParticipant . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
}
if ( user ! = null & & participant ! = null ) {
if ( user . status ! = null ) {
user . status . expires = cursor . intValue ( 1 ) ;
2015-11-26 22:04:02 +01:00
}
2016-05-25 23:49:47 +02:00
loadedUsers . add ( user ) ;
participant . date = cursor . intValue ( 3 ) ;
TLRPC . TL_chatChannelParticipant chatChannelParticipant = new TLRPC . TL_chatChannelParticipant ( ) ;
chatChannelParticipant . user_id = participant . user_id ;
chatChannelParticipant . date = participant . date ;
chatChannelParticipant . inviter_id = participant . inviter_id ;
chatChannelParticipant . channelParticipant = participant ;
info . participants . participants . add ( chatChannelParticipant ) ;
2015-11-26 22:04:02 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-11-26 22:04:02 +01:00
}
}
cursor . dispose ( ) ;
StringBuilder usersToLoad = new StringBuilder ( ) ;
for ( int a = 0 ; a < info . bot_info . size ( ) ; a + + ) {
TLRPC . BotInfo botInfo = info . bot_info . get ( a ) ;
if ( usersToLoad . length ( ) ! = 0 ) {
usersToLoad . append ( " , " ) ;
}
usersToLoad . append ( botInfo . user_id ) ;
}
if ( usersToLoad . length ( ) ! = 0 ) {
getUsersInternal ( usersToLoad . toString ( ) , loadedUsers ) ;
}
2013-10-25 17:19:00 +02:00
}
2014-08-08 12:17:06 +02:00
if ( semaphore ! = null ) {
semaphore . release ( ) ;
}
2016-03-16 13:26:32 +01:00
if ( info instanceof TLRPC . TL_channelFull & & info . pinned_msg_id ! = 0 ) {
pinnedMessageObject = MessagesQuery . loadPinnedMessage ( chat_id , info . pinned_msg_id , false ) ;
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-08 12:17:06 +02:00
} finally {
2016-04-22 15:49:00 +02:00
MessagesController . getInstance ( ) . processChatInfo ( chat_id , info , loadedUsers , true , force , byChannelUsers , pinnedMessageObject ) ;
2014-08-08 12:17:06 +02:00
if ( semaphore ! = null ) {
semaphore . release ( ) ;
}
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public void processPendingRead ( final long dialog_id , final long max_id , final int max_date ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-06-24 12:27:15 +02:00
database . beginTransaction ( ) ;
SQLitePreparedStatement state ;
int lower_id = ( int ) dialog_id ;
if ( lower_id ! = 0 ) {
state = database . executeFast ( " UPDATE messages SET read_state = read_state | 1 WHERE uid = ? AND mid <= ? AND read_state IN(0,2) AND out = 0 " ) ;
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
state . bindLong ( 1 , dialog_id ) ;
2016-06-24 12:27:15 +02:00
state . bindLong ( 2 , max_id ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
2016-06-24 12:27:15 +02:00
state . dispose ( ) ;
} else {
state = database . executeFast ( " UPDATE messages SET read_state = read_state | 1 WHERE uid = ? AND date <= ? AND read_state IN(0,2) AND out = 0 " ) ;
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
2016-06-24 12:27:15 +02:00
state . bindLong ( 1 , dialog_id ) ;
state . bindInteger ( 2 , max_date ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
state . dispose ( ) ;
2016-06-24 12:27:15 +02:00
}
2013-10-25 17:19:00 +02:00
2016-06-24 12:27:15 +02:00
int currentMaxId = 0 ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT inbox_max FROM dialogs WHERE did = " + dialog_id ) ;
if ( cursor . next ( ) ) {
currentMaxId = cursor . intValue ( 0 ) ;
2013-10-25 17:19:00 +02:00
}
2016-06-24 12:27:15 +02:00
cursor . dispose ( ) ;
currentMaxId = Math . max ( currentMaxId , ( int ) max_id ) ;
state = database . executeFast ( " UPDATE dialogs SET unread_count = 0, unread_count_i = 0, inbox_max = ? WHERE did = ? " ) ;
state . requery ( ) ;
state . bindInteger ( 1 , currentMaxId ) ;
state . bindLong ( 2 , dialog_id ) ;
state . step ( ) ;
state . dispose ( ) ;
database . commitTransaction ( ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2015-11-26 22:04:02 +01:00
public void putContacts ( ArrayList < TLRPC . TL_contact > contacts , final boolean deleteAll ) {
2013-10-25 17:19:00 +02:00
if ( contacts . isEmpty ( ) ) {
return ;
}
2015-11-26 22:04:02 +01:00
final ArrayList < TLRPC . TL_contact > contactsCopy = new ArrayList < > ( contacts ) ;
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( deleteAll ) {
database . executeFast ( " DELETE FROM contacts WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
}
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO contacts VALUES(?, ?) " ) ;
2015-11-26 22:04:02 +01:00
for ( int a = 0 ; a < contactsCopy . size ( ) ; a + + ) {
TLRPC . TL_contact contact = contactsCopy . get ( a ) ;
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
state . bindInteger ( 1 , contact . user_id ) ;
state . bindInteger ( 2 , contact . mutual ? 1 : 0 ) ;
state . step ( ) ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2014-02-04 19:36:55 +01:00
public void deleteContacts ( final ArrayList < Integer > uids ) {
if ( uids = = null | | uids . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-10-08 22:22:22 +02:00
String ids = TextUtils . join ( " , " , uids ) ;
2014-02-28 23:28:25 +01:00
database . executeFast ( " DELETE FROM contacts WHERE uid IN( " + ids + " ) " ) . stepThis ( ) . dispose ( ) ;
2014-02-04 19:36:55 +01:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-02-04 19:36:55 +01:00
}
}
} ) ;
}
public void applyPhoneBookUpdates ( final String adds , final String deletes ) {
if ( adds . length ( ) = = 0 & & deletes . length ( ) = = 0 ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( adds . length ( ) ! = 0 ) {
2014-02-28 23:28:25 +01:00
database . executeFast ( String . format ( Locale . US , " UPDATE user_phones_v6 SET deleted = 0 WHERE sphone IN(%s) " , adds ) ) . stepThis ( ) . dispose ( ) ;
2014-02-04 19:36:55 +01:00
}
if ( deletes . length ( ) ! = 0 ) {
2014-02-28 23:28:25 +01:00
database . executeFast ( String . format ( Locale . US , " UPDATE user_phones_v6 SET deleted = 1 WHERE sphone IN(%s) " , deletes ) ) . stepThis ( ) . dispose ( ) ;
2014-02-04 19:36:55 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-02-04 19:36:55 +01:00
}
}
} ) ;
}
public void putCachedPhoneBook ( final HashMap < Integer , ContactsController . Contact > contactHashMap ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO user_contacts_v6 VALUES(?, ?, ?) " ) ;
SQLitePreparedStatement state2 = database . executeFast ( " REPLACE INTO user_phones_v6 VALUES(?, ?, ?, ?) " ) ;
for ( HashMap . Entry < Integer , ContactsController . Contact > entry : contactHashMap . entrySet ( ) ) {
ContactsController . Contact contact = entry . getValue ( ) ;
2014-02-28 23:28:25 +01:00
if ( contact . phones . isEmpty ( ) | | contact . shortPhones . isEmpty ( ) ) {
continue ;
}
2014-02-04 19:36:55 +01:00
state . requery ( ) ;
state . bindInteger ( 1 , contact . id ) ;
state . bindString ( 2 , contact . first_name ) ;
state . bindString ( 3 , contact . last_name ) ;
state . step ( ) ;
for ( int a = 0 ; a < contact . phones . size ( ) ; a + + ) {
state2 . requery ( ) ;
state2 . bindInteger ( 1 , contact . id ) ;
state2 . bindString ( 2 , contact . phones . get ( a ) ) ;
state2 . bindString ( 3 , contact . shortPhones . get ( a ) ) ;
state2 . bindInteger ( 4 , contact . phoneDeleted . get ( a ) ) ;
state2 . step ( ) ;
}
}
state . dispose ( ) ;
state2 . dispose ( ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-02-04 19:36:55 +01:00
}
}
} ) ;
}
public void getCachedPhoneBook ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-01-02 23:15:07 +01:00
HashMap < Integer , ContactsController . Contact > contactHashMap = new HashMap < > ( ) ;
2014-02-04 19:36:55 +01:00
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT us.uid, us.fname, us.sname, up.phone, up.sphone, up.deleted FROM user_contacts_v6 as us LEFT JOIN user_phones_v6 as up ON us.uid = up.uid WHERE 1 " ) ;
while ( cursor . next ( ) ) {
int uid = cursor . intValue ( 0 ) ;
ContactsController . Contact contact = contactHashMap . get ( uid ) ;
if ( contact = = null ) {
contact = new ContactsController . Contact ( ) ;
contact . first_name = cursor . stringValue ( 1 ) ;
contact . last_name = cursor . stringValue ( 2 ) ;
2017-03-31 01:58:05 +02:00
if ( contact . first_name = = null ) {
contact . first_name = " " ;
}
if ( contact . last_name = = null ) {
contact . last_name = " " ;
}
2014-02-04 19:36:55 +01:00
contact . id = uid ;
contactHashMap . put ( uid , contact ) ;
}
2014-02-28 23:28:25 +01:00
String phone = cursor . stringValue ( 3 ) ;
if ( phone = = null ) {
continue ;
}
contact . phones . add ( phone ) ;
String sphone = cursor . stringValue ( 4 ) ;
if ( sphone = = null ) {
continue ;
}
if ( sphone . length ( ) = = 8 & & phone . length ( ) ! = 8 ) {
sphone = PhoneFormat . stripExceptNumbers ( phone ) ;
}
contact . shortPhones . add ( sphone ) ;
2014-02-04 19:36:55 +01:00
contact . phoneDeleted . add ( cursor . intValue ( 5 ) ) ;
contact . phoneTypes . add ( " " ) ;
}
cursor . dispose ( ) ;
} catch ( Exception e ) {
2014-02-11 15:32:09 +01:00
contactHashMap . clear ( ) ;
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-02-04 19:36:55 +01:00
}
2016-06-24 12:27:15 +02:00
ContactsController . getInstance ( ) . performSyncPhoneBook ( contactHashMap , true , true , false , false ) ;
2014-02-04 19:36:55 +01:00
}
2014-02-11 15:32:09 +01:00
} ) ;
2014-02-04 19:36:55 +01:00
}
2013-10-25 17:19:00 +02:00
public void getContacts ( ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . TL_contact > contacts = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
try {
SQLiteCursor cursor = database . queryFinalized ( " SELECT * FROM contacts WHERE 1 " ) ;
2014-10-08 22:22:22 +02:00
StringBuilder uids = new StringBuilder ( ) ;
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
int user_id = cursor . intValue ( 0 ) ;
TLRPC . TL_contact contact = new TLRPC . TL_contact ( ) ;
contact . user_id = user_id ;
contact . mutual = cursor . intValue ( 1 ) = = 1 ;
if ( uids . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
uids . append ( " , " ) ;
2013-10-25 17:19:00 +02:00
}
contacts . add ( contact ) ;
2014-10-08 22:22:22 +02:00
uids . append ( contact . user_id ) ;
2013-10-25 17:19:00 +02:00
}
cursor . dispose ( ) ;
if ( uids . length ( ) ! = 0 ) {
2014-10-23 17:30:35 +02:00
getUsersInternal ( uids . toString ( ) , users ) ;
2013-10-25 17:19:00 +02:00
}
} catch ( Exception e ) {
2014-02-11 15:32:09 +01:00
contacts . clear ( ) ;
users . clear ( ) ;
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
2014-03-22 23:31:55 +01:00
ContactsController . getInstance ( ) . processLoadedContacts ( contacts , users , 1 ) ;
2013-10-25 17:19:00 +02:00
}
2014-02-11 15:32:09 +01:00
} ) ;
2013-10-25 17:19:00 +02:00
}
2014-08-22 16:24:33 +02:00
public void getUnsentMessages ( final int count ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-01-02 23:15:07 +01:00
HashMap < Integer , TLRPC . Message > messageHashMap = new HashMap < > ( ) ;
ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
2015-11-26 22:04:02 +01:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
2015-01-02 23:15:07 +01:00
ArrayList < Integer > broadcastIds = new ArrayList < > ( ) ;
ArrayList < Integer > encryptedChatIds = new ArrayList < > ( ) ;
2015-11-26 22:04:02 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.uid, s.seq_in, s.seq_out, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid LEFT JOIN messages_seq as s ON m.mid = s.mid WHERE m.mid < 0 AND m.send_state = 1 ORDER BY m.mid DESC LIMIT " + count ) ;
2014-08-22 16:24:33 +02:00
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-01-02 23:15:07 +01:00
if ( ! messageHashMap . containsKey ( message . id ) ) {
2015-05-03 13:48:36 +02:00
MessageObject . setUnreadFlags ( message , cursor . intValue ( 0 ) ) ;
2015-01-02 23:15:07 +01:00
message . id = cursor . intValue ( 3 ) ;
message . date = cursor . intValue ( 4 ) ;
if ( ! cursor . isNull ( 5 ) ) {
message . random_id = cursor . longValue ( 5 ) ;
}
message . dialog_id = cursor . longValue ( 6 ) ;
message . seq_in = cursor . intValue ( 7 ) ;
message . seq_out = cursor . intValue ( 8 ) ;
2015-11-26 22:04:02 +01:00
message . ttl = cursor . intValue ( 9 ) ;
2015-01-02 23:15:07 +01:00
messages . add ( message ) ;
messageHashMap . put ( message . id , message ) ;
int lower_id = ( int ) message . dialog_id ;
int high_id = ( int ) ( message . dialog_id > > 32 ) ;
if ( lower_id ! = 0 ) {
if ( high_id = = 1 ) {
if ( ! broadcastIds . contains ( lower_id ) ) {
broadcastIds . add ( lower_id ) ;
2014-08-22 16:24:33 +02:00
}
} else {
2015-01-02 23:15:07 +01:00
if ( lower_id < 0 ) {
2015-11-26 22:04:02 +01:00
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
2015-01-02 23:15:07 +01:00
}
} else {
2015-11-26 22:04:02 +01:00
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
2015-01-02 23:15:07 +01:00
}
2014-08-22 16:24:33 +02:00
}
}
2015-01-02 23:15:07 +01:00
} else {
if ( ! encryptedChatIds . contains ( high_id ) ) {
encryptedChatIds . add ( high_id ) ;
}
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2015-01-02 23:15:07 +01:00
message . send_state = cursor . intValue ( 2 ) ;
2016-06-24 12:27:15 +02:00
if ( message . to_id . channel_id = = 0 & & ! MessageObject . isUnread ( message ) & & lower_id ! = 0 | | message . id > 0 ) { //TODO check
2015-01-02 23:15:07 +01:00
message . send_state = 0 ;
}
if ( lower_id = = 0 & & ! cursor . isNull ( 5 ) ) {
message . random_id = cursor . longValue ( 5 ) ;
}
2014-08-22 16:24:33 +02:00
}
}
}
cursor . dispose ( ) ;
2014-10-08 22:22:22 +02:00
2014-08-22 16:24:33 +02:00
if ( ! encryptedChatIds . isEmpty ( ) ) {
2015-11-26 22:04:02 +01:00
getEncryptedChatsInternal ( TextUtils . join ( " , " , encryptedChatIds ) , encryptedChats , usersToLoad ) ;
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
if ( ! usersToLoad . isEmpty ( ) ) {
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
if ( ! chatsToLoad . isEmpty ( ) | | ! broadcastIds . isEmpty ( ) ) {
2014-10-08 22:22:22 +02:00
StringBuilder stringToLoad = new StringBuilder ( ) ;
2015-11-26 22:04:02 +01:00
for ( int a = 0 ; a < chatsToLoad . size ( ) ; a + + ) {
Integer cid = chatsToLoad . get ( a ) ;
2014-08-22 16:24:33 +02:00
if ( stringToLoad . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
stringToLoad . append ( " , " ) ;
2014-08-22 16:24:33 +02:00
}
2014-10-08 22:22:22 +02:00
stringToLoad . append ( cid ) ;
2014-08-22 16:24:33 +02:00
}
2015-11-26 22:04:02 +01:00
for ( int a = 0 ; a < broadcastIds . size ( ) ; a + + ) {
Integer cid = broadcastIds . get ( a ) ;
2014-08-22 16:24:33 +02:00
if ( stringToLoad . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
stringToLoad . append ( " , " ) ;
2014-08-22 16:24:33 +02:00
}
2014-10-08 22:22:22 +02:00
stringToLoad . append ( - cid ) ;
2014-08-22 16:24:33 +02:00
}
2014-10-23 17:30:35 +02:00
getChatsInternal ( stringToLoad . toString ( ) , chats ) ;
2014-08-22 16:24:33 +02:00
}
SendMessagesHelper . getInstance ( ) . processUnsentMessages ( messages , users , chats , encryptedChats ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
2016-03-06 02:49:31 +01:00
public boolean checkMessageId ( final long dialog_id , final int mid ) {
final boolean [ ] result = new boolean [ 1 ] ;
final Semaphore semaphore = new Semaphore ( 0 ) ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLiteCursor cursor = null ;
try {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM messages WHERE uid = %d AND mid = %d " , dialog_id , mid ) ) ;
if ( cursor . next ( ) ) {
result [ 0 ] = true ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-06 02:49:31 +01:00
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
}
semaphore . release ( ) ;
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-06 02:49:31 +01:00
}
return result [ 0 ] ;
}
2017-03-31 01:58:05 +02:00
public void getMessages ( final long dialog_id , final int count , final int max_id , final int offset_date , final int minDate , final int classGuid , final int load_type , final boolean isChannel , final int loadIndex ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
TLRPC . TL_messages_messages res = new TLRPC . TL_messages_messages ( ) ;
2013-12-20 20:25:49 +01:00
int count_unread = 0 ;
int count_query = count ;
2014-08-02 01:31:15 +02:00
int offset_query = 0 ;
2013-12-20 20:25:49 +01:00
int min_unread_id = 0 ;
2014-10-31 20:02:29 +01:00
int last_message_id = 0 ;
2015-12-09 19:27:52 +01:00
boolean queryFromServer = false ;
2013-12-20 20:25:49 +01:00
int max_unread_date = 0 ;
2015-09-24 22:52:02 +02:00
long messageMaxId = max_id ;
2015-12-09 19:27:52 +01:00
int max_id_query = max_id ;
2017-03-31 01:58:05 +02:00
int max_id_override = max_id ;
2015-09-24 22:52:02 +02:00
int channelId = 0 ;
2016-06-24 12:27:15 +02:00
if ( isChannel ) {
2015-09-24 22:52:02 +02:00
channelId = - ( int ) dialog_id ;
}
if ( messageMaxId ! = 0 & & channelId ! = 0 ) {
messageMaxId | = ( ( long ) channelId ) < < 32 ;
}
boolean isEnd = false ;
2017-03-31 01:58:05 +02:00
int num = dialog_id = = 777000 ? 10 : 1 ;
2013-10-25 17:19:00 +02:00
try {
2015-11-26 22:04:02 +01:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
2015-09-24 22:52:02 +02:00
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
ArrayList < Long > replyMessages = new ArrayList < > ( ) ;
2015-03-19 00:09:45 +01:00
HashMap < Integer , ArrayList < TLRPC . Message > > replyMessageOwners = new HashMap < > ( ) ;
2016-03-06 02:49:31 +01:00
HashMap < Long , ArrayList < TLRPC . Message > > replyMessageRandomOwners = new HashMap < > ( ) ;
2013-10-25 17:19:00 +02:00
2015-05-21 23:27:27 +02:00
SQLiteCursor cursor ;
2015-12-09 19:27:52 +01:00
int lower_id = ( int ) dialog_id ;
2013-10-25 17:19:00 +02:00
if ( lower_id ! = 0 ) {
2017-03-31 01:58:05 +02:00
if ( load_type = = 3 & & minDate = = 0 ) {
cursor = database . queryFinalized ( " SELECT inbox_max, unread_count, date FROM dialogs WHERE did = " + dialog_id ) ;
if ( cursor . next ( ) ) {
min_unread_id = cursor . intValue ( 0 ) + 1 ;
count_unread = cursor . intValue ( 1 ) ;
max_unread_date = cursor . intValue ( 2 ) ;
}
cursor . dispose ( ) ;
} else if ( load_type ! = 1 & & load_type ! = 3 & & load_type ! = 4 & & minDate = = 0 ) {
2015-12-09 19:27:52 +01:00
if ( load_type = = 2 ) {
cursor = database . queryFinalized ( " SELECT inbox_max, unread_count, date FROM dialogs WHERE did = " + dialog_id ) ;
if ( cursor . next ( ) ) {
messageMaxId = max_id_query = min_unread_id = cursor . intValue ( 0 ) ;
count_unread = cursor . intValue ( 1 ) ;
max_unread_date = cursor . intValue ( 2 ) ;
queryFromServer = true ;
if ( messageMaxId ! = 0 & & channelId ! = 0 ) {
messageMaxId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
if ( ! queryFromServer ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0 " , dialog_id ) ) ;
2015-12-09 19:27:52 +01:00
if ( cursor . next ( ) ) {
min_unread_id = cursor . intValue ( 0 ) ;
max_unread_date = cursor . intValue ( 1 ) ;
}
cursor . dispose ( ) ;
if ( min_unread_id ! = 0 ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(*) FROM messages WHERE uid = %d AND mid >= %d AND out = 0 AND read_state IN(0,2) " , dialog_id , min_unread_id ) ) ;
2015-12-09 19:27:52 +01:00
if ( cursor . next ( ) ) {
count_unread = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
}
2016-04-22 15:49:00 +02:00
} else if ( max_id_query = = 0 ) {
int existingUnreadCount = 0 ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(*) FROM messages WHERE uid = %d AND mid > 0 AND out = 0 AND read_state IN(0,2) " , dialog_id ) ) ;
2016-04-22 15:49:00 +02:00
if ( cursor . next ( ) ) {
existingUnreadCount = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( existingUnreadCount = = count_unread ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > 0 " , dialog_id ) ) ;
2016-04-22 15:49:00 +02:00
if ( cursor . next ( ) ) {
messageMaxId = max_id_query = min_unread_id = cursor . intValue ( 0 ) ;
2016-05-25 23:49:47 +02:00
if ( messageMaxId ! = 0 & & channelId ! = 0 ) {
messageMaxId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
}
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start, end FROM messages_holes WHERE uid = %d AND start < %d AND end > %d " , dialog_id , max_id_query , max_id_query ) ) ;
2016-05-25 23:49:47 +02:00
boolean containMessage = ! cursor . next ( ) ;
cursor . dispose ( ) ;
if ( containMessage ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid > %d " , dialog_id , max_id_query ) ) ;
2016-05-25 23:49:47 +02:00
if ( cursor . next ( ) ) {
messageMaxId = max_id_query = cursor . intValue ( 0 ) ;
if ( messageMaxId ! = 0 & & channelId ! = 0 ) {
messageMaxId | = ( ( long ) channelId ) < < 32 ;
}
2016-04-22 15:49:00 +02:00
}
cursor . dispose ( ) ;
}
2015-12-09 19:27:52 +01:00
}
}
2016-04-22 15:49:00 +02:00
if ( count_query > count_unread | | count_unread < num ) {
2015-12-09 19:27:52 +01:00
count_query = Math . max ( count_query , count_unread + 10 ) ;
2016-04-22 15:49:00 +02:00
if ( count_unread < num ) {
2015-12-09 19:27:52 +01:00
count_unread = 0 ;
min_unread_id = 0 ;
messageMaxId = 0 ;
last_message_id = 0 ;
queryFromServer = false ;
}
} else {
offset_query = count_unread - count_query ;
count_query + = 10 ;
}
}
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start FROM messages_holes WHERE uid = %d AND start IN (0, 1) " , dialog_id ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
isEnd = cursor . intValue ( 0 ) = = 1 ;
cursor . dispose ( ) ;
} else {
cursor . dispose ( ) ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND mid > 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
int mid = cursor . intValue ( 0 ) ;
if ( mid ! = 0 ) {
2016-06-24 12:27:15 +02:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages_holes VALUES(?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
state . requery ( ) ;
state . bindLong ( 1 , dialog_id ) ;
state . bindInteger ( 2 , 0 ) ;
state . bindInteger ( 3 , mid ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
cursor . dispose ( ) ;
}
2017-03-31 01:58:05 +02:00
if ( load_type = = 3 | | load_type = = 4 | | queryFromServer & & load_type = = 2 ) {
2015-09-24 22:52:02 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0 " , dialog_id ) ) ;
2014-10-31 20:02:29 +01:00
if ( cursor . next ( ) ) {
last_message_id = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
2017-03-31 01:58:05 +02:00
if ( load_type = = 4 & & offset_date ! = 0 ) {
int startMid ;
int endMid ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(mid) FROM messages WHERE uid = %d AND date <= %d AND mid > 0 " , dialog_id , offset_date ) ) ;
if ( cursor . next ( ) ) {
startMid = cursor . intValue ( 0 ) ;
} else {
startMid = - 1 ;
}
cursor . dispose ( ) ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND date >= %d AND mid > 0 " , dialog_id , offset_date ) ) ;
if ( cursor . next ( ) ) {
endMid = cursor . intValue ( 0 ) ;
} else {
endMid = - 1 ;
}
cursor . dispose ( ) ;
if ( startMid ! = - 1 & & endMid ! = - 1 ) {
if ( startMid = = endMid ) {
max_id_query = startMid ;
} else {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d " , dialog_id , startMid , startMid ) ) ;
if ( cursor . next ( ) ) {
startMid = - 1 ;
}
cursor . dispose ( ) ;
if ( startMid ! = - 1 ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start FROM messages_holes WHERE uid = %d AND start <= %d AND end > %d " , dialog_id , endMid , endMid ) ) ;
if ( cursor . next ( ) ) {
endMid = - 1 ;
}
cursor . dispose ( ) ;
if ( endMid ! = - 1 ) {
max_id_override = endMid ;
messageMaxId = max_id_query = endMid ;
if ( messageMaxId ! = 0 & & channelId ! = 0 ) {
messageMaxId | = ( ( long ) channelId ) < < 32 ;
}
}
}
}
}
}
2016-04-22 15:49:00 +02:00
boolean containMessage = max_id_query ! = 0 ;
if ( containMessage ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start FROM messages_holes WHERE uid = %d AND start < %d AND end > %d " , dialog_id , max_id_query , max_id_query ) ) ;
2016-04-22 15:49:00 +02:00
if ( cursor . next ( ) ) {
containMessage = false ;
}
cursor . dispose ( ) ;
2014-11-18 06:01:04 +01:00
}
if ( containMessage ) {
2015-09-24 22:52:02 +02:00
long holeMessageMaxId = 0 ;
long holeMessageMinId = 1 ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start FROM messages_holes WHERE uid = %d AND start >= %d ORDER BY start ASC LIMIT 1 " , dialog_id , max_id_query ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
holeMessageMaxId = cursor . intValue ( 0 ) ;
if ( channelId ! = 0 ) {
holeMessageMaxId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1 " , dialog_id , max_id_query ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
holeMessageMinId = cursor . intValue ( 0 ) ;
if ( channelId ! = 0 ) {
holeMessageMinId | = ( ( long ) channelId ) < < 32 ;
}
}
2016-03-16 13:26:32 +01:00
/ * if ( holeMessageMaxId = = holeMessageMinId ) {
2015-09-24 22:52:02 +02:00
holeMessageMaxId = 0 ;
holeMessageMinId = 1 ;
} * /
cursor . dispose ( ) ;
if ( holeMessageMaxId ! = 0 | | holeMessageMinId ! = 1 ) {
if ( holeMessageMaxId = = 0 ) {
holeMessageMaxId = 1000000000 ;
if ( channelId ! = 0 ) {
holeMessageMaxId | = ( ( long ) channelId ) < < 32 ;
}
}
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d AND m.mid >= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " +
" SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d AND m.mid <= %d ORDER BY m.date ASC, m.mid ASC LIMIT %d) " , dialog_id , messageMaxId , holeMessageMinId , count_query / 2 , dialog_id , messageMaxId , holeMessageMaxId , count_query / 2 ) ) ;
2015-09-24 22:52:02 +02:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d) UNION " +
" SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d) " , dialog_id , messageMaxId , count_query / 2 , dialog_id , messageMaxId , count_query / 2 ) ) ;
2015-09-24 22:52:02 +02:00
}
2014-11-18 06:01:04 +01:00
} else {
cursor = null ;
}
2014-10-31 20:02:29 +01:00
} else if ( load_type = = 1 ) {
2015-09-24 22:52:02 +02:00
long holeMessageId = 0 ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start, end FROM messages_holes WHERE uid = %d AND start >= %d AND start != 1 AND end != 1 ORDER BY start ASC LIMIT 1 " , dialog_id , max_id ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
holeMessageId = cursor . intValue ( 0 ) ;
if ( channelId ! = 0 ) {
holeMessageId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
if ( holeMessageId ! = 0 ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d AND m.mid <= %d ORDER BY m.date ASC, m.mid ASC LIMIT %d " , dialog_id , minDate , messageMaxId , holeMessageId , count_query ) ) ;
2015-09-24 22:52:02 +02:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date >= %d AND m.mid > %d ORDER BY m.date ASC, m.mid ASC LIMIT %d " , dialog_id , minDate , messageMaxId , count_query ) ) ;
2015-09-24 22:52:02 +02:00
}
2013-12-20 20:25:49 +01:00
} else if ( minDate ! = 0 ) {
2015-09-24 22:52:02 +02:00
if ( messageMaxId ! = 0 ) {
long holeMessageId = 0 ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT end FROM messages_holes WHERE uid = %d AND end <= %d ORDER BY end DESC LIMIT 1 " , dialog_id , max_id ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
holeMessageId = cursor . intValue ( 0 ) ;
if ( channelId ! = 0 ) {
holeMessageId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
if ( holeMessageId ! = 0 ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d " , dialog_id , minDate , messageMaxId , holeMessageId , count_query ) ) ;
2015-09-24 22:52:02 +02:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d AND m.mid < %d ORDER BY m.date DESC, m.mid DESC LIMIT %d " , dialog_id , minDate , messageMaxId , count_query ) ) ;
2015-09-24 22:52:02 +02:00
}
2013-10-25 17:19:00 +02:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d " , dialog_id , minDate , offset_query , count_query ) ) ;
2013-10-25 17:19:00 +02:00
}
} else {
2015-12-09 19:27:52 +01:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(mid) FROM messages WHERE uid = %d AND mid > 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
last_message_id = cursor . intValue ( 0 ) ;
2013-10-25 17:19:00 +02:00
}
2015-12-09 19:27:52 +01:00
cursor . dispose ( ) ;
2015-09-24 22:52:02 +02:00
long holeMessageId = 0 ;
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(end) FROM messages_holes WHERE uid = %d " , dialog_id ) ) ;
2015-09-24 22:52:02 +02:00
if ( cursor . next ( ) ) {
holeMessageId = cursor . intValue ( 0 ) ;
if ( channelId ! = 0 ) {
holeMessageId | = ( ( long ) channelId ) < < 32 ;
}
}
cursor . dispose ( ) ;
if ( holeMessageId ! = 0 ) {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND (m.mid >= %d OR m.mid < 0) ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d " , dialog_id , holeMessageId , offset_query , count_query ) ) ;
2015-09-24 22:52:02 +02:00
} else {
2016-06-24 12:27:15 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.date DESC, m.mid DESC LIMIT %d,%d " , dialog_id , offset_query , count_query ) ) ;
2015-09-24 22:52:02 +02:00
}
2013-10-25 17:19:00 +02:00
}
} else {
2015-09-24 22:52:02 +02:00
isEnd = true ;
2017-03-31 01:58:05 +02:00
if ( load_type = = 3 & & minDate = = 0 ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
min_unread_id = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
int min_unread_id2 = 0 ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
min_unread_id2 = cursor . intValue ( 0 ) ;
max_unread_date = cursor . intValue ( 1 ) ;
}
cursor . dispose ( ) ;
if ( min_unread_id2 ! = 0 ) {
min_unread_id = min_unread_id2 ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2) " , dialog_id , min_unread_id2 ) ) ;
if ( cursor . next ( ) ) {
count_unread = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
}
}
if ( load_type = = 3 | | load_type = = 4 ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
last_message_id = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid <= %d ORDER BY m.mid DESC LIMIT %d) UNION " +
" SELECT * FROM (SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d) " , dialog_id , messageMaxId , count_query / 2 , dialog_id , messageMaxId , count_query / 2 ) ) ;
} else if ( load_type = = 1 ) {
2016-04-22 15:49:00 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid < %d ORDER BY m.mid DESC LIMIT %d " , dialog_id , max_id , count_query ) ) ;
2013-12-20 20:25:49 +01:00
} else if ( minDate ! = 0 ) {
2014-03-22 23:31:55 +01:00
if ( max_id ! = 0 ) {
2016-04-22 15:49:00 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.mid > %d ORDER BY m.mid ASC LIMIT %d " , dialog_id , max_id , count_query ) ) ;
2014-03-22 23:31:55 +01:00
} else {
2016-04-22 15:49:00 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d AND m.date <= %d ORDER BY m.mid ASC LIMIT %d,%d " , dialog_id , minDate , offset_query , count_query ) ) ;
2014-03-22 23:31:55 +01:00
}
2013-10-25 17:19:00 +02:00
} else {
2014-10-31 20:02:29 +01:00
if ( load_type = = 2 ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(mid) FROM messages WHERE uid = %d AND mid < 0 " , dialog_id ) ) ;
if ( cursor . next ( ) ) {
last_message_id = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
2015-05-03 13:48:36 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT max(mid), max(date) FROM messages WHERE uid = %d AND out = 0 AND read_state IN(0,2) AND mid < 0 " , dialog_id ) ) ;
2013-12-20 20:25:49 +01:00
if ( cursor . next ( ) ) {
min_unread_id = cursor . intValue ( 0 ) ;
2014-10-31 20:02:29 +01:00
max_unread_date = cursor . intValue ( 1 ) ;
2013-12-20 20:25:49 +01:00
}
cursor . dispose ( ) ;
if ( min_unread_id ! = 0 ) {
2015-05-03 13:48:36 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT COUNT(*) FROM messages WHERE uid = %d AND mid <= %d AND out = 0 AND read_state IN(0,2) " , dialog_id , min_unread_id ) ) ;
2013-12-20 20:25:49 +01:00
if ( cursor . next ( ) ) {
count_unread = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
}
}
2016-04-22 15:49:00 +02:00
if ( count_query > count_unread | | count_unread < num ) {
2013-12-20 20:25:49 +01:00
count_query = Math . max ( count_query , count_unread + 10 ) ;
2016-04-22 15:49:00 +02:00
if ( count_unread < num ) {
2013-12-20 20:25:49 +01:00
count_unread = 0 ;
min_unread_id = 0 ;
2014-10-31 20:02:29 +01:00
last_message_id = 0 ;
2013-12-20 20:25:49 +01:00
}
2013-10-25 17:19:00 +02:00
} else {
2013-12-20 20:25:49 +01:00
offset_query = count_unread - count_query ;
count_query + = 10 ;
2013-10-25 17:19:00 +02:00
}
2016-04-22 15:49:00 +02:00
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.read_state, m.data, m.send_state, m.mid, m.date, r.random_id, m.replydata, m.media, m.ttl FROM messages as m LEFT JOIN randoms as r ON r.mid = m.mid WHERE m.uid = %d ORDER BY m.mid ASC LIMIT %d,%d " , dialog_id , offset_query , count_query ) ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-11-18 06:01:04 +01:00
if ( cursor ! = null ) {
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-05-03 13:48:36 +02:00
MessageObject . setUnreadFlags ( message , cursor . intValue ( 0 ) ) ;
2014-11-18 06:01:04 +01:00
message . id = cursor . intValue ( 3 ) ;
message . date = cursor . intValue ( 4 ) ;
message . dialog_id = dialog_id ;
2015-09-24 22:52:02 +02:00
if ( ( message . flags & TLRPC . MESSAGE_FLAG_HAS_VIEWS ) ! = 0 ) {
message . views = cursor . intValue ( 7 ) ;
}
2017-07-23 14:56:38 +02:00
if ( lower_id ! = 0 & & message . ttl = = 0 ) {
2016-05-25 23:49:47 +02:00
message . ttl = cursor . intValue ( 8 ) ;
}
2014-11-18 06:01:04 +01:00
res . messages . add ( message ) ;
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2016-03-06 02:49:31 +01:00
if ( message . reply_to_msg_id ! = 0 | | message . reply_to_random_id ! = 0 ) {
2015-03-19 00:09:45 +01:00
if ( ! cursor . isNull ( 6 ) ) {
2016-05-25 23:49:47 +02:00
data = cursor . byteBufferValue ( 6 ) ;
if ( data ! = null ) {
message . replyMessage = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
2015-03-19 00:09:45 +01:00
if ( message . replyMessage ! = null ) {
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message . replyMessage , usersToLoad , chatsToLoad ) ;
2015-03-19 00:09:45 +01:00
}
}
}
2016-03-16 13:26:32 +01:00
if ( message . replyMessage = = null ) {
2016-03-06 02:49:31 +01:00
if ( message . reply_to_msg_id ! = 0 ) {
long messageId = message . reply_to_msg_id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
if ( ! replyMessages . contains ( messageId ) ) {
replyMessages . add ( messageId ) ;
}
ArrayList < TLRPC . Message > messages = replyMessageOwners . get ( message . reply_to_msg_id ) ;
if ( messages = = null ) {
messages = new ArrayList < > ( ) ;
replyMessageOwners . put ( message . reply_to_msg_id , messages ) ;
}
messages . add ( message ) ;
} else {
if ( ! replyMessages . contains ( message . reply_to_random_id ) ) {
replyMessages . add ( message . reply_to_random_id ) ;
}
ArrayList < TLRPC . Message > messages = replyMessageRandomOwners . get ( message . reply_to_random_id ) ;
if ( messages = = null ) {
messages = new ArrayList < > ( ) ;
replyMessageRandomOwners . put ( message . reply_to_random_id , messages ) ;
}
messages . add ( message ) ;
2015-03-19 00:09:45 +01:00
}
}
}
2014-11-18 06:01:04 +01:00
message . send_state = cursor . intValue ( 2 ) ;
2015-10-29 18:10:07 +01:00
if ( message . id > 0 & & message . send_state ! = 0 ) {
2014-11-18 06:01:04 +01:00
message . send_state = 0 ;
}
if ( lower_id = = 0 & & ! cursor . isNull ( 5 ) ) {
message . random_id = cursor . longValue ( 5 ) ;
}
2017-07-23 14:56:38 +02:00
if ( MessageObject . isSecretPhotoOrVideo ( message ) ) {
2014-11-18 06:01:04 +01:00
try {
SQLiteCursor cursor2 = database . queryFinalized ( String . format ( Locale . US , " SELECT date FROM enc_tasks_v2 WHERE mid = %d " , message . id ) ) ;
if ( cursor2 . next ( ) ) {
message . destroyTime = cursor2 . intValue ( 0 ) ;
}
cursor2 . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-09 17:55:05 +02:00
}
}
}
2013-10-25 17:19:00 +02:00
}
2014-11-18 06:01:04 +01:00
cursor . dispose ( ) ;
2014-10-31 20:02:29 +01:00
}
2014-09-14 01:40:36 +02:00
2014-10-31 20:02:29 +01:00
Collections . sort ( res . messages , new Comparator < TLRPC . Message > ( ) {
@Override
public int compare ( TLRPC . Message lhs , TLRPC . Message rhs ) {
if ( lhs . id > 0 & & rhs . id > 0 ) {
2014-11-19 02:23:46 +01:00
if ( lhs . id > rhs . id ) {
return - 1 ;
} else if ( lhs . id < rhs . id ) {
return 1 ;
2014-10-31 20:02:29 +01:00
}
} else if ( lhs . id < 0 & & rhs . id < 0 ) {
2014-11-19 02:23:46 +01:00
if ( lhs . id < rhs . id ) {
return - 1 ;
} else if ( lhs . id > rhs . id ) {
return 1 ;
2014-10-31 20:02:29 +01:00
}
} else {
2014-11-19 02:23:46 +01:00
if ( lhs . date > rhs . date ) {
return - 1 ;
} else if ( lhs . date < rhs . date ) {
return 1 ;
2014-09-14 01:40:36 +02:00
}
}
2014-10-31 20:02:29 +01:00
return 0 ;
}
} ) ;
2013-10-25 17:19:00 +02:00
2017-03-31 01:58:05 +02:00
if ( lower_id ! = 0 ) {
if ( ( load_type = = 3 | | load_type = = 4 | | load_type = = 2 & & queryFromServer ) & & ! res . messages . isEmpty ( ) ) {
int minId = res . messages . get ( res . messages . size ( ) - 1 ) . id ;
int maxId = res . messages . get ( 0 ) . id ;
if ( ! ( minId < = max_id_query & & maxId > = max_id_query ) ) {
replyMessages . clear ( ) ;
usersToLoad . clear ( ) ;
chatsToLoad . clear ( ) ;
res . messages . clear ( ) ;
}
}
if ( ( load_type = = 4 | | load_type = = 3 ) & & res . messages . size ( ) = = 1 ) {
2015-12-09 19:27:52 +01:00
res . messages . clear ( ) ;
}
}
2015-03-19 00:09:45 +01:00
if ( ! replyMessages . isEmpty ( ) ) {
2016-03-06 02:49:31 +01:00
if ( ! replyMessageOwners . isEmpty ( ) ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date FROM messages WHERE mid IN(%s) " , TextUtils . join ( " , " , replyMessages ) ) ) ;
} else {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT m.data, m.mid, m.date, r.random_id FROM randoms as r INNER JOIN messages as m ON r.mid = m.mid WHERE r.random_id IN(%s) " , TextUtils . join ( " , " , replyMessages ) ) ) ;
}
2015-03-19 00:09:45 +01:00
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-03-19 00:09:45 +01:00
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = dialog_id ;
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2016-03-06 02:49:31 +01:00
if ( ! replyMessageOwners . isEmpty ( ) ) {
ArrayList < TLRPC . Message > arrayList = replyMessageOwners . get ( message . id ) ;
if ( arrayList ! = null ) {
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
arrayList . get ( a ) . replyMessage = message ;
}
}
} else {
ArrayList < TLRPC . Message > arrayList = replyMessageRandomOwners . remove ( cursor . longValue ( 3 ) ) ;
if ( arrayList ! = null ) {
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
TLRPC . Message object = arrayList . get ( a ) ;
object . replyMessage = message ;
object . reply_to_msg_id = message . id ;
}
2015-03-19 00:09:45 +01:00
}
2014-11-19 02:23:46 +01:00
}
}
}
2015-03-19 00:09:45 +01:00
cursor . dispose ( ) ;
2016-03-06 02:49:31 +01:00
if ( ! replyMessageRandomOwners . isEmpty ( ) ) {
for ( HashMap . Entry < Long , ArrayList < TLRPC . Message > > entry : replyMessageRandomOwners . entrySet ( ) ) {
ArrayList < TLRPC . Message > arrayList = entry . getValue ( ) ;
for ( int a = 0 ; a < arrayList . size ( ) ; a + + ) {
arrayList . get ( a ) . reply_to_random_id = 0 ;
}
}
}
2015-03-19 00:09:45 +01:00
}
2014-11-19 02:23:46 +01:00
2015-11-26 22:04:02 +01:00
if ( ! usersToLoad . isEmpty ( ) ) {
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , res . users ) ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
if ( ! chatsToLoad . isEmpty ( ) ) {
getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , res . chats ) ;
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
res . messages . clear ( ) ;
res . chats . clear ( ) ;
res . users . clear ( ) ;
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
2017-03-31 01:58:05 +02:00
MessagesController . getInstance ( ) . processLoadedMessages ( res , dialog_id , count_query , max_id_override , offset_date , true , classGuid , min_unread_id , last_message_id , count_unread , max_unread_date , load_type , isChannel , isEnd , loadIndex , queryFromServer ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-02-11 15:32:09 +01:00
} ) ;
2013-10-25 17:19:00 +02:00
}
public void startTransaction ( boolean useQueue ) {
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . beginTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
} else {
try {
database . beginTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
}
public void commitTransaction ( boolean useQueue ) {
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-08-13 11:23:31 +02:00
try {
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-08-13 11:23:31 +02:00
}
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2015-08-13 11:23:31 +02:00
try {
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-08-13 11:23:31 +02:00
}
2013-10-25 17:19:00 +02:00
}
}
2014-06-20 02:18:13 +02:00
public TLObject getSentFile ( final String path , final int type ) {
2017-03-31 01:58:05 +02:00
if ( path = = null | | path . endsWith ( " attheme " ) ) {
2014-06-20 02:18:13 +02:00
return null ;
}
final Semaphore semaphore = new Semaphore ( 0 ) ;
2015-01-02 23:15:07 +01:00
final ArrayList < TLObject > result = new ArrayList < > ( ) ;
2014-06-20 02:18:13 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
String id = Utilities . MD5 ( path ) ;
if ( id ! = null ) {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM sent_files_v2 WHERE uid = '%s' AND type = %d " , id , type ) ) ;
if ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-06 02:49:31 +01:00
TLObject file = TLRPC . MessageMedia . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-06 02:49:31 +01:00
if ( file instanceof TLRPC . TL_messageMediaDocument ) {
result . add ( ( ( TLRPC . TL_messageMediaDocument ) file ) . document ) ;
} else if ( file instanceof TLRPC . TL_messageMediaPhoto ) {
2016-06-24 12:27:15 +02:00
result . add ( ( ( TLRPC . TL_messageMediaPhoto ) file ) . photo ) ;
2014-06-20 02:18:13 +02:00
}
}
}
cursor . dispose ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-06-20 02:18:13 +02:00
} finally {
semaphore . release ( ) ;
}
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-06-20 02:18:13 +02:00
}
return ! result . isEmpty ( ) ? result . get ( 0 ) : null ;
}
public void putSentFile ( final String path , final TLObject file , final int type ) {
if ( path = = null | | file = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-02-01 19:51:02 +01:00
SQLitePreparedStatement state = null ;
2014-06-20 02:18:13 +02:00
try {
String id = Utilities . MD5 ( path ) ;
if ( id ! = null ) {
2016-03-06 02:49:31 +01:00
TLRPC . MessageMedia messageMedia = null ;
if ( file instanceof TLRPC . Photo ) {
messageMedia = new TLRPC . TL_messageMediaPhoto ( ) ;
messageMedia . photo = ( TLRPC . Photo ) file ;
2017-07-23 14:56:38 +02:00
messageMedia . flags | = 1 ;
2016-03-06 02:49:31 +01:00
} else if ( file instanceof TLRPC . Document ) {
messageMedia = new TLRPC . TL_messageMediaDocument ( ) ;
messageMedia . document = ( TLRPC . Document ) file ;
2017-07-23 14:56:38 +02:00
messageMedia . flags | = 1 ;
2016-03-06 02:49:31 +01:00
}
if ( messageMedia = = null ) {
return ;
}
2015-02-01 19:51:02 +01:00
state = database . executeFast ( " REPLACE INTO sent_files_v2 VALUES(?, ?, ?) " ) ;
2014-06-20 02:18:13 +02:00
state . requery ( ) ;
2016-03-06 02:49:31 +01:00
NativeByteBuffer data = new NativeByteBuffer ( messageMedia . getObjectSize ( ) ) ;
messageMedia . serializeToStream ( data ) ;
2014-06-20 02:18:13 +02:00
state . bindString ( 1 , id ) ;
state . bindInteger ( 2 , type ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 3 , data ) ;
2014-06-20 02:18:13 +02:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-06-20 02:18:13 +02:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-02-01 19:51:02 +01:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
2014-06-20 02:18:13 +02:00
}
}
} ) ;
}
2014-10-16 22:02:44 +02:00
public void updateEncryptedChatSeq ( final TLRPC . EncryptedChat chat ) {
if ( chat = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLitePreparedStatement state = null ;
try {
2016-10-11 13:57:01 +02:00
state = database . executeFast ( " UPDATE enc_chats SET seq_in = ?, seq_out = ?, use_count = ?, in_seq_no = ? WHERE uid = ? " ) ;
2014-10-16 22:02:44 +02:00
state . bindInteger ( 1 , chat . seq_in ) ;
state . bindInteger ( 2 , chat . seq_out ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 3 , ( int ) chat . key_use_count_in < < 16 | chat . key_use_count_out ) ;
2016-10-11 13:57:01 +02:00
state . bindInteger ( 4 , chat . in_seq_no ) ;
state . bindInteger ( 5 , chat . id ) ;
2014-10-16 22:02:44 +02:00
state . step ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-16 22:02:44 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
}
} ) ;
}
2013-10-25 17:19:00 +02:00
public void updateEncryptedChatTTL ( final TLRPC . EncryptedChat chat ) {
if ( chat = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLitePreparedStatement state = null ;
try {
state = database . executeFast ( " UPDATE enc_chats SET ttl = ? WHERE uid = ? " ) ;
state . bindInteger ( 1 , chat . ttl ) ;
state . bindInteger ( 2 , chat . id ) ;
state . step ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
}
} ) ;
}
2014-10-14 10:13:16 +02:00
public void updateEncryptedChatLayer ( final TLRPC . EncryptedChat chat ) {
if ( chat = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLitePreparedStatement state = null ;
try {
state = database . executeFast ( " UPDATE enc_chats SET layer = ? WHERE uid = ? " ) ;
state . bindInteger ( 1 , chat . layer ) ;
state . bindInteger ( 2 , chat . id ) ;
state . step ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-14 10:13:16 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
}
} ) ;
}
2013-10-25 17:19:00 +02:00
public void updateEncryptedChat ( final TLRPC . EncryptedChat chat ) {
if ( chat = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLitePreparedStatement state = null ;
try {
2016-03-06 02:49:31 +01:00
if ( ( chat . key_hash = = null | | chat . key_hash . length < 16 ) & & chat . auth_key ! = null ) {
chat . key_hash = AndroidUtilities . calcAuthKeyHash ( chat . auth_key ) ;
2014-12-01 18:56:31 +01:00
}
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " UPDATE enc_chats SET data = ?, g = ?, authkey = ?, ttl = ?, layer = ?, seq_in = ?, seq_out = ?, use_count = ?, exchange_id = ?, key_date = ?, fprint = ?, fauthkey = ?, khash = ?, in_seq_no = ?, admin_id = ? WHERE uid = ? " ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( chat . getObjectSize ( ) ) ;
NativeByteBuffer data2 = new NativeByteBuffer ( chat . a_or_b ! = null ? chat . a_or_b . length : 1 ) ;
NativeByteBuffer data3 = new NativeByteBuffer ( chat . auth_key ! = null ? chat . auth_key . length : 1 ) ;
NativeByteBuffer data4 = new NativeByteBuffer ( chat . future_auth_key ! = null ? chat . future_auth_key . length : 1 ) ;
NativeByteBuffer data5 = new NativeByteBuffer ( chat . key_hash ! = null ? chat . key_hash . length : 1 ) ;
2013-10-25 17:19:00 +02:00
chat . serializeToStream ( data ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 1 , data ) ;
2013-10-25 17:19:00 +02:00
if ( chat . a_or_b ! = null ) {
2015-09-24 22:52:02 +02:00
data2 . writeBytes ( chat . a_or_b ) ;
2013-10-25 17:19:00 +02:00
}
if ( chat . auth_key ! = null ) {
2015-09-24 22:52:02 +02:00
data3 . writeBytes ( chat . auth_key ) ;
2013-10-25 17:19:00 +02:00
}
2014-12-01 18:56:31 +01:00
if ( chat . future_auth_key ! = null ) {
2015-09-24 22:52:02 +02:00
data4 . writeBytes ( chat . future_auth_key ) ;
2014-12-01 18:56:31 +01:00
}
if ( chat . key_hash ! = null ) {
2015-09-24 22:52:02 +02:00
data5 . writeBytes ( chat . key_hash ) ;
2014-12-01 18:56:31 +01:00
}
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 2 , data2 ) ;
state . bindByteBuffer ( 3 , data3 ) ;
2013-10-25 17:19:00 +02:00
state . bindInteger ( 4 , chat . ttl ) ;
2014-10-14 22:36:15 +02:00
state . bindInteger ( 5 , chat . layer ) ;
2014-10-16 22:02:44 +02:00
state . bindInteger ( 6 , chat . seq_in ) ;
state . bindInteger ( 7 , chat . seq_out ) ;
2015-09-24 22:52:02 +02:00
state . bindInteger ( 8 , ( int ) chat . key_use_count_in < < 16 | chat . key_use_count_out ) ;
2014-12-01 18:56:31 +01:00
state . bindLong ( 9 , chat . exchange_id ) ;
state . bindInteger ( 10 , chat . key_create_date ) ;
state . bindLong ( 11 , chat . future_key_fingerprint ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 12 , data4 ) ;
state . bindByteBuffer ( 13 , data5 ) ;
2016-10-11 13:57:01 +02:00
state . bindInteger ( 14 , chat . in_seq_no ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 15 , chat . admin_id ) ;
state . bindInteger ( 16 , chat . id ) ;
2014-12-01 18:56:31 +01:00
2013-10-25 17:19:00 +02:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
data2 . reuse ( ) ;
data3 . reuse ( ) ;
data4 . reuse ( ) ;
data5 . reuse ( ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
}
} ) ;
}
2015-10-29 18:10:07 +01:00
public boolean isDialogHasMessages ( final long did ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
final boolean result [ ] = new boolean [ 1 ] ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM messages WHERE uid = %d LIMIT 1 " , did ) ) ;
result [ 0 ] = cursor . next ( ) ;
cursor . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-10-29 18:10:07 +01:00
} finally {
semaphore . release ( ) ;
}
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-10-29 18:10:07 +01:00
}
return result [ 0 ] ;
}
2016-06-24 12:27:15 +02:00
public boolean hasAuthMessage ( final int date ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
final boolean result [ ] = new boolean [ 1 ] ;
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM messages WHERE uid = 777000 AND date = %d AND mid < 0 LIMIT 1 " , date ) ) ;
result [ 0 ] = cursor . next ( ) ;
cursor . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-06-24 12:27:15 +02:00
} finally {
semaphore . release ( ) ;
}
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-06-24 12:27:15 +02:00
}
return result [ 0 ] ;
}
2013-10-25 17:19:00 +02:00
public void getEncryptedChat ( final int chat_id , final Semaphore semaphore , final ArrayList < TLObject > result ) {
if ( semaphore = = null | | result = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-01-02 23:15:07 +01:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getEncryptedChatsInternal ( " " + chat_id , encryptedChats , usersToLoad ) ;
if ( ! encryptedChats . isEmpty ( ) & & ! usersToLoad . isEmpty ( ) ) {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , users ) ;
if ( ! users . isEmpty ( ) ) {
result . add ( encryptedChats . get ( 0 ) ) ;
result . add ( users . get ( 0 ) ) ;
2013-10-25 17:19:00 +02:00
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
semaphore . release ( ) ;
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public void putEncryptedChat ( final TLRPC . EncryptedChat chat , final TLRPC . User user , final TLRPC . TL_dialog dialog ) {
2013-10-25 17:19:00 +02:00
if ( chat = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2016-03-06 02:49:31 +01:00
if ( ( chat . key_hash = = null | | chat . key_hash . length < 16 ) & & chat . auth_key ! = null ) {
chat . key_hash = AndroidUtilities . calcAuthKeyHash ( chat . auth_key ) ;
2014-12-01 18:56:31 +01:00
}
2017-03-31 01:58:05 +02:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO enc_chats VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( chat . getObjectSize ( ) ) ;
NativeByteBuffer data2 = new NativeByteBuffer ( chat . a_or_b ! = null ? chat . a_or_b . length : 1 ) ;
NativeByteBuffer data3 = new NativeByteBuffer ( chat . auth_key ! = null ? chat . auth_key . length : 1 ) ;
NativeByteBuffer data4 = new NativeByteBuffer ( chat . future_auth_key ! = null ? chat . future_auth_key . length : 1 ) ;
NativeByteBuffer data5 = new NativeByteBuffer ( chat . key_hash ! = null ? chat . key_hash . length : 1 ) ;
2014-07-03 00:39:05 +02:00
2013-10-25 17:19:00 +02:00
chat . serializeToStream ( data ) ;
state . bindInteger ( 1 , chat . id ) ;
state . bindInteger ( 2 , user . id ) ;
2014-10-23 17:30:35 +02:00
state . bindString ( 3 , formatUserSearchName ( user ) ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 4 , data ) ;
2013-10-25 17:19:00 +02:00
if ( chat . a_or_b ! = null ) {
2015-09-24 22:52:02 +02:00
data2 . writeBytes ( chat . a_or_b ) ;
2013-10-25 17:19:00 +02:00
}
if ( chat . auth_key ! = null ) {
2015-09-24 22:52:02 +02:00
data3 . writeBytes ( chat . auth_key ) ;
2013-10-25 17:19:00 +02:00
}
2014-12-01 18:56:31 +01:00
if ( chat . future_auth_key ! = null ) {
2015-09-24 22:52:02 +02:00
data4 . writeBytes ( chat . future_auth_key ) ;
2014-12-01 18:56:31 +01:00
}
if ( chat . key_hash ! = null ) {
2015-09-24 22:52:02 +02:00
data5 . writeBytes ( chat . key_hash ) ;
2014-12-01 18:56:31 +01:00
}
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 5 , data2 ) ;
state . bindByteBuffer ( 6 , data3 ) ;
2013-10-25 17:19:00 +02:00
state . bindInteger ( 7 , chat . ttl ) ;
2014-10-14 10:13:16 +02:00
state . bindInteger ( 8 , chat . layer ) ;
2014-10-16 22:02:44 +02:00
state . bindInteger ( 9 , chat . seq_in ) ;
state . bindInteger ( 10 , chat . seq_out ) ;
2015-09-24 22:52:02 +02:00
state . bindInteger ( 11 , ( int ) chat . key_use_count_in < < 16 | chat . key_use_count_out ) ;
2014-12-01 18:56:31 +01:00
state . bindLong ( 12 , chat . exchange_id ) ;
state . bindInteger ( 13 , chat . key_create_date ) ;
state . bindLong ( 14 , chat . future_key_fingerprint ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 15 , data4 ) ;
state . bindByteBuffer ( 16 , data5 ) ;
2016-10-11 13:57:01 +02:00
state . bindInteger ( 17 , chat . in_seq_no ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 18 , chat . admin_id ) ;
2014-12-01 18:56:31 +01:00
2013-10-25 17:19:00 +02:00
state . step ( ) ;
state . dispose ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
data2 . reuse ( ) ;
data3 . reuse ( ) ;
data4 . reuse ( ) ;
data5 . reuse ( ) ;
2013-10-25 17:19:00 +02:00
if ( dialog ! = null ) {
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2013-10-25 17:19:00 +02:00
state . bindLong ( 1 , dialog . id ) ;
state . bindInteger ( 2 , dialog . last_message_date ) ;
state . bindInteger ( 3 , dialog . unread_count ) ;
state . bindInteger ( 4 , dialog . top_message ) ;
2015-05-03 13:48:36 +02:00
state . bindInteger ( 5 , dialog . read_inbox_max_id ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 6 , dialog . read_outbox_max_id ) ;
state . bindInteger ( 7 , 0 ) ;
state . bindInteger ( 8 , 0 ) ;
2015-09-24 22:52:02 +02:00
state . bindInteger ( 9 , dialog . pts ) ;
state . bindInteger ( 10 , 0 ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 11 , dialog . pinnedNum ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
state . dispose ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2014-10-23 17:30:35 +02:00
private String formatUserSearchName ( TLRPC . User user ) {
StringBuilder str = new StringBuilder ( " " ) ;
if ( user . first_name ! = null & & user . first_name . length ( ) > 0 ) {
str . append ( user . first_name ) ;
}
if ( user . last_name ! = null & & user . last_name . length ( ) > 0 ) {
if ( str . length ( ) > 0 ) {
str . append ( " " ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-23 17:30:35 +02:00
str . append ( user . last_name ) ;
}
str . append ( " ;;; " ) ;
if ( user . username ! = null & & user . username . length ( ) > 0 ) {
str . append ( user . username ) ;
}
return str . toString ( ) . toLowerCase ( ) ;
}
private void putUsersInternal ( ArrayList < TLRPC . User > users ) throws Exception {
if ( users = = null | | users . isEmpty ( ) ) {
return ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO users VALUES(?, ?, ?, ?) " ) ;
2016-03-06 02:49:31 +01:00
for ( int a = 0 ; a < users . size ( ) ; a + + ) {
TLRPC . User user = users . get ( a ) ;
if ( user . min ) {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM users WHERE uid = %d " , user . id ) ) ;
if ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-06 02:49:31 +01:00
TLRPC . User oldUser = TLRPC . User . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( oldUser ! = null ) {
if ( user . username ! = null ) {
oldUser . username = user . username ;
oldUser . flags | = 8 ;
} else {
oldUser . username = null ;
2016-06-24 12:27:15 +02:00
oldUser . flags = oldUser . flags & ~ 8 ;
2016-03-16 13:26:32 +01:00
}
2016-03-06 02:49:31 +01:00
if ( user . photo ! = null ) {
oldUser . photo = user . photo ;
oldUser . flags | = 32 ;
} else {
oldUser . photo = null ;
2016-06-24 12:27:15 +02:00
oldUser . flags = oldUser . flags & ~ 32 ;
2016-03-06 02:49:31 +01:00
}
2016-03-16 13:26:32 +01:00
user = oldUser ;
2016-03-06 02:49:31 +01:00
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-06 02:49:31 +01:00
}
}
2016-05-25 23:49:47 +02:00
cursor . dispose ( ) ;
2016-03-06 02:49:31 +01:00
}
2014-10-23 17:30:35 +02:00
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( user . getObjectSize ( ) ) ;
2014-10-23 17:30:35 +02:00
user . serializeToStream ( data ) ;
state . bindInteger ( 1 , user . id ) ;
state . bindString ( 2 , formatUserSearchName ( user ) ) ;
if ( user . status ! = null ) {
2014-11-19 02:23:46 +01:00
if ( user . status instanceof TLRPC . TL_userStatusRecently ) {
user . status . expires = - 100 ;
} else if ( user . status instanceof TLRPC . TL_userStatusLastWeek ) {
user . status . expires = - 101 ;
} else if ( user . status instanceof TLRPC . TL_userStatusLastMonth ) {
user . status . expires = - 102 ;
}
2014-10-23 17:30:35 +02:00
state . bindInteger ( 3 , user . status . expires ) ;
} else {
state . bindInteger ( 3 , 0 ) ;
}
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 4 , data ) ;
2014-10-23 17:30:35 +02:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-10-23 17:30:35 +02:00
}
state . dispose ( ) ;
}
private void putChatsInternal ( ArrayList < TLRPC . Chat > chats ) throws Exception {
if ( chats = = null | | chats . isEmpty ( ) ) {
return ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO chats VALUES(?, ?, ?) " ) ;
2016-03-06 02:49:31 +01:00
for ( int a = 0 ; a < chats . size ( ) ; a + + ) {
TLRPC . Chat chat = chats . get ( a ) ;
2016-03-16 13:26:32 +01:00
if ( chat . min ) {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM chats WHERE uid = %d " , chat . id ) ) ;
if ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-16 13:26:32 +01:00
TLRPC . Chat oldChat = TLRPC . Chat . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( oldChat ! = null ) {
oldChat . title = chat . title ;
oldChat . photo = chat . photo ;
oldChat . broadcast = chat . broadcast ;
oldChat . verified = chat . verified ;
oldChat . megagroup = chat . megagroup ;
oldChat . democracy = chat . democracy ;
if ( chat . username ! = null ) {
oldChat . username = chat . username ;
oldChat . flags | = 64 ;
} else {
oldChat . username = null ;
2016-06-24 12:27:15 +02:00
oldChat . flags = oldChat . flags & ~ 64 ;
2016-03-16 13:26:32 +01:00
}
chat = oldChat ;
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-16 13:26:32 +01:00
}
}
2016-06-24 12:27:15 +02:00
cursor . dispose ( ) ;
2016-03-16 13:26:32 +01:00
}
2014-10-23 17:30:35 +02:00
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( chat . getObjectSize ( ) ) ;
2014-10-23 17:30:35 +02:00
chat . serializeToStream ( data ) ;
state . bindInteger ( 1 , chat . id ) ;
if ( chat . title ! = null ) {
String name = chat . title . toLowerCase ( ) ;
state . bindString ( 2 , name ) ;
} else {
state . bindString ( 2 , " " ) ;
}
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 3 , data ) ;
2014-10-23 17:30:35 +02:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-10-23 17:30:35 +02:00
}
state . dispose ( ) ;
}
2015-02-01 19:51:02 +01:00
public void getUsersInternal ( String usersToLoad , ArrayList < TLRPC . User > result ) throws Exception {
2014-10-23 17:30:35 +02:00
if ( usersToLoad = = null | | usersToLoad . length ( ) = = 0 | | result = = null ) {
return ;
}
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, status FROM users WHERE uid IN(%s) " , usersToLoad ) ) ;
while ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . User user = TLRPC . User . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2014-10-23 17:30:35 +02:00
if ( user ! = null ) {
if ( user . status ! = null ) {
user . status . expires = cursor . intValue ( 1 ) ;
}
result . add ( user ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-23 17:30:35 +02:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-23 17:30:35 +02:00
}
}
cursor . dispose ( ) ;
}
2015-02-01 19:51:02 +01:00
public void getChatsInternal ( String chatsToLoad , ArrayList < TLRPC . Chat > result ) throws Exception {
2014-10-23 17:30:35 +02:00
if ( chatsToLoad = = null | | chatsToLoad . length ( ) = = 0 | | result = = null ) {
return ;
}
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data FROM chats WHERE uid IN(%s) " , chatsToLoad ) ) ;
while ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Chat chat = TLRPC . Chat . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2014-10-23 17:30:35 +02:00
if ( chat ! = null ) {
result . add ( chat ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-10-23 17:30:35 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-23 17:30:35 +02:00
}
cursor . dispose ( ) ;
}
2015-02-01 19:51:02 +01:00
public void getEncryptedChatsInternal ( String chatsToLoad , ArrayList < TLRPC . EncryptedChat > result , ArrayList < Integer > usersToLoad ) throws Exception {
2014-10-23 17:30:35 +02:00
if ( chatsToLoad = = null | | chatsToLoad . length ( ) = = 0 | | result = = null ) {
return ;
}
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, user, g, authkey, ttl, layer, seq_in, seq_out, use_count, exchange_id, key_date, fprint, fauthkey, khash, in_seq_no, admin_id FROM enc_chats WHERE uid IN(%s) " , chatsToLoad ) ) ;
2014-10-23 17:30:35 +02:00
while ( cursor . next ( ) ) {
try {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . EncryptedChat chat = TLRPC . EncryptedChat . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2014-10-23 17:30:35 +02:00
if ( chat ! = null ) {
chat . user_id = cursor . intValue ( 1 ) ;
if ( usersToLoad ! = null & & ! usersToLoad . contains ( chat . user_id ) ) {
usersToLoad . add ( chat . user_id ) ;
}
chat . a_or_b = cursor . byteArrayValue ( 2 ) ;
chat . auth_key = cursor . byteArrayValue ( 3 ) ;
chat . ttl = cursor . intValue ( 4 ) ;
chat . layer = cursor . intValue ( 5 ) ;
chat . seq_in = cursor . intValue ( 6 ) ;
chat . seq_out = cursor . intValue ( 7 ) ;
2014-12-01 18:56:31 +01:00
int use_count = cursor . intValue ( 8 ) ;
2016-06-24 12:27:15 +02:00
chat . key_use_count_in = ( short ) ( use_count > > 16 ) ;
chat . key_use_count_out = ( short ) ( use_count ) ;
2014-12-01 18:56:31 +01:00
chat . exchange_id = cursor . longValue ( 9 ) ;
chat . key_create_date = cursor . intValue ( 10 ) ;
chat . future_key_fingerprint = cursor . longValue ( 11 ) ;
chat . future_auth_key = cursor . byteArrayValue ( 12 ) ;
chat . key_hash = cursor . byteArrayValue ( 13 ) ;
2016-10-11 13:57:01 +02:00
chat . in_seq_no = cursor . intValue ( 14 ) ;
2017-03-31 01:58:05 +02:00
int admin_id = cursor . intValue ( 15 ) ;
if ( admin_id ! = 0 ) {
chat . admin_id = admin_id ;
}
2014-10-23 17:30:35 +02:00
result . add ( chat ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-10-23 17:30:35 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-23 17:30:35 +02:00
}
}
cursor . dispose ( ) ;
}
private void putUsersAndChatsInternal ( final ArrayList < TLRPC . User > users , final ArrayList < TLRPC . Chat > chats , final boolean withTransaction ) {
try {
if ( withTransaction ) {
database . beginTransaction ( ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-23 17:30:35 +02:00
putUsersInternal ( users ) ;
putChatsInternal ( chats ) ;
2013-10-25 17:19:00 +02:00
if ( withTransaction ) {
database . commitTransaction ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
public void putUsersAndChats ( final ArrayList < TLRPC . User > users , final ArrayList < TLRPC . Chat > chats , final boolean withTransaction , boolean useQueue ) {
if ( users ! = null & & users . isEmpty ( ) & & chats ! = null & & chats . isEmpty ( ) ) {
return ;
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
putUsersAndChatsInternal ( users , chats , withTransaction ) ;
}
} ) ;
} else {
putUsersAndChatsInternal ( users , chats , withTransaction ) ;
}
}
2014-09-30 00:48:11 +02:00
public void removeFromDownloadQueue ( final long id , final int type , final boolean move ) {
2014-08-22 16:24:33 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-09-30 00:48:11 +02:00
if ( move ) {
int minDate = - 1 ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT min(date) FROM download_queue WHERE type = %d " , type ) ) ;
if ( cursor . next ( ) ) {
minDate = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( minDate ! = - 1 ) {
database . executeFast ( String . format ( Locale . US , " UPDATE download_queue SET date = %d WHERE uid = %d AND type = %d " , minDate - 1 , id , type ) ) . stepThis ( ) . dispose ( ) ;
}
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM download_queue WHERE uid = %d AND type = %d " , id , type ) ) . stepThis ( ) . dispose ( ) ;
}
2014-08-22 16:24:33 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
public void clearDownloadQueue ( final int type ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
if ( type = = 0 ) {
database . executeFast ( " DELETE FROM download_queue WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM download_queue WHERE type = %d " , type ) ) . stepThis ( ) . dispose ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
public void getDownloadQueue ( final int type ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-01-02 23:15:07 +01:00
final ArrayList < DownloadObject > objects = new ArrayList < > ( ) ;
2014-08-22 16:24:33 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT uid, type, data FROM download_queue WHERE type = %d ORDER BY date DESC LIMIT 3 " , type ) ) ;
while ( cursor . next ( ) ) {
DownloadObject downloadObject = new DownloadObject ( ) ;
downloadObject . type = cursor . intValue ( 1 ) ;
downloadObject . id = cursor . longValue ( 0 ) ;
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 2 ) ;
if ( data ! = null ) {
2016-03-06 02:49:31 +01:00
TLRPC . MessageMedia messageMedia = TLRPC . MessageMedia . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-06 02:49:31 +01:00
if ( messageMedia . document ! = null ) {
downloadObject . object = messageMedia . document ;
} else if ( messageMedia . photo ! = null ) {
downloadObject . object = FileLoader . getClosestPhotoSizeWithSize ( messageMedia . photo . sizes , AndroidUtilities . getPhotoSize ( ) ) ;
}
2017-07-23 14:56:38 +02:00
downloadObject . secret = messageMedia . ttl_seconds ! = 0 ;
2014-08-22 16:24:33 +02:00
}
objects . add ( downloadObject ) ;
}
cursor . dispose ( ) ;
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-08-22 16:24:33 +02:00
@Override
public void run ( ) {
MediaController . getInstance ( ) . processDownloadObjects ( type , objects ) ;
}
} ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-22 16:24:33 +02:00
}
}
} ) ;
}
2014-10-21 22:35:16 +02:00
private int getMessageMediaType ( TLRPC . Message message ) {
2017-07-23 14:56:38 +02:00
if ( message instanceof TLRPC . TL_message & & ( message . media instanceof TLRPC . TL_messageMediaPhoto | | message . media instanceof TLRPC . TL_messageMediaDocument ) & & message . media . ttl_seconds ! = 0 ) {
return 1 ;
} else if ( message instanceof TLRPC . TL_message_secret & & (
2015-11-26 22:04:02 +01:00
message . media instanceof TLRPC . TL_messageMediaPhoto & & message . ttl > 0 & & message . ttl < = 60 | |
2016-06-24 12:27:15 +02:00
MessageObject . isVoiceMessage ( message ) | |
2017-07-08 18:32:04 +02:00
MessageObject . isVideoMessage ( message ) | |
MessageObject . isRoundVideoMessage ( message ) ) ) {
2014-10-08 22:22:22 +02:00
return 1 ;
2016-03-06 02:49:31 +01:00
} else if ( message . media instanceof TLRPC . TL_messageMediaPhoto | | MessageObject . isVideoMessage ( message ) ) {
2014-10-14 22:36:15 +02:00
return 0 ;
2014-10-08 22:22:22 +02:00
}
2014-10-14 22:36:15 +02:00
return - 1 ;
2014-10-08 22:22:22 +02:00
}
2015-04-09 20:00:14 +02:00
public void putWebPages ( final HashMap < Long , TLRPC . WebPage > webPages ) {
if ( webPages = = null | | webPages . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
final ArrayList < TLRPC . Message > messages = new ArrayList < > ( ) ;
2017-03-31 01:58:05 +02:00
for ( HashMap . Entry < Long , TLRPC . WebPage > entry : webPages . entrySet ( ) ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT mid FROM webpage_pending WHERE id = " + entry . getKey ( ) ) ;
ArrayList < Long > mids = new ArrayList < > ( ) ;
while ( cursor . next ( ) ) {
mids . add ( cursor . longValue ( 0 ) ) ;
}
cursor . dispose ( ) ;
if ( mids . isEmpty ( ) ) {
continue ;
}
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid, data FROM messages WHERE mid IN (%s) " , TextUtils . join ( " , " , mids ) ) ) ;
while ( cursor . next ( ) ) {
int mid = cursor . intValue ( 0 ) ;
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
if ( message . media instanceof TLRPC . TL_messageMediaWebPage ) {
message . id = mid ;
message . media . webpage = entry . getValue ( ) ;
messages . add ( message ) ;
}
2015-04-09 20:00:14 +02:00
}
}
2017-03-31 01:58:05 +02:00
cursor . dispose ( ) ;
2015-04-09 20:00:14 +02:00
}
2017-03-31 01:58:05 +02:00
//database.executeFast(String.format(Locale.US, "DELETE FROM webpage_pending WHERE id IN (%s)", ids)).stepThis().dispose();
2015-04-09 20:00:14 +02:00
if ( messages . isEmpty ( ) ) {
return ;
}
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " UPDATE messages SET data = ? WHERE mid = ? " ) ;
2015-08-13 11:23:31 +02:00
SQLitePreparedStatement state2 = database . executeFast ( " UPDATE media_v2 SET data = ? WHERE mid = ? " ) ;
2016-05-25 23:49:47 +02:00
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
2015-04-09 20:00:14 +02:00
message . serializeToStream ( data ) ;
2015-09-24 22:52:02 +02:00
long messageId = message . id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
2015-04-09 20:00:14 +02:00
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 1 , data ) ;
state . bindLong ( 2 , messageId ) ;
2015-04-09 20:00:14 +02:00
state . step ( ) ;
2015-08-13 11:23:31 +02:00
state2 . requery ( ) ;
2015-09-24 22:52:02 +02:00
state2 . bindByteBuffer ( 1 , data ) ;
state2 . bindLong ( 2 , messageId ) ;
2015-08-13 11:23:31 +02:00
state2 . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2015-04-09 20:00:14 +02:00
}
state . dispose ( ) ;
2015-08-13 11:23:31 +02:00
state2 . dispose ( ) ;
2015-04-09 20:00:14 +02:00
database . commitTransaction ( ) ;
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . didReceivedWebpages , messages ) ;
}
} ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-04-09 20:00:14 +02:00
}
}
} ) ;
}
2015-12-09 19:27:52 +01:00
public void overwriteChannel ( final int channel_id , final TLRPC . TL_updates_channelDifferenceTooLong difference , final int newDialogType ) {
2015-09-24 22:52:02 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-11-26 22:04:02 +01:00
boolean checkInvite = false ;
2015-09-24 22:52:02 +02:00
final long did = - channel_id ;
2017-03-31 01:58:05 +02:00
int pinned = 0 ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT pts, pinned FROM dialogs WHERE did = " + did ) ;
if ( ! cursor . next ( ) ) {
if ( newDialogType ! = 0 ) {
2015-11-26 22:04:02 +01:00
checkInvite = true ;
}
2017-03-31 01:58:05 +02:00
} else {
pinned = cursor . intValue ( 1 ) ;
2015-11-26 22:04:02 +01:00
}
2017-03-31 01:58:05 +02:00
cursor . dispose ( ) ;
2014-08-27 00:26:25 +02:00
2015-09-24 22:52:02 +02:00
database . executeFast ( " DELETE FROM messages WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM bot_keyboard WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_counts_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM messages_holes WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_holes_v2 WHERE uid = " + did ) . stepThis ( ) . dispose ( ) ;
BotQuery . clearBotKeyboard ( did , null ) ;
TLRPC . TL_messages_dialogs dialogs = new TLRPC . TL_messages_dialogs ( ) ;
dialogs . chats . addAll ( difference . chats ) ;
dialogs . users . addAll ( difference . users ) ;
dialogs . messages . addAll ( difference . messages ) ;
2016-06-24 12:27:15 +02:00
TLRPC . TL_dialog dialog = new TLRPC . TL_dialog ( ) ;
2015-09-24 22:52:02 +02:00
dialog . id = did ;
2016-06-24 12:27:15 +02:00
dialog . flags = 1 ;
2015-09-24 22:52:02 +02:00
dialog . peer = new TLRPC . TL_peerChannel ( ) ;
dialog . peer . channel_id = channel_id ;
2016-06-24 12:27:15 +02:00
dialog . top_message = difference . top_message ;
2015-09-24 22:52:02 +02:00
dialog . read_inbox_max_id = difference . read_inbox_max_id ;
2016-06-24 12:27:15 +02:00
dialog . read_outbox_max_id = difference . read_outbox_max_id ;
dialog . unread_count = difference . unread_count ;
2015-09-24 22:52:02 +02:00
dialog . notify_settings = null ;
2017-03-31 01:58:05 +02:00
dialog . pinned = pinned ! = 0 ;
dialog . pinnedNum = pinned ;
2015-09-24 22:52:02 +02:00
dialog . pts = difference . pts ;
dialogs . dialogs . add ( dialog ) ;
2017-03-31 01:58:05 +02:00
putDialogsInternal ( dialogs , false ) ;
2015-09-24 22:52:02 +02:00
2017-03-31 01:58:05 +02:00
MessagesStorage . getInstance ( ) . updateDialogsWithDeletedMessages ( new ArrayList < Integer > ( ) , null , false , channel_id ) ;
2015-09-24 22:52:02 +02:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
@Override
public void run ( ) {
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . removeAllMessagesFromDialog , did , true ) ;
}
} ) ;
2015-11-26 22:04:02 +01:00
if ( checkInvite ) {
2015-12-09 19:27:52 +01:00
if ( newDialogType = = 1 ) {
MessagesController . getInstance ( ) . checkChannelInviter ( channel_id ) ;
} else {
MessagesController . getInstance ( ) . generateJoinMessage ( channel_id , false ) ;
}
2015-11-26 22:04:02 +01:00
}
2015-09-24 22:52:02 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} ) ;
}
public void putChannelViews ( final SparseArray < SparseIntArray > channelViews , final boolean isChannel ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . beginTransaction ( ) ;
SQLitePreparedStatement state = database . executeFast ( " UPDATE messages SET media = max((SELECT media FROM messages WHERE mid = ?), ?) WHERE mid = ? " ) ;
for ( int a = 0 ; a < channelViews . size ( ) ; a + + ) {
int peer = channelViews . keyAt ( a ) ;
SparseIntArray messages = channelViews . get ( peer ) ;
for ( int b = 0 ; b < messages . size ( ) ; b + + ) {
int views = messages . get ( messages . keyAt ( b ) ) ;
long messageId = messages . keyAt ( b ) ;
if ( isChannel ) {
messageId | = ( ( long ) - peer ) < < 32 ;
}
state . requery ( ) ;
state . bindLong ( 1 , messageId ) ;
state . bindInteger ( 2 , views ) ;
state . bindLong ( 3 , messageId ) ;
state . step ( ) ;
}
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} ) ;
}
2016-04-22 15:49:00 +02:00
private boolean isValidKeyboardToSave ( TLRPC . Message message ) {
return message . reply_markup ! = null & & ! ( message . reply_markup instanceof TLRPC . TL_replyInlineMarkup ) & & ( ! message . reply_markup . selective | | message . mentioned ) ;
}
2016-06-24 12:27:15 +02:00
private void putMessagesInternal ( final ArrayList < TLRPC . Message > messages , final boolean withTransaction , final boolean doNotUpdateDialogDate , final int downloadMask , boolean ifNoLastMessage ) {
2015-09-24 22:52:02 +02:00
try {
2016-06-24 12:27:15 +02:00
if ( ifNoLastMessage ) {
TLRPC . Message lastMessage = messages . get ( 0 ) ;
if ( lastMessage . dialog_id = = 0 ) {
if ( lastMessage . to_id . user_id ! = 0 ) {
lastMessage . dialog_id = lastMessage . to_id . user_id ;
} else if ( lastMessage . to_id . chat_id ! = 0 ) {
lastMessage . dialog_id = - lastMessage . to_id . chat_id ;
} else {
lastMessage . dialog_id = - lastMessage . to_id . channel_id ;
}
}
int lastMid = - 1 ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT last_mid FROM dialogs WHERE did = " + lastMessage . dialog_id ) ;
if ( cursor . next ( ) ) {
lastMid = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
if ( lastMid ! = 0 ) {
return ;
}
}
2015-09-24 22:52:02 +02:00
if ( withTransaction ) {
database . beginTransaction ( ) ;
}
HashMap < Long , TLRPC . Message > messagesMap = new HashMap < > ( ) ;
HashMap < Long , Integer > messagesCounts = new HashMap < > ( ) ;
HashMap < Integer , HashMap < Long , Integer > > mediaCounts = null ;
HashMap < Long , TLRPC . Message > botKeyboards = new HashMap < > ( ) ;
HashMap < Long , Long > messagesMediaIdsMap = null ;
StringBuilder messageMediaIds = null ;
HashMap < Long , Integer > mediaTypes = null ;
StringBuilder messageIds = new StringBuilder ( ) ;
2015-12-09 19:27:52 +01:00
HashMap < Long , Integer > dialogsReadMax = new HashMap < > ( ) ;
2015-09-24 22:52:02 +02:00
HashMap < Long , Long > messagesIdsMap = new HashMap < > ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?) " ) ;
SQLitePreparedStatement state2 = null ;
SQLitePreparedStatement state3 = database . executeFast ( " REPLACE INTO randoms VALUES(?, ?) " ) ;
SQLitePreparedStatement state4 = database . executeFast ( " REPLACE INTO download_queue VALUES(?, ?, ?, ?) " ) ;
SQLitePreparedStatement state5 = database . executeFast ( " REPLACE INTO webpage_pending VALUES(?, ?) " ) ;
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
long messageId = message . id ;
if ( message . dialog_id = = 0 ) {
if ( message . to_id . user_id ! = 0 ) {
message . dialog_id = message . to_id . user_id ;
} else if ( message . to_id . chat_id ! = 0 ) {
message . dialog_id = - message . to_id . chat_id ;
} else {
message . dialog_id = - message . to_id . channel_id ;
2014-02-04 19:36:55 +01:00
}
2015-09-24 22:52:02 +02:00
}
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
2014-02-04 19:36:55 +01:00
}
2016-06-24 12:27:15 +02:00
if ( MessageObject . isUnread ( message ) & & ! MessageObject . isOut ( message ) ) {
2015-12-09 19:27:52 +01:00
Integer currentMaxId = dialogsReadMax . get ( message . dialog_id ) ;
if ( currentMaxId = = null ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT inbox_max FROM dialogs WHERE did = " + message . dialog_id ) ;
if ( cursor . next ( ) ) {
currentMaxId = cursor . intValue ( 0 ) ;
} else {
currentMaxId = 0 ;
}
cursor . dispose ( ) ;
dialogsReadMax . put ( message . dialog_id , currentMaxId ) ;
2015-09-24 22:52:02 +02:00
}
2015-12-09 19:27:52 +01:00
if ( message . id < 0 | | currentMaxId < message . id ) {
if ( messageIds . length ( ) > 0 ) {
messageIds . append ( " , " ) ;
}
messageIds . append ( messageId ) ;
2016-06-24 12:27:15 +02:00
messagesIdsMap . put ( messageId , message . dialog_id ) ;
2015-09-24 22:52:02 +02:00
}
}
2015-02-01 19:51:02 +01:00
if ( SharedMediaQuery . canAddMessageToMedia ( message ) ) {
2015-09-24 22:52:02 +02:00
if ( messageMediaIds = = null ) {
messageMediaIds = new StringBuilder ( ) ;
messagesMediaIdsMap = new HashMap < > ( ) ;
mediaTypes = new HashMap < > ( ) ;
}
2014-02-04 19:36:55 +01:00
if ( messageMediaIds . length ( ) > 0 ) {
2014-10-08 22:22:22 +02:00
messageMediaIds . append ( " , " ) ;
2014-02-04 19:36:55 +01:00
}
2015-09-24 22:52:02 +02:00
messageMediaIds . append ( messageId ) ;
messagesMediaIdsMap . put ( messageId , message . dialog_id ) ;
mediaTypes . put ( messageId , SharedMediaQuery . getMediaType ( message ) ) ;
2014-02-04 19:36:55 +01:00
}
2016-04-22 15:49:00 +02:00
if ( isValidKeyboardToSave ( message ) ) {
2015-09-24 22:52:02 +02:00
TLRPC . Message oldMessage = botKeyboards . get ( message . dialog_id ) ;
2015-06-29 19:12:11 +02:00
if ( oldMessage = = null | | oldMessage . id < message . id ) {
2015-09-24 22:52:02 +02:00
botKeyboards . put ( message . dialog_id , message ) ;
2015-06-29 19:12:11 +02:00
}
}
}
for ( HashMap . Entry < Long , TLRPC . Message > entry : botKeyboards . entrySet ( ) ) {
BotQuery . putBotKeyboard ( entry . getKey ( ) , entry . getValue ( ) ) ;
2014-02-04 19:36:55 +01:00
}
2015-09-24 22:52:02 +02:00
if ( messageMediaIds ! = null ) {
2015-02-01 19:51:02 +01:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT mid FROM media_v2 WHERE mid IN( " + messageMediaIds . toString ( ) + " ) " ) ;
2014-02-04 19:36:55 +01:00
while ( cursor . next ( ) ) {
2015-09-24 22:52:02 +02:00
long mid = cursor . longValue ( 0 ) ;
2015-02-01 19:51:02 +01:00
messagesMediaIdsMap . remove ( mid ) ;
2014-02-04 19:36:55 +01:00
}
cursor . dispose ( ) ;
2015-09-24 22:52:02 +02:00
mediaCounts = new HashMap < > ( ) ;
for ( HashMap . Entry < Long , Long > entry : messagesMediaIdsMap . entrySet ( ) ) {
2015-02-01 19:51:02 +01:00
Integer type = mediaTypes . get ( entry . getKey ( ) ) ;
HashMap < Long , Integer > counts = mediaCounts . get ( type ) ;
Integer count ;
if ( counts = = null ) {
counts = new HashMap < > ( ) ;
count = 0 ;
mediaCounts . put ( type , counts ) ;
} else {
count = counts . get ( entry . getValue ( ) ) ;
}
2014-02-04 19:36:55 +01:00
if ( count = = null ) {
count = 0 ;
}
count + + ;
2015-02-01 19:51:02 +01:00
counts . put ( entry . getValue ( ) , count ) ;
2014-02-04 19:36:55 +01:00
}
}
2015-02-01 19:51:02 +01:00
if ( messageIds . length ( ) > 0 ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT mid FROM messages WHERE mid IN( " + messageIds . toString ( ) + " ) " ) ;
2014-02-04 19:36:55 +01:00
while ( cursor . next ( ) ) {
2015-09-24 22:52:02 +02:00
messagesIdsMap . remove ( cursor . longValue ( 0 ) ) ;
2014-02-04 19:36:55 +01:00
}
cursor . dispose ( ) ;
2015-02-01 19:51:02 +01:00
for ( Long dialog_id : messagesIdsMap . values ( ) ) {
Integer count = messagesCounts . get ( dialog_id ) ;
2014-02-04 19:36:55 +01:00
if ( count = = null ) {
count = 0 ;
}
count + + ;
2015-02-01 19:51:02 +01:00
messagesCounts . put ( dialog_id , count ) ;
2014-02-04 19:36:55 +01:00
}
}
2014-08-22 16:24:33 +02:00
int downloadMediaMask = 0 ;
2015-06-29 19:12:11 +02:00
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
TLRPC . Message message = messages . get ( a ) ;
2015-01-09 13:50:15 +01:00
fixUnsupportedMedia ( message ) ;
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
long messageId = message . id ;
2013-10-25 17:19:00 +02:00
if ( message . local_id ! = 0 ) {
messageId = message . local_id ;
}
2015-09-24 22:52:02 +02:00
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
2013-10-25 17:19:00 +02:00
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
2013-10-25 17:19:00 +02:00
message . serializeToStream ( data ) ;
2014-10-22 22:01:07 +02:00
boolean updateDialog = true ;
if ( message . action ! = null & & message . action instanceof TLRPC . TL_messageEncryptedAction & & ! ( message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionSetMessageTTL | | message . action . encryptedAction instanceof TLRPC . TL_decryptedMessageActionScreenshotMessages ) ) {
updateDialog = false ;
2013-10-25 17:19:00 +02:00
}
2014-10-22 22:01:07 +02:00
if ( updateDialog ) {
2016-06-24 12:27:15 +02:00
TLRPC . Message lastMessage = messagesMap . get ( message . dialog_id ) ;
if ( lastMessage = = null | | message . date > lastMessage . date | | message . id > 0 & & lastMessage . id > 0 & & message . id > lastMessage . id | | message . id < 0 & & lastMessage . id < 0 & & message . id < lastMessage . id ) {
messagesMap . put ( message . dialog_id , message ) ;
2014-10-22 22:01:07 +02:00
}
}
2015-09-24 22:52:02 +02:00
state . bindLong ( 1 , messageId ) ;
state . bindLong ( 2 , message . dialog_id ) ;
2015-05-03 13:48:36 +02:00
state . bindInteger ( 3 , MessageObject . getUnreadFlags ( message ) ) ;
2013-10-25 17:19:00 +02:00
state . bindInteger ( 4 , message . send_state ) ;
state . bindInteger ( 5 , message . date ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 6 , data ) ;
2014-10-09 17:55:05 +02:00
state . bindInteger ( 7 , ( MessageObject . isOut ( message ) ? 1 : 0 ) ) ;
2013-10-25 17:19:00 +02:00
state . bindInteger ( 8 , message . ttl ) ;
2015-09-24 22:52:02 +02:00
if ( ( message . flags & TLRPC . MESSAGE_FLAG_HAS_VIEWS ) ! = 0 ) {
state . bindInteger ( 9 , message . views ) ;
} else {
state . bindInteger ( 9 , getMessageMediaType ( message ) ) ;
}
2016-06-24 12:27:15 +02:00
state . bindInteger ( 10 , 0 ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
if ( message . random_id ! = 0 ) {
state3 . requery ( ) ;
state3 . bindLong ( 1 , message . random_id ) ;
2015-09-24 22:52:02 +02:00
state3 . bindLong ( 2 , messageId ) ;
2013-10-25 17:19:00 +02:00
state3 . step ( ) ;
}
2015-02-01 19:51:02 +01:00
if ( SharedMediaQuery . canAddMessageToMedia ( message ) ) {
2015-09-24 22:52:02 +02:00
if ( state2 = = null ) {
state2 = database . executeFast ( " REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?) " ) ;
}
2013-10-25 17:19:00 +02:00
state2 . requery ( ) ;
2015-09-24 22:52:02 +02:00
state2 . bindLong ( 1 , messageId ) ;
state2 . bindLong ( 2 , message . dialog_id ) ;
2013-10-25 17:19:00 +02:00
state2 . bindInteger ( 3 , message . date ) ;
2015-02-01 19:51:02 +01:00
state2 . bindInteger ( 4 , SharedMediaQuery . getMediaType ( message ) ) ;
2015-09-24 22:52:02 +02:00
state2 . bindByteBuffer ( 5 , data ) ;
2013-10-25 17:19:00 +02:00
state2 . step ( ) ;
}
2015-04-09 20:00:14 +02:00
2017-03-31 01:58:05 +02:00
if ( message . media instanceof TLRPC . TL_messageMediaWebPage ) {
2015-04-09 20:00:14 +02:00
state5 . requery ( ) ;
state5 . bindLong ( 1 , message . media . webpage . id ) ;
2015-09-24 22:52:02 +02:00
state5 . bindLong ( 2 , messageId ) ;
2015-04-09 20:00:14 +02:00
state5 . step ( ) ;
}
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-08-22 16:24:33 +02:00
2016-06-24 12:27:15 +02:00
if ( ( message . to_id . channel_id = = 0 | | message . post ) & & message . date > = ConnectionsManager . getInstance ( ) . getCurrentTime ( ) - 60 * 60 & & downloadMask ! = 0 ) {
2016-03-06 02:49:31 +01:00
if ( message . media instanceof TLRPC . TL_messageMediaPhoto | | message . media instanceof TLRPC . TL_messageMediaDocument ) {
2014-08-22 16:24:33 +02:00
int type = 0 ;
long id = 0 ;
2016-03-06 02:49:31 +01:00
TLRPC . MessageMedia object = null ;
if ( MessageObject . isVoiceMessage ( message ) ) {
2017-07-08 18:32:04 +02:00
if ( ( downloadMask & MediaController . AUTODOWNLOAD_MASK_AUDIO ) ! = 0 & & message . media . document . size < 1024 * 1024 * 2 ) {
2016-03-06 02:49:31 +01:00
id = message . media . document . id ;
2014-08-22 16:24:33 +02:00
type = MediaController . AUTODOWNLOAD_MASK_AUDIO ;
2016-03-06 02:49:31 +01:00
object = new TLRPC . TL_messageMediaDocument ( ) ;
object . document = message . media . document ;
2017-07-23 14:56:38 +02:00
object . flags | = 1 ;
2014-08-22 16:24:33 +02:00
}
2017-07-08 18:32:04 +02:00
} else if ( MessageObject . isRoundVideoMessage ( message ) ) {
if ( ( downloadMask & MediaController . AUTODOWNLOAD_MASK_VIDEOMESSAGE ) ! = 0 & & message . media . document . size < 1024 * 1024 * 5 ) {
id = message . media . document . id ;
type = MediaController . AUTODOWNLOAD_MASK_VIDEOMESSAGE ;
object = new TLRPC . TL_messageMediaDocument ( ) ;
object . document = message . media . document ;
2017-07-23 14:56:38 +02:00
object . flags | = 1 ;
2017-07-08 18:32:04 +02:00
}
2014-08-22 16:24:33 +02:00
} else if ( message . media instanceof TLRPC . TL_messageMediaPhoto ) {
if ( ( downloadMask & MediaController . AUTODOWNLOAD_MASK_PHOTO ) ! = 0 ) {
2014-10-01 21:55:24 +02:00
TLRPC . PhotoSize photoSize = FileLoader . getClosestPhotoSizeWithSize ( message . media . photo . sizes , AndroidUtilities . getPhotoSize ( ) ) ;
2014-08-22 16:24:33 +02:00
if ( photoSize ! = null ) {
id = message . media . photo . id ;
type = MediaController . AUTODOWNLOAD_MASK_PHOTO ;
2016-03-06 02:49:31 +01:00
object = new TLRPC . TL_messageMediaPhoto ( ) ;
object . photo = message . media . photo ;
2017-07-23 14:56:38 +02:00
object . flags | = 1 ;
2014-08-22 16:24:33 +02:00
}
}
2016-03-06 02:49:31 +01:00
} else if ( MessageObject . isVideoMessage ( message ) ) {
2014-08-22 16:24:33 +02:00
if ( ( downloadMask & MediaController . AUTODOWNLOAD_MASK_VIDEO ) ! = 0 ) {
2016-03-06 02:49:31 +01:00
id = message . media . document . id ;
2014-08-22 16:24:33 +02:00
type = MediaController . AUTODOWNLOAD_MASK_VIDEO ;
2016-03-06 02:49:31 +01:00
object = new TLRPC . TL_messageMediaDocument ( ) ;
object . document = message . media . document ;
2017-07-23 14:56:38 +02:00
object . flags | = 1 ;
2014-08-22 16:24:33 +02:00
}
2016-01-11 18:19:48 +01:00
} else if ( message . media instanceof TLRPC . TL_messageMediaDocument & & ! MessageObject . isMusicMessage ( message ) & & ! MessageObject . isGifDocument ( message . media . document ) ) {
2014-08-22 16:24:33 +02:00
if ( ( downloadMask & MediaController . AUTODOWNLOAD_MASK_DOCUMENT ) ! = 0 ) {
id = message . media . document . id ;
type = MediaController . AUTODOWNLOAD_MASK_DOCUMENT ;
2016-03-06 02:49:31 +01:00
object = new TLRPC . TL_messageMediaDocument ( ) ;
object . document = message . media . document ;
2017-07-23 14:56:38 +02:00
object . flags | = 1 ;
2014-08-22 16:24:33 +02:00
}
}
if ( object ! = null ) {
2017-07-23 14:56:38 +02:00
if ( message . media . ttl_seconds ! = 0 ) {
object . ttl_seconds = message . media . ttl_seconds ;
object . flags | = 4 ;
}
2014-08-22 16:24:33 +02:00
downloadMediaMask | = type ;
state4 . requery ( ) ;
2015-09-24 22:52:02 +02:00
data = new NativeByteBuffer ( object . getObjectSize ( ) ) ;
2014-08-22 16:24:33 +02:00
object . serializeToStream ( data ) ;
state4 . bindLong ( 1 , id ) ;
state4 . bindInteger ( 2 , type ) ;
state4 . bindInteger ( 3 , message . date ) ;
2015-09-24 22:52:02 +02:00
state4 . bindByteBuffer ( 4 , data ) ;
2014-08-22 16:24:33 +02:00
state4 . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-08-22 16:24:33 +02:00
}
}
}
2013-10-25 17:19:00 +02:00
}
state . dispose ( ) ;
2015-09-24 22:52:02 +02:00
if ( state2 ! = null ) {
state2 . dispose ( ) ;
}
2013-10-25 17:19:00 +02:00
state3 . dispose ( ) ;
2014-08-22 16:24:33 +02:00
state4 . dispose ( ) ;
2015-04-09 20:00:14 +02:00
state5 . dispose ( ) ;
2014-07-27 00:28:33 +02:00
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
HashMap < Long , TLRPC . Message > dids = new HashMap < > ( ) ;
dids . putAll ( messagesMap ) ;
for ( HashMap . Entry < Long , TLRPC . Message > pair : dids . entrySet ( ) ) {
2013-10-25 17:19:00 +02:00
Long key = pair . getKey ( ) ;
2015-09-24 22:52:02 +02:00
if ( key = = 0 ) {
continue ;
}
TLRPC . Message message = messagesMap . get ( key ) ;
2014-07-27 00:28:33 +02:00
2015-09-24 22:52:02 +02:00
int channelId = 0 ;
if ( message ! = null ) {
channelId = message . to_id . channel_id ;
}
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( " SELECT date, unread_count, pts, last_mid, inbox_max, outbox_max, pinned FROM dialogs WHERE did = " + key ) ;
2014-07-27 00:28:33 +02:00
int dialog_date = 0 ;
2015-09-24 22:52:02 +02:00
int last_mid = 0 ;
2014-07-27 00:28:33 +02:00
int old_unread_count = 0 ;
2015-09-24 22:52:02 +02:00
int pts = channelId ! = 0 ? 1 : 0 ;
2015-11-26 22:04:02 +01:00
int inbox_max = 0 ;
2016-06-24 12:27:15 +02:00
int outbox_max = 0 ;
2017-03-31 01:58:05 +02:00
int pinned = 0 ;
2014-07-27 00:28:33 +02:00
if ( cursor . next ( ) ) {
dialog_date = cursor . intValue ( 0 ) ;
old_unread_count = cursor . intValue ( 1 ) ;
2016-06-24 12:27:15 +02:00
pts = cursor . intValue ( 2 ) ;
last_mid = cursor . intValue ( 3 ) ;
inbox_max = cursor . intValue ( 4 ) ;
outbox_max = cursor . intValue ( 5 ) ;
2017-03-31 01:58:05 +02:00
pinned = cursor . intValue ( 6 ) ;
2015-09-24 22:52:02 +02:00
} else if ( channelId ! = 0 ) {
MessagesController . getInstance ( ) . checkChannelInviter ( channelId ) ;
2014-07-27 00:28:33 +02:00
}
cursor . dispose ( ) ;
2013-10-25 17:19:00 +02:00
Integer unread_count = messagesCounts . get ( key ) ;
if ( unread_count = = null ) {
unread_count = 0 ;
2014-08-22 16:24:33 +02:00
} else {
2014-08-27 00:26:25 +02:00
messagesCounts . put ( key , unread_count + old_unread_count ) ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
long messageId = message ! = null ? message . id : last_mid ;
if ( message ! = null ) {
if ( message . local_id ! = 0 ) {
messageId = message . local_id ;
}
}
if ( channelId ! = 0 ) {
messageId | = ( ( long ) channelId ) < < 32 ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
2015-11-26 22:04:02 +01:00
state . requery ( ) ;
2013-10-25 17:19:00 +02:00
state . bindLong ( 1 , key ) ;
2015-09-24 22:52:02 +02:00
if ( message ! = null & & ( ! doNotUpdateDialogDate | | dialog_date = = 0 ) ) {
state . bindInteger ( 2 , message . date ) ;
2014-07-27 00:28:33 +02:00
} else {
2015-09-24 22:52:02 +02:00
state . bindInteger ( 2 , dialog_date ) ;
2014-07-27 00:28:33 +02:00
}
2014-08-06 23:27:24 +02:00
state . bindInteger ( 3 , old_unread_count + unread_count ) ;
2015-09-24 22:52:02 +02:00
state . bindLong ( 4 , messageId ) ;
2015-11-26 22:04:02 +01:00
state . bindInteger ( 5 , inbox_max ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 6 , outbox_max ) ;
state . bindLong ( 7 , 0 ) ;
state . bindInteger ( 8 , 0 ) ;
2015-09-24 22:52:02 +02:00
state . bindInteger ( 9 , pts ) ;
2016-06-24 12:27:15 +02:00
state . bindInteger ( 10 , 0 ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 11 , pinned ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
}
state . dispose ( ) ;
2015-09-24 22:52:02 +02:00
if ( mediaCounts ! = null ) {
state3 = database . executeFast ( " REPLACE INTO media_counts_v2 VALUES(?, ?, ?) " ) ;
2015-02-01 19:51:02 +01:00
for ( HashMap . Entry < Integer , HashMap < Long , Integer > > counts : mediaCounts . entrySet ( ) ) {
Integer type = counts . getKey ( ) ;
for ( HashMap . Entry < Long , Integer > pair : counts . getValue ( ) . entrySet ( ) ) {
long uid = pair . getKey ( ) ;
int lower_part = ( int ) uid ;
int count = - 1 ;
SQLiteCursor cursor = database . 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 ( ) ;
if ( count ! = - 1 ) {
2015-09-24 22:52:02 +02:00
state3 . requery ( ) ;
2015-02-01 19:51:02 +01:00
count + = pair . getValue ( ) ;
2015-09-24 22:52:02 +02:00
state3 . bindLong ( 1 , uid ) ;
state3 . bindInteger ( 2 , type ) ;
state3 . bindInteger ( 3 , count ) ;
state3 . step ( ) ;
2015-02-01 19:51:02 +01:00
}
2013-10-25 17:19:00 +02:00
}
}
2015-09-24 22:52:02 +02:00
state3 . dispose ( ) ;
2013-10-25 17:19:00 +02:00
}
2015-02-01 19:51:02 +01:00
if ( withTransaction ) {
database . commitTransaction ( ) ;
}
MessagesController . getInstance ( ) . processDialogsUpdateRead ( messagesCounts ) ;
2013-10-25 17:19:00 +02:00
2014-08-22 16:24:33 +02:00
if ( downloadMediaMask ! = 0 ) {
final int downloadMediaMaskFinal = downloadMediaMask ;
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-08-22 16:24:33 +02:00
@Override
public void run ( ) {
MediaController . getInstance ( ) . newDownloadObjectsAvailable ( downloadMediaMaskFinal ) ;
}
} ) ;
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
2015-09-24 22:52:02 +02:00
public void putMessages ( final ArrayList < TLRPC . Message > messages , final boolean withTransaction , boolean useQueue , final boolean doNotUpdateDialogDate , final int downloadMask ) {
2016-06-24 12:27:15 +02:00
putMessages ( messages , withTransaction , useQueue , doNotUpdateDialogDate , downloadMask , false ) ;
}
public void putMessages ( final ArrayList < TLRPC . Message > messages , final boolean withTransaction , boolean useQueue , final boolean doNotUpdateDialogDate , final int downloadMask , final boolean ifNoLastMessage ) {
2013-10-25 17:19:00 +02:00
if ( messages . size ( ) = = 0 ) {
return ;
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2016-06-24 12:27:15 +02:00
putMessagesInternal ( messages , withTransaction , doNotUpdateDialogDate , downloadMask , ifNoLastMessage ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2016-06-24 12:27:15 +02:00
putMessagesInternal ( messages , withTransaction , doNotUpdateDialogDate , downloadMask , ifNoLastMessage ) ;
2013-10-25 17:19:00 +02:00
}
}
2015-09-24 22:52:02 +02:00
public void markMessageAsSendError ( final TLRPC . Message message ) {
2014-08-27 00:26:25 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-09-24 22:52:02 +02:00
long messageId = message . id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
database . executeFast ( " UPDATE messages SET send_state = 2 WHERE mid = " + messageId ) . stepThis ( ) . dispose ( ) ;
2014-08-27 00:26:25 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-08-27 00:26:25 +02:00
}
}
} ) ;
}
2014-10-29 15:28:54 +01:00
/ * public void getHoleMessages ( ) {
2014-10-28 18:07:44 +01:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-28 18:07:44 +01:00
}
}
} ) ;
}
public void clearHoleMessages ( final int enc_id ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
database . executeFast ( " DELETE FROM secret_holes WHERE uid = " + enc_id ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-28 18:07:44 +01:00
}
}
} ) ;
}
public void putHoleMessage ( final int enc_id , final TLRPC . Message message ) {
if ( message = = null ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO secret_holes VALUES(?, ?, ?, ?) " ) ;
state . requery ( ) ;
2015-09-24 22:52:02 +02:00
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
2014-10-28 18:07:44 +01:00
message . serializeToStream ( data ) ;
state . bindInteger ( 1 , enc_id ) ;
state . bindInteger ( 2 , message . seq_in ) ;
state . bindInteger ( 3 , message . seq_out ) ;
2015-09-24 22:52:02 +02:00
state . bindByteBuffer ( 4 , data ) ;
2014-10-28 18:07:44 +01:00
state . step ( ) ;
2015-09-24 22:52:02 +02:00
data . reuse ( ) ;
2014-10-28 18:07:44 +01:00
state . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-28 18:07:44 +01:00
}
}
} ) ;
2014-10-29 15:28:54 +01:00
} * /
2014-10-28 18:07:44 +01:00
2014-10-22 22:01:07 +02:00
public void setMessageSeq ( final int mid , final int seq_in , final int seq_out ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages_seq VALUES(?, ?, ?) " ) ;
state . requery ( ) ;
state . bindInteger ( 1 , mid ) ;
state . bindInteger ( 2 , seq_in ) ;
state . bindInteger ( 3 , seq_out ) ;
state . step ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-22 22:01:07 +02:00
}
}
} ) ;
}
2015-09-24 22:52:02 +02:00
private long [ ] updateMessageStateAndIdInternal ( long random_id , Integer _oldId , int newId , int date , int channelId ) {
SQLiteCursor cursor = null ;
long oldMessageId ;
long newMessageId = newId ;
if ( _oldId = = null ) {
try {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM randoms WHERE random_id = %d LIMIT 1 " , random_id ) ) ;
if ( cursor . next ( ) ) {
_oldId = cursor . intValue ( 0 ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
}
if ( _oldId = = null ) {
return null ;
}
}
oldMessageId = _oldId ;
if ( channelId ! = 0 ) {
oldMessageId | = ( ( long ) channelId ) < < 32 ;
newMessageId | = ( ( long ) channelId ) < < 32 ;
}
long did = 0 ;
try {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT uid FROM messages WHERE mid = %d LIMIT 1 " , oldMessageId ) ) ;
if ( cursor . next ( ) ) {
did = cursor . longValue ( 0 ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
}
if ( did = = 0 ) {
return null ;
}
if ( oldMessageId = = newMessageId & & date ! = 0 ) {
2013-10-25 17:19:00 +02:00
SQLitePreparedStatement state = null ;
try {
state = database . executeFast ( " UPDATE messages SET send_state = 0, date = ? WHERE mid = ? " ) ;
state . bindInteger ( 1 , date ) ;
2015-09-24 22:52:02 +02:00
state . bindLong ( 2 , newMessageId ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
2014-10-22 22:01:07 +02:00
2016-06-24 12:27:15 +02:00
return new long [ ] { did , newId } ;
2013-10-25 17:19:00 +02:00
} else {
SQLitePreparedStatement state = null ;
try {
state = database . executeFast ( " UPDATE messages SET mid = ?, send_state = 0 WHERE mid = ? " ) ;
2015-09-24 22:52:02 +02:00
state . bindLong ( 1 , newMessageId ) ;
state . bindLong ( 2 , oldMessageId ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
} catch ( Exception e ) {
2015-02-01 19:51:02 +01:00
try {
2015-09-24 22:52:02 +02:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM messages WHERE mid = %d " , oldMessageId ) ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( String . format ( Locale . US , " DELETE FROM messages_seq WHERE mid = %d " , oldMessageId ) ) . stepThis ( ) . dispose ( ) ;
2015-02-01 19:51:02 +01:00
} catch ( Exception e2 ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e2 ) ;
2015-02-01 19:51:02 +01:00
}
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
2014-10-22 22:01:07 +02:00
state = null ;
2013-10-25 17:19:00 +02:00
}
}
try {
2015-02-01 19:51:02 +01:00
state = database . executeFast ( " UPDATE media_v2 SET mid = ? WHERE mid = ? " ) ;
2015-09-24 22:52:02 +02:00
state . bindLong ( 1 , newMessageId ) ;
state . bindLong ( 2 , oldMessageId ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
} catch ( Exception e ) {
2015-02-01 19:51:02 +01:00
try {
2015-09-24 22:52:02 +02:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_v2 WHERE mid = %d " , oldMessageId ) ) . stepThis ( ) . dispose ( ) ;
2015-02-01 19:51:02 +01:00
} catch ( Exception e2 ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e2 ) ;
2015-02-01 19:51:02 +01:00
}
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
2014-10-22 22:01:07 +02:00
state = null ;
2013-10-25 17:19:00 +02:00
}
}
try {
state = database . executeFast ( " UPDATE dialogs SET last_mid = ? WHERE last_mid = ? " ) ;
2015-09-24 22:52:02 +02:00
state . bindLong ( 1 , newMessageId ) ;
state . bindLong ( 2 , oldMessageId ) ;
2013-10-25 17:19:00 +02:00
state . step ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
} finally {
if ( state ! = null ) {
state . dispose ( ) ;
}
}
2016-06-24 12:27:15 +02:00
return new long [ ] { did , _oldId } ;
2013-10-25 17:19:00 +02:00
}
}
2015-09-24 22:52:02 +02:00
public long [ ] updateMessageStateAndId ( final long random_id , final Integer _oldId , final int newId , final int date , boolean useQueue , final int channelId ) {
2013-10-25 17:19:00 +02:00
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-09-24 22:52:02 +02:00
updateMessageStateAndIdInternal ( random_id , _oldId , newId , date , channelId ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2015-09-24 22:52:02 +02:00
return updateMessageStateAndIdInternal ( random_id , _oldId , newId , date , channelId ) ;
2013-10-25 17:19:00 +02:00
}
return null ;
}
private void updateUsersInternal ( final ArrayList < TLRPC . User > users , final boolean onlyStatus , final boolean withTransaction ) {
if ( Thread . currentThread ( ) . getId ( ) ! = storageQueue . getId ( ) ) {
throw new RuntimeException ( " wrong db thread " ) ;
}
try {
if ( onlyStatus ) {
if ( withTransaction ) {
database . beginTransaction ( ) ;
}
SQLitePreparedStatement state = database . executeFast ( " UPDATE users SET status = ? WHERE uid = ? " ) ;
for ( TLRPC . User user : users ) {
state . requery ( ) ;
if ( user . status ! = null ) {
2014-02-28 23:28:25 +01:00
state . bindInteger ( 1 , user . status . expires ) ;
2013-10-25 17:19:00 +02:00
} else {
state . bindInteger ( 1 , 0 ) ;
}
state . bindInteger ( 2 , user . id ) ;
state . step ( ) ;
}
state . dispose ( ) ;
if ( withTransaction ) {
database . commitTransaction ( ) ;
}
} else {
2014-10-08 22:22:22 +02:00
StringBuilder ids = new StringBuilder ( ) ;
2015-01-02 23:15:07 +01:00
HashMap < Integer , TLRPC . User > usersDict = new HashMap < > ( ) ;
2013-10-25 17:19:00 +02:00
for ( TLRPC . User user : users ) {
if ( ids . length ( ) ! = 0 ) {
2014-10-08 22:22:22 +02:00
ids . append ( " , " ) ;
2013-10-25 17:19:00 +02:00
}
2014-10-08 22:22:22 +02:00
ids . append ( user . id ) ;
2013-10-25 17:19:00 +02:00
usersDict . put ( user . id , user ) ;
}
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . User > loadedUsers = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getUsersInternal ( ids . toString ( ) , loadedUsers ) ;
for ( TLRPC . User user : loadedUsers ) {
TLRPC . User updateUser = usersDict . get ( user . id ) ;
if ( updateUser ! = null ) {
2013-10-25 17:19:00 +02:00
if ( updateUser . first_name ! = null & & updateUser . last_name ! = null ) {
2015-06-29 19:12:11 +02:00
if ( ! UserObject . isContact ( user ) ) {
2015-05-03 13:48:36 +02:00
user . first_name = updateUser . first_name ;
user . last_name = updateUser . last_name ;
}
2014-10-17 20:29:13 +02:00
user . username = updateUser . username ;
2013-10-25 17:19:00 +02:00
} else if ( updateUser . photo ! = null ) {
user . photo = updateUser . photo ;
2014-12-01 18:56:31 +01:00
} else if ( updateUser . phone ! = null ) {
user . phone = updateUser . phone ;
2013-10-25 17:19:00 +02:00
}
}
}
2014-10-23 17:30:35 +02:00
2013-10-25 17:19:00 +02:00
if ( ! loadedUsers . isEmpty ( ) ) {
if ( withTransaction ) {
database . beginTransaction ( ) ;
}
2014-10-23 17:30:35 +02:00
putUsersInternal ( loadedUsers ) ;
2013-10-25 17:19:00 +02:00
if ( withTransaction ) {
database . commitTransaction ( ) ;
}
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
public void updateUsers ( final ArrayList < TLRPC . User > users , final boolean onlyStatus , final boolean withTransaction , boolean useQueue ) {
if ( users . isEmpty ( ) ) {
return ;
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
updateUsersInternal ( users , onlyStatus , withTransaction ) ;
}
} ) ;
} else {
updateUsersInternal ( users , onlyStatus , withTransaction ) ;
}
}
2016-06-24 12:27:15 +02:00
private void markMessagesAsReadInternal ( SparseArray < Long > inbox , SparseArray < Long > outbox , HashMap < Integer , Integer > encryptedMessages ) {
2013-10-25 17:19:00 +02:00
try {
2015-03-19 00:09:45 +01:00
if ( inbox ! = null ) {
2015-09-24 22:52:02 +02:00
for ( int b = 0 ; b < inbox . size ( ) ; b + + ) {
int key = inbox . keyAt ( b ) ;
long messageId = inbox . get ( key ) ;
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid > 0 AND mid <= %d AND read_state IN(0,2) AND out = 0 " , key , messageId ) ) . stepThis ( ) . dispose ( ) ;
2015-03-19 00:09:45 +01:00
}
}
if ( outbox ! = null ) {
2015-09-24 22:52:02 +02:00
for ( int b = 0 ; b < outbox . size ( ) ; b + + ) {
int key = outbox . keyAt ( b ) ;
2016-06-24 12:27:15 +02:00
long messageId = outbox . get ( key ) ;
2015-09-24 22:52:02 +02:00
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET read_state = read_state | 1 WHERE uid = %d AND mid > 0 AND mid <= %d AND read_state IN(0,2) AND out = 1 " , key , messageId ) ) . stepThis ( ) . dispose ( ) ;
2015-03-19 00:09:45 +01:00
}
2013-10-25 17:19:00 +02:00
}
if ( encryptedMessages ! = null & & ! encryptedMessages . isEmpty ( ) ) {
for ( HashMap . Entry < Integer , Integer > entry : encryptedMessages . entrySet ( ) ) {
2016-06-24 12:27:15 +02:00
long dialog_id = ( ( long ) entry . getKey ( ) ) < < 32 ;
2013-10-25 17:19:00 +02:00
int max_date = entry . getValue ( ) ;
2015-05-03 13:48:36 +02:00
SQLitePreparedStatement state = database . executeFast ( " UPDATE messages SET read_state = read_state | 1 WHERE uid = ? AND date <= ? AND read_state IN(0,2) AND out = 1 " ) ;
2013-10-25 17:19:00 +02:00
state . requery ( ) ;
state . bindLong ( 1 , dialog_id ) ;
state . bindInteger ( 2 , max_date ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
2017-07-23 14:56:38 +02:00
public void markMessagesContentAsRead ( final ArrayList < Long > mids , final int date ) {
2015-05-03 13:48:36 +02:00
if ( mids = = null | | mids . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2017-07-23 14:56:38 +02:00
String midsStr = TextUtils . join ( " , " , mids ) ;
database . executeFast ( String . format ( Locale . US , " UPDATE messages SET read_state = read_state | 2 WHERE mid IN (%s) " , midsStr ) ) . stepThis ( ) . dispose ( ) ;
if ( date ! = 0 ) {
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid, ttl FROM messages WHERE mid IN (%s) AND ttl > 0 " , midsStr ) ) ;
ArrayList < Integer > arrayList = null ;
while ( cursor . next ( ) ) {
if ( arrayList = = null ) {
arrayList = new ArrayList < > ( ) ;
}
arrayList . add ( cursor . intValue ( 0 ) ) ;
}
if ( arrayList ! = null ) {
emptyMessagesMedia ( arrayList ) ;
}
cursor . dispose ( ) ;
}
2015-05-03 13:48:36 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-05-03 13:48:36 +02:00
}
}
} ) ;
}
2016-06-24 12:27:15 +02:00
public void markMessagesAsRead ( final SparseArray < Long > inbox , final SparseArray < Long > outbox , final HashMap < Integer , Integer > encryptedMessages , boolean useQueue ) {
2013-10-25 17:19:00 +02:00
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-03-19 00:09:45 +01:00
markMessagesAsReadInternal ( inbox , outbox , encryptedMessages ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2015-03-19 00:09:45 +01:00
markMessagesAsReadInternal ( inbox , outbox , encryptedMessages ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-03-22 23:31:55 +01:00
public void markMessagesAsDeletedByRandoms ( final ArrayList < Long > messages ) {
if ( messages . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2014-10-08 22:22:22 +02:00
String ids = TextUtils . join ( " , " , messages ) ;
2014-03-22 23:31:55 +01:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid FROM randoms WHERE random_id IN(%s) " , ids ) ) ;
2015-01-02 23:15:07 +01:00
final ArrayList < Integer > mids = new ArrayList < > ( ) ;
2014-03-22 23:31:55 +01:00
while ( cursor . next ( ) ) {
mids . add ( cursor . intValue ( 0 ) ) ;
}
cursor . dispose ( ) ;
if ( ! mids . isEmpty ( ) ) {
2014-11-06 22:34:47 +01:00
AndroidUtilities . runOnUIThread ( new Runnable ( ) {
2014-03-22 23:31:55 +01:00
@Override
public void run ( ) {
2015-09-24 22:52:02 +02:00
NotificationCenter . getInstance ( ) . postNotificationName ( NotificationCenter . messagesDeleted , mids , 0 ) ;
2014-03-22 23:31:55 +01:00
}
} ) ;
2016-06-24 12:27:15 +02:00
MessagesStorage . getInstance ( ) . updateDialogsWithReadMessagesInternal ( mids , null , null ) ;
2015-09-24 22:52:02 +02:00
MessagesStorage . getInstance ( ) . markMessagesAsDeletedInternal ( mids , 0 ) ;
2017-03-31 01:58:05 +02:00
MessagesStorage . getInstance ( ) . updateDialogsWithDeletedMessagesInternal ( mids , null , 0 ) ;
2014-03-22 23:31:55 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-03-22 23:31:55 +01:00
}
}
} ) ;
}
2017-03-31 01:58:05 +02:00
private ArrayList < Long > markMessagesAsDeletedInternal ( final ArrayList < Integer > messages , int channelId ) {
2013-10-25 17:19:00 +02:00
try {
2015-09-24 22:52:02 +02:00
String ids ;
2017-03-31 01:58:05 +02:00
ArrayList < Long > dialogsIds = new ArrayList < > ( ) ;
HashMap < Long , Integer > dialogsToUpdate = new HashMap < > ( ) ;
2015-09-24 22:52:02 +02:00
if ( channelId ! = 0 ) {
StringBuilder builder = new StringBuilder ( messages . size ( ) ) ;
for ( int a = 0 ; a < messages . size ( ) ; a + + ) {
long messageId = messages . get ( a ) ;
messageId | = ( ( long ) channelId ) < < 32 ;
if ( builder . length ( ) > 0 ) {
builder . append ( ',' ) ;
}
builder . append ( messageId ) ;
}
ids = builder . toString ( ) ;
} else {
ids = TextUtils . join ( " , " , messages ) ;
}
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT uid, data, read_state, out FROM messages WHERE mid IN(%s) " , ids ) ) ;
2015-01-02 23:15:07 +01:00
ArrayList < File > filesToDelete = new ArrayList < > ( ) ;
2017-03-31 01:58:05 +02:00
int currentUser = UserConfig . getClientUserId ( ) ;
2014-10-22 22:01:07 +02:00
try {
while ( cursor . next ( ) ) {
long did = cursor . longValue ( 0 ) ;
2017-03-31 01:58:05 +02:00
if ( did = = currentUser ) {
continue ;
}
int read_state = cursor . intValue ( 2 ) ;
if ( ( read_state = = 0 | | read_state = = 2 ) & & cursor . intValue ( 3 ) = = 0 ) {
Integer unread_count = dialogsToUpdate . get ( did ) ;
if ( unread_count = = null ) {
unread_count = 0 ;
}
2015-11-26 22:04:02 +01:00
unread_count + + ;
2017-03-31 01:58:05 +02:00
dialogsToUpdate . put ( did , unread_count ) ;
2015-11-26 22:04:02 +01:00
}
if ( ( int ) did ! = 0 ) {
2014-10-22 22:01:07 +02:00
continue ;
}
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
if ( message ! = null ) {
2016-03-16 13:26:32 +01:00
if ( message . media instanceof TLRPC . TL_messageMediaPhoto ) {
for ( TLRPC . PhotoSize photoSize : message . media . photo . sizes ) {
File file = FileLoader . getPathToAttach ( photoSize ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
} else if ( message . media instanceof TLRPC . TL_messageMediaDocument ) {
File file = FileLoader . getPathToAttach ( message . media . document ) ;
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
file = FileLoader . getPathToAttach ( message . media . document . thumb ) ;
2014-10-22 22:01:07 +02:00
if ( file ! = null & & file . toString ( ) . length ( ) > 0 ) {
filesToDelete . add ( file ) ;
}
}
}
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-10-22 22:01:07 +02:00
}
cursor . dispose ( ) ;
2015-12-09 19:27:52 +01:00
FileLoader . getInstance ( ) . deleteFiles ( filesToDelete , 0 ) ;
2015-11-26 22:04:02 +01:00
2017-03-31 01:58:05 +02:00
for ( HashMap . Entry < Long , Integer > entry : dialogsToUpdate . entrySet ( ) ) {
Long did = entry . getKey ( ) ;
dialogsIds . add ( did ) ;
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET unread_count = max(0, ((SELECT unread_count FROM dialogs WHERE did = ?) - ?)) WHERE did = ? " ) ;
2015-11-26 22:04:02 +01:00
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
2017-03-31 01:58:05 +02:00
state . bindInteger ( 2 , entry . getValue ( ) ) ;
2015-11-26 22:04:02 +01:00
state . bindLong ( 3 , did ) ;
state . step ( ) ;
state . dispose ( ) ;
}
2014-02-28 23:28:25 +01:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM messages WHERE mid IN(%s) " , ids ) ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM bot_keyboard WHERE mid IN(%s) " , ids ) ) . stepThis ( ) . dispose ( ) ;
2014-10-22 22:01:07 +02:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM messages_seq WHERE mid IN(%s) " , ids ) ) . stepThis ( ) . dispose ( ) ;
2015-02-01 19:51:02 +01:00
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_v2 WHERE mid IN(%s) " , ids ) ) . stepThis ( ) . dispose ( ) ;
database . executeFast ( " DELETE FROM media_counts_v2 WHERE 1 " ) . stepThis ( ) . dispose ( ) ;
2015-06-29 19:12:11 +02:00
BotQuery . clearBotKeyboard ( 0 , messages ) ;
2017-03-31 01:58:05 +02:00
return dialogsIds ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
return null ;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
private void updateDialogsWithDeletedMessagesInternal ( final ArrayList < Integer > messages , ArrayList < Long > additionalDialogsToUpdate , int channelId ) {
2013-10-25 17:19:00 +02:00
if ( Thread . currentThread ( ) . getId ( ) ! = storageQueue . getId ( ) ) {
throw new RuntimeException ( " wrong db thread " ) ;
}
try {
2015-09-24 22:52:02 +02:00
String ids ;
2017-03-31 01:58:05 +02:00
ArrayList < Long > dialogsToUpdate = new ArrayList < > ( ) ;
2015-09-24 22:52:02 +02:00
if ( ! messages . isEmpty ( ) ) {
2015-11-26 22:04:02 +01:00
SQLitePreparedStatement state ;
2015-09-24 22:52:02 +02:00
if ( channelId ! = 0 ) {
2015-11-26 22:04:02 +01:00
dialogsToUpdate . add ( ( long ) - channelId ) ;
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " UPDATE dialogs SET last_mid = (SELECT mid FROM messages WHERE uid = ? AND date = (SELECT MAX(date) FROM messages WHERE uid = ?)) WHERE did = ? " ) ;
2015-09-24 22:52:02 +02:00
} else {
ids = TextUtils . join ( " , " , messages ) ;
2015-11-26 22:04:02 +01:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT did FROM dialogs WHERE last_mid IN(%s) " , ids ) ) ;
while ( cursor . next ( ) ) {
dialogsToUpdate . add ( cursor . longValue ( 0 ) ) ;
}
cursor . dispose ( ) ;
2017-03-31 01:58:05 +02:00
state = database . executeFast ( " UPDATE dialogs SET last_mid = (SELECT mid FROM messages WHERE uid = ? AND date = (SELECT MAX(date) FROM messages WHERE uid = ? AND date != 0)) WHERE did = ? " ) ;
2015-09-24 22:52:02 +02:00
}
database . beginTransaction ( ) ;
2015-11-26 22:04:02 +01:00
for ( int a = 0 ; a < dialogsToUpdate . size ( ) ; a + + ) {
long did = dialogsToUpdate . get ( a ) ;
2015-09-24 22:52:02 +02:00
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindLong ( 2 , did ) ;
state . bindLong ( 3 , did ) ;
state . step ( ) ;
}
state . dispose ( ) ;
database . commitTransaction ( ) ;
} else {
2017-03-31 01:58:05 +02:00
dialogsToUpdate . add ( ( long ) - channelId ) ;
}
if ( additionalDialogsToUpdate ! = null ) {
for ( int a = 0 ; a < additionalDialogsToUpdate . size ( ) ; a + + ) {
Long did = additionalDialogsToUpdate . get ( a ) ;
if ( ! dialogsToUpdate . contains ( did ) ) {
dialogsToUpdate . add ( did ) ;
}
}
2015-09-24 22:52:02 +02:00
}
2017-03-31 01:58:05 +02:00
ids = TextUtils . join ( " , " , dialogsToUpdate ) ;
2013-10-25 17:19:00 +02:00
TLRPC . messages_Dialogs dialogs = new TLRPC . messages_Dialogs ( ) ;
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > encryptedToLoad = new ArrayList < > ( ) ;
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, m.date, d.pts, d.inbox_max, d.outbox_max, d.pinned FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid WHERE d.did IN(%s) " , ids ) ) ;
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
2016-06-24 12:27:15 +02:00
TLRPC . TL_dialog dialog = new TLRPC . TL_dialog ( ) ;
2013-10-25 17:19:00 +02:00
dialog . id = cursor . longValue ( 0 ) ;
dialog . top_message = cursor . intValue ( 1 ) ;
2016-06-24 12:27:15 +02:00
dialog . read_inbox_max_id = cursor . intValue ( 10 ) ;
dialog . read_outbox_max_id = cursor . intValue ( 11 ) ;
2013-10-25 17:19:00 +02:00
dialog . unread_count = cursor . intValue ( 2 ) ;
dialog . last_message_date = cursor . intValue ( 3 ) ;
2016-06-24 12:27:15 +02:00
dialog . pts = cursor . intValue ( 9 ) ;
dialog . flags = channelId = = 0 ? 0 : 1 ;
2017-03-31 01:58:05 +02:00
dialog . pinnedNum = cursor . intValue ( 12 ) ;
dialog . pinned = dialog . pinnedNum ! = 0 ;
2015-09-24 22:52:02 +02:00
2013-10-25 17:19:00 +02:00
dialogs . dialogs . add ( dialog ) ;
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 4 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2015-05-03 13:48:36 +02:00
MessageObject . setUnreadFlags ( message , cursor . intValue ( 5 ) ) ;
2013-10-25 17:19:00 +02:00
message . id = cursor . intValue ( 6 ) ;
message . send_state = cursor . intValue ( 7 ) ;
2015-02-26 02:32:51 +01:00
int date = cursor . intValue ( 8 ) ;
if ( date ! = 0 ) {
dialog . last_message_date = date ;
}
2015-09-24 22:52:02 +02:00
message . dialog_id = dialog . id ;
2013-10-25 17:19:00 +02:00
dialogs . messages . add ( message ) ;
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2013-10-25 17:19:00 +02:00
}
2016-06-24 12:27:15 +02:00
int lower_id = ( int ) dialog . id ;
int high_id = ( int ) ( dialog . id > > 32 ) ;
2013-10-25 17:19:00 +02:00
if ( lower_id ! = 0 ) {
2014-07-27 12:53:00 +02:00
if ( high_id = = 1 ) {
if ( ! chatsToLoad . contains ( lower_id ) ) {
chatsToLoad . add ( lower_id ) ;
2013-10-25 17:19:00 +02:00
}
} else {
2014-07-27 12:53:00 +02:00
if ( lower_id > 0 ) {
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
}
} else {
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
}
2013-10-25 17:19:00 +02:00
}
}
} else {
2014-07-27 12:53:00 +02:00
if ( ! encryptedToLoad . contains ( high_id ) ) {
encryptedToLoad . add ( high_id ) ;
2013-10-25 17:19:00 +02:00
}
}
}
cursor . dispose ( ) ;
if ( ! encryptedToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getEncryptedChatsInternal ( TextUtils . join ( " , " , encryptedToLoad ) , encryptedChats , usersToLoad ) ;
2013-10-25 17:19:00 +02:00
}
if ( ! chatsToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , dialogs . chats ) ;
2013-10-25 17:19:00 +02:00
}
if ( ! usersToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , dialogs . users ) ;
2013-10-25 17:19:00 +02:00
}
if ( ! dialogs . dialogs . isEmpty ( ) | | ! encryptedChats . isEmpty ( ) ) {
2014-03-22 23:31:55 +01:00
MessagesController . getInstance ( ) . processDialogsUpdate ( dialogs , encryptedChats ) ;
2013-10-25 17:19:00 +02:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
2017-03-31 01:58:05 +02:00
public void updateDialogsWithDeletedMessages ( final ArrayList < Integer > messages , final ArrayList < Long > additionalDialogsToUpdate , boolean useQueue , final int channelId ) {
2015-09-24 22:52:02 +02:00
if ( messages . isEmpty ( ) & & channelId = = 0 ) {
2013-10-25 17:19:00 +02:00
return ;
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2017-03-31 01:58:05 +02:00
updateDialogsWithDeletedMessagesInternal ( messages , additionalDialogsToUpdate , channelId ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2017-03-31 01:58:05 +02:00
updateDialogsWithDeletedMessagesInternal ( messages , additionalDialogsToUpdate , channelId ) ;
2013-10-25 17:19:00 +02:00
}
}
2017-03-31 01:58:05 +02:00
public ArrayList < Long > markMessagesAsDeleted ( final ArrayList < Integer > messages , boolean useQueue , final int channelId ) {
2013-10-25 17:19:00 +02:00
if ( messages . isEmpty ( ) ) {
2017-03-31 01:58:05 +02:00
return null ;
2013-10-25 17:19:00 +02:00
}
if ( useQueue ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2015-09-24 22:52:02 +02:00
markMessagesAsDeletedInternal ( messages , channelId ) ;
2013-10-25 17:19:00 +02:00
}
} ) ;
} else {
2017-03-31 01:58:05 +02:00
return markMessagesAsDeletedInternal ( messages , channelId ) ;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
return null ;
2013-10-25 17:19:00 +02:00
}
2015-01-09 13:50:15 +01:00
private void fixUnsupportedMedia ( TLRPC . Message message ) {
2015-04-09 20:00:14 +02:00
if ( message = = null ) {
return ;
}
boolean ok = false ;
if ( message . media instanceof TLRPC . TL_messageMediaUnsupported_old ) {
2015-01-09 13:50:15 +01:00
if ( message . media . bytes . length = = 0 ) {
message . media . bytes = new byte [ 1 ] ;
message . media . bytes [ 0 ] = TLRPC . LAYER ;
}
2015-04-09 20:00:14 +02:00
} else if ( message . media instanceof TLRPC . TL_messageMediaUnsupported ) {
message . media = new TLRPC . TL_messageMediaUnsupported_old ( ) ;
message . media . bytes = new byte [ 1 ] ;
message . media . bytes [ 0 ] = TLRPC . LAYER ;
2015-09-24 22:52:02 +02:00
message . flags | = TLRPC . MESSAGE_FLAG_HAS_MEDIA ;
2015-01-09 13:50:15 +01:00
}
}
2015-09-24 22:52:02 +02:00
private void doneHolesInTable ( String table , long did , int max_id ) throws Exception {
if ( max_id = = 0 ) {
database . executeFast ( String . format ( Locale . US , " DELETE FROM " + table + " WHERE uid = %d " , did ) ) . stepThis ( ) . dispose ( ) ;
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM " + table + " WHERE uid = %d AND start = 0 " , did ) ) . stepThis ( ) . dispose ( ) ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO " + table + " VALUES(?, ?, ?) " ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , 1 ) ;
state . bindInteger ( 3 , 1 ) ;
state . step ( ) ;
state . dispose ( ) ;
}
public void doneHolesInMedia ( long did , int max_id , int type ) throws Exception {
if ( type = = - 1 ) {
if ( max_id = = 0 ) {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d " , did ) ) . stepThis ( ) . dispose ( ) ;
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d AND start = 0 " , did ) ) . stepThis ( ) . dispose ( ) ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?) " ) ;
for ( int a = 0 ; a < SharedMediaQuery . MEDIA_TYPES_COUNT ; a + + ) {
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , a ) ;
state . bindInteger ( 3 , 1 ) ;
state . bindInteger ( 4 , 1 ) ;
state . step ( ) ;
}
state . dispose ( ) ;
} else {
if ( max_id = = 0 ) {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d AND type = %d " , did , type ) ) . stepThis ( ) . dispose ( ) ;
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d AND type = %d AND start = 0 " , did , type ) ) . stepThis ( ) . dispose ( ) ;
}
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?) " ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , type ) ;
state . bindInteger ( 3 , 1 ) ;
state . bindInteger ( 4 , 1 ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
private class Hole {
public Hole ( int s , int e ) {
start = s ;
end = e ;
}
public Hole ( int t , int s , int e ) {
type = t ;
start = s ;
end = e ;
}
public int start ;
public int end ;
public int type ;
}
public void closeHolesInMedia ( long did , int minId , int maxId , int type ) throws Exception {
try {
boolean ok = false ;
SQLiteCursor cursor ;
if ( type < 0 ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT type, start, end FROM media_holes_v2 WHERE uid = %d AND type >= 0 AND ((end >= %d AND end <= %d) OR (start >= %d AND start <= %d) OR (start >= %d AND end <= %d) OR (start <= %d AND end >= %d)) " , did , minId , maxId , minId , maxId , minId , maxId , minId , maxId ) ) ;
} else {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT type, start, end FROM media_holes_v2 WHERE uid = %d AND type = %d AND ((end >= %d AND end <= %d) OR (start >= %d AND start <= %d) OR (start >= %d AND end <= %d) OR (start <= %d AND end >= %d)) " , did , type , minId , maxId , minId , maxId , minId , maxId , minId , maxId ) ) ;
}
ArrayList < Hole > holes = null ;
while ( cursor . next ( ) ) {
if ( holes = = null ) {
holes = new ArrayList < > ( ) ;
}
int holeType = cursor . intValue ( 0 ) ;
int start = cursor . intValue ( 1 ) ;
int end = cursor . intValue ( 2 ) ;
if ( start = = end & & start = = 1 ) {
continue ;
}
holes . add ( new Hole ( holeType , start , end ) ) ;
}
cursor . dispose ( ) ;
if ( holes ! = null ) {
for ( int a = 0 ; a < holes . size ( ) ; a + + ) {
Hole hole = holes . get ( a ) ;
if ( maxId > = hole . end - 1 & & minId < = hole . start + 1 ) {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d AND type = %d AND start = %d AND end = %d " , did , hole . type , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
} else if ( maxId > = hole . end - 1 ) {
if ( hole . end ! = minId ) {
try {
database . executeFast ( String . format ( Locale . US , " UPDATE media_holes_v2 SET end = %d WHERE uid = %d AND type = %d AND start = %d AND end = %d " , minId , did , hole . type , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} else if ( minId < = hole . start + 1 ) {
if ( hole . start ! = maxId ) {
try {
database . executeFast ( String . format ( Locale . US , " UPDATE media_holes_v2 SET start = %d WHERE uid = %d AND type = %d AND start = %d AND end = %d " , maxId , did , hole . type , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM media_holes_v2 WHERE uid = %d AND type = %d AND start = %d AND end = %d " , did , hole . type , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?) " ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , hole . type ) ;
state . bindInteger ( 3 , hole . start ) ;
state . bindInteger ( 4 , minId ) ;
state . step ( ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , hole . type ) ;
state . bindInteger ( 3 , maxId ) ;
state . bindInteger ( 4 , hole . end ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
}
private void closeHolesInTable ( String table , long did , int minId , int maxId ) throws Exception {
try {
boolean ok = false ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT start, end FROM " + table + " WHERE uid = %d AND ((end >= %d AND end <= %d) OR (start >= %d AND start <= %d) OR (start >= %d AND end <= %d) OR (start <= %d AND end >= %d)) " , did , minId , maxId , minId , maxId , minId , maxId , minId , maxId ) ) ;
ArrayList < Hole > holes = null ;
while ( cursor . next ( ) ) {
if ( holes = = null ) {
holes = new ArrayList < > ( ) ;
}
int start = cursor . intValue ( 0 ) ;
int end = cursor . intValue ( 1 ) ;
if ( start = = end & & start = = 1 ) {
continue ;
}
holes . add ( new Hole ( start , end ) ) ;
}
cursor . dispose ( ) ;
if ( holes ! = null ) {
for ( int a = 0 ; a < holes . size ( ) ; a + + ) {
Hole hole = holes . get ( a ) ;
if ( maxId > = hole . end - 1 & & minId < = hole . start + 1 ) {
database . executeFast ( String . format ( Locale . US , " DELETE FROM " + table + " WHERE uid = %d AND start = %d AND end = %d " , did , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
} else if ( maxId > = hole . end - 1 ) {
if ( hole . end ! = minId ) {
try {
database . executeFast ( String . format ( Locale . US , " UPDATE " + table + " SET end = %d WHERE uid = %d AND start = %d AND end = %d " , minId , did , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} else if ( minId < = hole . start + 1 ) {
if ( hole . start ! = maxId ) {
try {
2015-11-26 22:04:02 +01:00
database . executeFast ( String . format ( Locale . US , " UPDATE " + table + " SET start = %d WHERE uid = %d AND start = %d AND end = %d " , maxId , did , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
2015-09-24 22:52:02 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
} else {
database . executeFast ( String . format ( Locale . US , " DELETE FROM " + table + " WHERE uid = %d AND start = %d AND end = %d " , did , hole . start , hole . end ) ) . stepThis ( ) . dispose ( ) ;
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO " + table + " VALUES(?, ?, ?) " ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , hole . start ) ;
state . bindInteger ( 3 , minId ) ;
state . step ( ) ;
state . requery ( ) ;
state . bindLong ( 1 , did ) ;
state . bindInteger ( 2 , maxId ) ;
state . bindInteger ( 3 , hole . end ) ;
state . step ( ) ;
state . dispose ( ) ;
}
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
2016-06-24 12:27:15 +02:00
public void putMessages ( final TLRPC . messages_Messages messages , final long dialog_id , final int load_type , final int max_id , final boolean createDialog ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
2015-09-24 22:52:02 +02:00
if ( messages . messages . isEmpty ( ) ) {
if ( load_type = = 0 ) {
2016-06-24 12:27:15 +02:00
doneHolesInTable ( " messages_holes " , dialog_id , max_id ) ;
doneHolesInMedia ( dialog_id , max_id , - 1 ) ;
2015-09-24 22:52:02 +02:00
}
return ;
}
2013-10-25 17:19:00 +02:00
database . beginTransaction ( ) ;
2015-09-24 22:52:02 +02:00
if ( load_type = = 0 ) {
int minId = messages . messages . get ( messages . messages . size ( ) - 1 ) . id ;
2016-06-24 12:27:15 +02:00
closeHolesInTable ( " messages_holes " , dialog_id , minId , max_id ) ;
closeHolesInMedia ( dialog_id , minId , max_id , - 1 ) ;
2015-10-29 18:10:07 +01:00
} else if ( load_type = = 1 ) {
2015-09-24 22:52:02 +02:00
int maxId = messages . messages . get ( 0 ) . id ;
2016-06-24 12:27:15 +02:00
closeHolesInTable ( " messages_holes " , dialog_id , max_id , maxId ) ;
closeHolesInMedia ( dialog_id , max_id , maxId , - 1 ) ;
2017-03-31 01:58:05 +02:00
} else if ( load_type = = 3 | | load_type = = 2 | | load_type = = 4 ) {
int maxId = max_id = = 0 & & load_type ! = 4 ? Integer . MAX_VALUE : messages . messages . get ( 0 ) . id ;
2015-09-24 22:52:02 +02:00
int minId = messages . messages . get ( messages . messages . size ( ) - 1 ) . id ;
2016-06-24 12:27:15 +02:00
closeHolesInTable ( " messages_holes " , dialog_id , minId , maxId ) ;
closeHolesInMedia ( dialog_id , minId , maxId , - 1 ) ;
2015-09-24 22:52:02 +02:00
}
int count = messages . messages . size ( ) ;
//load_type == 0 ? backward loading
//load_type == 1 ? forward loading
//load_type == 2 ? load from first unread
//load_type == 3 ? load around message
2017-03-31 01:58:05 +02:00
//load_type == 4 ? load around date
2015-09-24 22:52:02 +02:00
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?) " ) ;
SQLitePreparedStatement state2 = database . executeFast ( " REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?) " ) ;
2016-05-25 23:49:47 +02:00
SQLitePreparedStatement state5 = null ;
2015-09-24 22:52:02 +02:00
TLRPC . Message botKeyboard = null ;
int minChannelMessageId = Integer . MAX_VALUE ;
int maxChannelMessageId = 0 ;
int channelId = 0 ;
for ( int a = 0 ; a < count ; a + + ) {
TLRPC . Message message = messages . messages . get ( a ) ;
long messageId = message . id ;
if ( channelId = = 0 ) {
channelId = message . to_id . channel_id ;
}
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) channelId ) < < 32 ;
}
2016-03-06 02:49:31 +01:00
if ( load_type = = - 2 ) {
2016-10-11 13:57:01 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT mid, data, ttl FROM messages WHERE mid = %d " , messageId ) ) ;
2016-05-25 23:49:47 +02:00
boolean exist ;
if ( exist = cursor . next ( ) ) {
NativeByteBuffer data = cursor . byteBufferValue ( 1 ) ;
if ( data ! = null ) {
TLRPC . Message oldMessage = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
if ( oldMessage ! = null ) {
message . attachPath = oldMessage . attachPath ;
2016-10-11 13:57:01 +02:00
message . ttl = cursor . intValue ( 2 ) ;
2016-05-25 23:49:47 +02:00
}
}
}
2016-03-06 02:49:31 +01:00
cursor . dispose ( ) ;
if ( ! exist ) {
continue ;
}
}
2015-09-24 22:52:02 +02:00
if ( a = = 0 & & createDialog ) {
2017-03-31 01:58:05 +02:00
int pinned = 0 ;
SQLiteCursor cursor = database . queryFinalized ( " SELECT pinned FROM dialogs WHERE did = " + dialog_id ) ;
if ( cursor . next ( ) ) {
pinned = cursor . intValue ( 0 ) ;
}
cursor . dispose ( ) ;
SQLitePreparedStatement state3 = database . executeFast ( " REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
state3 . bindLong ( 1 , dialog_id ) ;
state3 . bindInteger ( 2 , message . date ) ;
state3 . bindInteger ( 3 , 0 ) ;
state3 . bindLong ( 4 , messageId ) ;
state3 . bindInteger ( 5 , message . id ) ;
state3 . bindInteger ( 6 , 0 ) ;
state3 . bindLong ( 7 , messageId ) ;
2016-04-22 15:49:00 +02:00
state3 . bindInteger ( 8 , message . ttl ) ;
2015-09-24 22:52:02 +02:00
state3 . bindInteger ( 9 , messages . pts ) ;
state3 . bindInteger ( 10 , message . date ) ;
2017-03-31 01:58:05 +02:00
state3 . bindInteger ( 11 , pinned ) ;
2015-09-24 22:52:02 +02:00
state3 . step ( ) ;
state3 . dispose ( ) ;
}
fixUnsupportedMedia ( message ) ;
state . requery ( ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
state . bindLong ( 1 , messageId ) ;
state . bindLong ( 2 , dialog_id ) ;
state . bindInteger ( 3 , MessageObject . getUnreadFlags ( message ) ) ;
state . bindInteger ( 4 , message . send_state ) ;
state . bindInteger ( 5 , message . date ) ;
state . bindByteBuffer ( 6 , data ) ;
state . bindInteger ( 7 , ( MessageObject . isOut ( message ) ? 1 : 0 ) ) ;
2017-07-23 14:56:38 +02:00
state . bindInteger ( 8 , message . ttl ) ;
2015-09-24 22:52:02 +02:00
if ( ( message . flags & TLRPC . MESSAGE_FLAG_HAS_VIEWS ) ! = 0 ) {
state . bindInteger ( 9 , message . views ) ;
} else {
2017-07-23 14:56:38 +02:00
state . bindInteger ( 9 , getMessageMediaType ( message ) ) ;
2015-09-24 22:52:02 +02:00
}
2016-06-24 12:27:15 +02:00
state . bindInteger ( 10 , 0 ) ;
2015-09-24 22:52:02 +02:00
state . step ( ) ;
2013-10-25 17:19:00 +02:00
2015-09-24 22:52:02 +02:00
if ( SharedMediaQuery . canAddMessageToMedia ( message ) ) {
state2 . requery ( ) ;
state2 . bindLong ( 1 , messageId ) ;
state2 . bindLong ( 2 , dialog_id ) ;
state2 . bindInteger ( 3 , message . date ) ;
state2 . bindInteger ( 4 , SharedMediaQuery . getMediaType ( message ) ) ;
state2 . bindByteBuffer ( 5 , data ) ;
state2 . step ( ) ;
}
data . reuse ( ) ;
2017-03-31 01:58:05 +02:00
if ( message . media instanceof TLRPC . TL_messageMediaWebPage ) {
2016-05-25 23:49:47 +02:00
if ( state5 = = null ) {
state5 = database . executeFast ( " REPLACE INTO webpage_pending VALUES(?, ?) " ) ;
}
state5 . requery ( ) ;
state5 . bindLong ( 1 , message . media . webpage . id ) ;
state5 . bindLong ( 2 , messageId ) ;
state5 . step ( ) ;
}
2015-09-24 22:52:02 +02:00
2016-04-22 15:49:00 +02:00
if ( load_type = = 0 & & isValidKeyboardToSave ( message ) ) {
2015-09-24 22:52:02 +02:00
if ( botKeyboard = = null | | botKeyboard . id < message . id ) {
botKeyboard = message ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
}
}
state . dispose ( ) ;
state2 . dispose ( ) ;
2016-05-25 23:49:47 +02:00
if ( state5 ! = null ) {
state5 . dispose ( ) ;
}
2015-09-24 22:52:02 +02:00
if ( botKeyboard ! = null ) {
BotQuery . putBotKeyboard ( dialog_id , botKeyboard ) ;
}
2015-06-29 19:12:11 +02:00
2014-10-23 17:30:35 +02:00
putUsersInternal ( messages . users ) ;
putChatsInternal ( messages . chats ) ;
2013-10-25 17:19:00 +02:00
database . commitTransaction ( ) ;
2015-09-24 22:52:02 +02:00
if ( createDialog ) {
2017-03-31 01:58:05 +02:00
MessagesStorage . getInstance ( ) . updateDialogsWithDeletedMessages ( new ArrayList < Integer > ( ) , null , false , channelId ) ;
2015-09-24 22:52:02 +02:00
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2013-10-25 17:19:00 +02:00
}
}
} ) ;
}
2015-11-26 22:04:02 +01:00
public static void addUsersAndChatsFromMessage ( TLRPC . Message message , ArrayList < Integer > usersToLoad , ArrayList < Integer > chatsToLoad ) {
if ( message . from_id ! = 0 ) {
if ( message . from_id > 0 ) {
if ( ! usersToLoad . contains ( message . from_id ) ) {
usersToLoad . add ( message . from_id ) ;
}
} else {
if ( ! chatsToLoad . contains ( - message . from_id ) ) {
chatsToLoad . add ( - message . from_id ) ;
}
}
}
2016-01-11 18:19:48 +01:00
if ( message . via_bot_id ! = 0 & & ! usersToLoad . contains ( message . via_bot_id ) ) {
usersToLoad . add ( message . via_bot_id ) ;
}
2015-11-26 22:04:02 +01:00
if ( message . action ! = null ) {
if ( message . action . user_id ! = 0 & & ! usersToLoad . contains ( message . action . user_id ) ) {
usersToLoad . add ( message . action . user_id ) ;
}
if ( message . action . channel_id ! = 0 & & ! chatsToLoad . contains ( message . action . channel_id ) ) {
chatsToLoad . add ( message . action . channel_id ) ;
}
if ( message . action . chat_id ! = 0 & & ! chatsToLoad . contains ( message . action . chat_id ) ) {
chatsToLoad . add ( message . action . chat_id ) ;
}
if ( ! message . action . users . isEmpty ( ) ) {
for ( int a = 0 ; a < message . action . users . size ( ) ; a + + ) {
Integer uid = message . action . users . get ( a ) ;
if ( ! usersToLoad . contains ( uid ) ) {
usersToLoad . add ( uid ) ;
}
}
}
}
2016-05-25 23:49:47 +02:00
if ( ! message . entities . isEmpty ( ) ) {
for ( int a = 0 ; a < message . entities . size ( ) ; a + + ) {
TLRPC . MessageEntity entity = message . entities . get ( a ) ;
if ( entity instanceof TLRPC . TL_messageEntityMentionName ) {
usersToLoad . add ( ( ( TLRPC . TL_messageEntityMentionName ) entity ) . user_id ) ;
} else if ( entity instanceof TLRPC . TL_inputMessageEntityMentionName ) {
usersToLoad . add ( ( ( TLRPC . TL_inputMessageEntityMentionName ) entity ) . user_id . user_id ) ;
}
}
}
2015-11-26 22:04:02 +01:00
if ( message . media ! = null ) {
if ( message . media . user_id ! = 0 & & ! usersToLoad . contains ( message . media . user_id ) ) {
usersToLoad . add ( message . media . user_id ) ;
}
}
2016-03-06 02:49:31 +01:00
if ( message . fwd_from ! = null ) {
if ( message . fwd_from . from_id ! = 0 ) {
if ( ! usersToLoad . contains ( message . fwd_from . from_id ) ) {
usersToLoad . add ( message . fwd_from . from_id ) ;
}
2015-11-26 22:04:02 +01:00
}
2016-03-06 02:49:31 +01:00
if ( message . fwd_from . channel_id ! = 0 ) {
if ( ! chatsToLoad . contains ( message . fwd_from . channel_id ) ) {
chatsToLoad . add ( message . fwd_from . channel_id ) ;
}
2015-11-26 22:04:02 +01:00
}
}
if ( message . ttl < 0 ) {
if ( ! chatsToLoad . contains ( - message . ttl ) ) {
chatsToLoad . add ( - message . ttl ) ;
}
}
}
public void getDialogs ( final int offset , final int count ) {
2013-10-25 17:19:00 +02:00
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
TLRPC . messages_Dialogs dialogs = new TLRPC . messages_Dialogs ( ) ;
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
2013-10-25 17:19:00 +02:00
try {
2015-01-02 23:15:07 +01:00
ArrayList < Integer > usersToLoad = new ArrayList < > ( ) ;
2014-06-13 12:42:21 +02:00
usersToLoad . add ( UserConfig . getClientUserId ( ) ) ;
2015-01-02 23:15:07 +01:00
ArrayList < Integer > chatsToLoad = new ArrayList < > ( ) ;
ArrayList < Integer > encryptedToLoad = new ArrayList < > ( ) ;
2016-03-16 13:26:32 +01:00
ArrayList < Long > replyMessages = new ArrayList < > ( ) ;
HashMap < Long , TLRPC . Message > replyMessageOwners = new HashMap < > ( ) ;
2017-03-31 01:58:05 +02:00
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT d.did, d.last_mid, d.unread_count, d.date, m.data, m.read_state, m.mid, m.send_state, s.flags, m.date, d.pts, d.inbox_max, d.outbox_max, m.replydata, d.pinned FROM dialogs as d LEFT JOIN messages as m ON d.last_mid = m.mid LEFT JOIN dialog_settings as s ON d.did = s.did ORDER BY d.pinned DESC, d.date DESC LIMIT %d,%d " , offset , count ) ) ;
2013-10-25 17:19:00 +02:00
while ( cursor . next ( ) ) {
2016-06-24 12:27:15 +02:00
TLRPC . TL_dialog dialog = new TLRPC . TL_dialog ( ) ;
dialog . id = cursor . longValue ( 0 ) ;
2013-10-25 17:19:00 +02:00
dialog . top_message = cursor . intValue ( 1 ) ;
dialog . unread_count = cursor . intValue ( 2 ) ;
dialog . last_message_date = cursor . intValue ( 3 ) ;
2016-06-24 12:27:15 +02:00
dialog . pts = cursor . intValue ( 10 ) ;
dialog . flags = dialog . pts = = 0 | | ( int ) dialog . id > 0 ? 0 : 1 ;
dialog . read_inbox_max_id = cursor . intValue ( 11 ) ;
dialog . read_outbox_max_id = cursor . intValue ( 12 ) ;
2017-03-31 01:58:05 +02:00
dialog . pinnedNum = cursor . intValue ( 14 ) ;
dialog . pinned = dialog . pinnedNum ! = 0 ;
2015-02-01 19:51:02 +01:00
long flags = cursor . longValue ( 8 ) ;
2016-06-24 12:27:15 +02:00
int low_flags = ( int ) flags ;
2015-02-01 19:51:02 +01:00
dialog . notify_settings = new TLRPC . TL_peerNotifySettings ( ) ;
if ( ( low_flags & 1 ) ! = 0 ) {
2016-06-24 12:27:15 +02:00
dialog . notify_settings . mute_until = ( int ) ( flags > > 32 ) ;
2015-02-01 19:51:02 +01:00
if ( dialog . notify_settings . mute_until = = 0 ) {
dialog . notify_settings . mute_until = Integer . MAX_VALUE ;
}
}
2013-10-25 17:19:00 +02:00
dialogs . dialogs . add ( dialog ) ;
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 4 ) ;
if ( data ! = null ) {
2015-05-03 13:48:36 +02:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2013-10-25 17:19:00 +02:00
if ( message ! = null ) {
2015-05-03 13:48:36 +02:00
MessageObject . setUnreadFlags ( message , cursor . intValue ( 5 ) ) ;
2013-10-25 17:19:00 +02:00
message . id = cursor . intValue ( 6 ) ;
2015-02-26 02:32:51 +01:00
int date = cursor . intValue ( 9 ) ;
if ( date ! = 0 ) {
dialog . last_message_date = date ;
}
2013-10-25 17:19:00 +02:00
message . send_state = cursor . intValue ( 7 ) ;
2015-09-24 22:52:02 +02:00
message . dialog_id = dialog . id ;
2013-10-25 17:19:00 +02:00
dialogs . messages . add ( message ) ;
2015-11-26 22:04:02 +01:00
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
2016-03-16 13:26:32 +01:00
try {
2017-03-31 01:58:05 +02:00
if ( message . reply_to_msg_id ! = 0 & & (
message . action instanceof TLRPC . TL_messageActionPinMessage | |
message . action instanceof TLRPC . TL_messageActionPaymentSent | |
message . action instanceof TLRPC . TL_messageActionGameScore ) ) {
2016-06-24 12:27:15 +02:00
if ( ! cursor . isNull ( 13 ) ) {
data = cursor . byteBufferValue ( 13 ) ;
2016-05-25 23:49:47 +02:00
if ( data ! = null ) {
message . replyMessage = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
if ( message . replyMessage ! = null ) {
addUsersAndChatsFromMessage ( message . replyMessage , usersToLoad , chatsToLoad ) ;
}
}
}
if ( message . replyMessage = = null ) {
long messageId = message . reply_to_msg_id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
if ( ! replyMessages . contains ( messageId ) ) {
replyMessages . add ( messageId ) ;
}
replyMessageOwners . put ( dialog . id , message ) ;
}
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-03-16 13:26:32 +01:00
}
2013-10-25 17:19:00 +02:00
}
}
2016-06-24 12:27:15 +02:00
int lower_id = ( int ) dialog . id ;
int high_id = ( int ) ( dialog . id > > 32 ) ;
2013-10-25 17:19:00 +02:00
if ( lower_id ! = 0 ) {
2014-07-27 12:53:00 +02:00
if ( high_id = = 1 ) {
if ( ! chatsToLoad . contains ( lower_id ) ) {
chatsToLoad . add ( lower_id ) ;
2013-10-25 17:19:00 +02:00
}
} else {
2014-07-27 12:53:00 +02:00
if ( lower_id > 0 ) {
if ( ! usersToLoad . contains ( lower_id ) ) {
usersToLoad . add ( lower_id ) ;
}
} else {
if ( ! chatsToLoad . contains ( - lower_id ) ) {
chatsToLoad . add ( - lower_id ) ;
}
2013-10-25 17:19:00 +02:00
}
}
} else {
2014-07-27 12:53:00 +02:00
if ( ! encryptedToLoad . contains ( high_id ) ) {
encryptedToLoad . add ( high_id ) ;
2013-10-25 17:19:00 +02:00
}
}
}
cursor . dispose ( ) ;
2016-03-16 13:26:32 +01:00
if ( ! replyMessages . isEmpty ( ) ) {
cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT data, mid, date, uid FROM messages WHERE mid IN(%s) " , TextUtils . join ( " , " , replyMessages ) ) ) ;
while ( cursor . next ( ) ) {
2016-05-25 23:49:47 +02:00
NativeByteBuffer data = cursor . byteBufferValue ( 0 ) ;
if ( data ! = null ) {
2016-03-16 13:26:32 +01:00
TLRPC . Message message = TLRPC . Message . TLdeserialize ( data , data . readInt32 ( false ) , false ) ;
2016-05-25 23:49:47 +02:00
data . reuse ( ) ;
2016-03-16 13:26:32 +01:00
message . id = cursor . intValue ( 1 ) ;
message . date = cursor . intValue ( 2 ) ;
message . dialog_id = cursor . longValue ( 3 ) ;
addUsersAndChatsFromMessage ( message , usersToLoad , chatsToLoad ) ;
TLRPC . Message owner = replyMessageOwners . get ( message . dialog_id ) ;
if ( owner ! = null ) {
owner . replyMessage = message ;
message . dialog_id = owner . dialog_id ;
}
}
}
cursor . dispose ( ) ;
}
2013-10-25 17:19:00 +02:00
if ( ! encryptedToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getEncryptedChatsInternal ( TextUtils . join ( " , " , encryptedToLoad ) , encryptedChats , usersToLoad ) ;
2013-10-25 17:19:00 +02:00
}
if ( ! chatsToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getChatsInternal ( TextUtils . join ( " , " , chatsToLoad ) , dialogs . chats ) ;
2013-10-25 17:19:00 +02:00
}
if ( ! usersToLoad . isEmpty ( ) ) {
2014-10-23 17:30:35 +02:00
getUsersInternal ( TextUtils . join ( " , " , usersToLoad ) , dialogs . users ) ;
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
MessagesController . getInstance ( ) . processLoadedDialogs ( dialogs , encryptedChats , offset , count , 1 , false , false , true ) ;
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
dialogs . dialogs . clear ( ) ;
dialogs . users . clear ( ) ;
dialogs . chats . clear ( ) ;
encryptedChats . clear ( ) ;
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
MessagesController . getInstance ( ) . processLoadedDialogs ( dialogs , encryptedChats , 0 , 100 , 1 , true , false , true ) ;
2013-10-25 17:19:00 +02:00
}
}
2014-02-11 15:32:09 +01:00
} ) ;
2013-10-25 17:19:00 +02:00
}
2016-06-24 12:27:15 +02:00
public static void createFirstHoles ( long did , SQLitePreparedStatement state5 , SQLitePreparedStatement state6 , int messageId ) throws Exception {
state5 . requery ( ) ;
state5 . bindLong ( 1 , did ) ;
state5 . bindInteger ( 2 , messageId = = 1 ? 1 : 0 ) ;
state5 . bindInteger ( 3 , messageId ) ;
state5 . step ( ) ;
for ( int b = 0 ; b < SharedMediaQuery . MEDIA_TYPES_COUNT ; b + + ) {
state6 . requery ( ) ;
state6 . bindLong ( 1 , did ) ;
state6 . bindInteger ( 2 , b ) ;
state6 . bindInteger ( 3 , messageId = = 1 ? 1 : 0 ) ;
state6 . bindInteger ( 4 , messageId ) ;
state6 . step ( ) ;
2015-12-09 19:27:52 +01:00
}
}
2017-03-31 01:58:05 +02:00
private void putDialogsInternal ( final TLRPC . messages_Dialogs dialogs , boolean check ) {
2015-09-24 22:52:02 +02:00
try {
database . beginTransaction ( ) ;
2016-06-24 12:27:15 +02:00
final HashMap < Long , TLRPC . Message > new_dialogMessage = new HashMap < > ( ) ;
2015-09-24 22:52:02 +02:00
for ( int a = 0 ; a < dialogs . messages . size ( ) ; a + + ) {
TLRPC . Message message = dialogs . messages . get ( a ) ;
2016-06-24 12:27:15 +02:00
new_dialogMessage . put ( message . dialog_id , message ) ;
2015-09-24 22:52:02 +02:00
}
if ( ! dialogs . dialogs . isEmpty ( ) ) {
SQLitePreparedStatement state = database . executeFast ( " REPLACE INTO messages VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, NULL, ?) " ) ;
2017-03-31 01:58:05 +02:00
SQLitePreparedStatement state2 = database . executeFast ( " REPLACE INTO dialogs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) " ) ;
2015-09-24 22:52:02 +02:00
SQLitePreparedStatement state3 = database . executeFast ( " REPLACE INTO media_v2 VALUES(?, ?, ?, ?, ?) " ) ;
SQLitePreparedStatement state4 = database . executeFast ( " REPLACE INTO dialog_settings VALUES(?, ?) " ) ;
SQLitePreparedStatement state5 = database . executeFast ( " REPLACE INTO messages_holes VALUES(?, ?, ?) " ) ;
SQLitePreparedStatement state6 = database . executeFast ( " REPLACE INTO media_holes_v2 VALUES(?, ?, ?, ?) " ) ;
for ( int a = 0 ; a < dialogs . dialogs . size ( ) ; a + + ) {
2016-06-24 12:27:15 +02:00
TLRPC . TL_dialog dialog = dialogs . dialogs . get ( a ) ;
2015-09-24 22:52:02 +02:00
if ( dialog . id = = 0 ) {
if ( dialog . peer . user_id ! = 0 ) {
dialog . id = dialog . peer . user_id ;
} else if ( dialog . peer . chat_id ! = 0 ) {
dialog . id = - dialog . peer . chat_id ;
} else {
dialog . id = - dialog . peer . channel_id ;
}
2013-10-25 17:19:00 +02:00
}
2017-03-31 01:58:05 +02:00
if ( check ) {
SQLiteCursor cursor = database . queryFinalized ( " SELECT did FROM dialogs WHERE did = " + dialog . id ) ;
boolean exists = cursor . next ( ) ;
cursor . dispose ( ) ;
if ( exists ) {
continue ;
}
}
2015-09-24 22:52:02 +02:00
int messageDate = 0 ;
2013-10-25 17:19:00 +02:00
2016-06-24 12:27:15 +02:00
TLRPC . Message message = new_dialogMessage . get ( dialog . id ) ;
if ( message ! = null ) {
messageDate = Math . max ( message . date , messageDate ) ;
2013-10-25 17:19:00 +02:00
2016-06-24 12:27:15 +02:00
if ( isValidKeyboardToSave ( message ) ) {
BotQuery . putBotKeyboard ( dialog . id , message ) ;
}
2015-06-29 19:12:11 +02:00
2016-06-24 12:27:15 +02:00
fixUnsupportedMedia ( message ) ;
NativeByteBuffer data = new NativeByteBuffer ( message . getObjectSize ( ) ) ;
message . serializeToStream ( data ) ;
2013-10-25 17:19:00 +02:00
2016-06-24 12:27:15 +02:00
long messageId = message . id ;
if ( message . to_id . channel_id ! = 0 ) {
messageId | = ( ( long ) message . to_id . channel_id ) < < 32 ;
}
2015-06-29 19:12:11 +02:00
2016-06-24 12:27:15 +02:00
state . requery ( ) ;
state . bindLong ( 1 , messageId ) ;
state . bindLong ( 2 , dialog . id ) ;
state . bindInteger ( 3 , MessageObject . getUnreadFlags ( message ) ) ;
state . bindInteger ( 4 , message . send_state ) ;
state . bindInteger ( 5 , message . date ) ;
state . bindByteBuffer ( 6 , data ) ;
state . bindInteger ( 7 , ( MessageObject . isOut ( message ) ? 1 : 0 ) ) ;
state . bindInteger ( 8 , 0 ) ;
state . bindInteger ( 9 , ( message . flags & TLRPC . MESSAGE_FLAG_HAS_VIEWS ) ! = 0 ? message . views : 0 ) ;
state . bindInteger ( 10 , 0 ) ;
state . step ( ) ;
if ( SharedMediaQuery . canAddMessageToMedia ( message ) ) {
state3 . requery ( ) ;
state3 . bindLong ( 1 , messageId ) ;
state3 . bindLong ( 2 , dialog . id ) ;
state3 . bindInteger ( 3 , message . date ) ;
state3 . bindInteger ( 4 , SharedMediaQuery . getMediaType ( message ) ) ;
state3 . bindByteBuffer ( 5 , data ) ;
state3 . step ( ) ;
2015-09-24 22:52:02 +02:00
}
2016-06-24 12:27:15 +02:00
data . reuse ( ) ;
2015-09-24 22:52:02 +02:00
2016-06-24 12:27:15 +02:00
createFirstHoles ( dialog . id , state5 , state6 , message . id ) ;
2013-10-25 17:19:00 +02:00
}
2015-09-24 22:52:02 +02:00
long topMessage = dialog . top_message ;
if ( dialog . peer . channel_id ! = 0 ) {
topMessage | = ( ( long ) dialog . peer . channel_id ) < < 32 ;
}
2013-10-25 17:19:00 +02:00
2015-09-24 22:52:02 +02:00
state2 . requery ( ) ;
state2 . bindLong ( 1 , dialog . id ) ;
state2 . bindInteger ( 2 , messageDate ) ;
state2 . bindInteger ( 3 , dialog . unread_count ) ;
state2 . bindLong ( 4 , topMessage ) ;
state2 . bindInteger ( 5 , dialog . read_inbox_max_id ) ;
2016-06-24 12:27:15 +02:00
state2 . bindInteger ( 6 , dialog . read_outbox_max_id ) ;
state2 . bindLong ( 7 , 0 ) ;
state2 . bindInteger ( 8 , 0 ) ;
2015-09-24 22:52:02 +02:00
state2 . bindInteger ( 9 , dialog . pts ) ;
2016-06-24 12:27:15 +02:00
state2 . bindInteger ( 10 , 0 ) ;
2017-03-31 01:58:05 +02:00
state2 . bindInteger ( 11 , dialog . pinnedNum ) ;
2015-09-24 22:52:02 +02:00
state2 . step ( ) ;
if ( dialog . notify_settings ! = null ) {
state4 . requery ( ) ;
state4 . bindLong ( 1 , dialog . id ) ;
state4 . bindInteger ( 2 , dialog . notify_settings . mute_until ! = 0 ? 1 : 0 ) ;
state4 . step ( ) ;
}
}
state . dispose ( ) ;
state2 . dispose ( ) ;
state3 . dispose ( ) ;
state4 . dispose ( ) ;
state5 . dispose ( ) ;
state6 . dispose ( ) ;
}
putUsersInternal ( dialogs . users ) ;
putChatsInternal ( dialogs . chats ) ;
database . commitTransaction ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
}
2017-03-31 01:58:05 +02:00
public void unpinAllDialogsExceptNew ( final ArrayList < Long > dids ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
ArrayList < Long > unpinnedDialogs = new ArrayList < > ( ) ;
SQLiteCursor cursor = database . queryFinalized ( String . format ( Locale . US , " SELECT did FROM dialogs WHERE pinned != 0 AND did NOT IN (%s) " , TextUtils . join ( " , " , dids ) ) ) ;
while ( cursor . next ( ) ) {
long did = cursor . longValue ( 0 ) ;
if ( ( int ) did ! = 0 ) {
unpinnedDialogs . add ( cursor . longValue ( 0 ) ) ;
}
}
cursor . dispose ( ) ;
if ( ! unpinnedDialogs . isEmpty ( ) ) {
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET pinned = ? WHERE did = ? " ) ;
for ( int a = 0 ; a < unpinnedDialogs . size ( ) ; a + + ) {
long did = unpinnedDialogs . get ( a ) ;
state . requery ( ) ;
state . bindInteger ( 1 , 0 ) ;
state . bindLong ( 2 , did ) ;
state . step ( ) ;
}
state . dispose ( ) ;
}
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
public void setDialogPinned ( final long did , final int pinned ) {
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
try {
SQLitePreparedStatement state = database . executeFast ( " UPDATE dialogs SET pinned = ? WHERE did = ? " ) ;
state . bindInteger ( 1 , pinned ) ;
state . bindLong ( 2 , did ) ;
state . step ( ) ;
state . dispose ( ) ;
} catch ( Exception e ) {
FileLog . e ( e ) ;
}
}
} ) ;
}
public void putDialogs ( final TLRPC . messages_Dialogs dialogs , final boolean check ) {
2015-09-24 22:52:02 +02:00
if ( dialogs . dialogs . isEmpty ( ) ) {
return ;
}
storageQueue . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
2017-03-31 01:58:05 +02:00
putDialogsInternal ( dialogs , check ) ;
2015-09-24 22:52:02 +02:00
loadUnreadMessages ( ) ;
}
} ) ;
}
2014-07-11 15:54:17 +02:00
2016-06-24 12:27:15 +02:00
public int getDialogReadMax ( final boolean outbox , final long dialog_id ) {
2015-11-26 22:04:02 +01:00
final Semaphore semaphore = new Semaphore ( 0 ) ;
2016-06-24 12:27:15 +02:00
final Integer [ ] max = new Integer [ ] { 0 } ;
2015-11-26 22:04:02 +01:00
MessagesStorage . getInstance ( ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLiteCursor cursor = null ;
try {
2016-06-24 12:27:15 +02:00
if ( outbox ) {
cursor = database . queryFinalized ( " SELECT outbox_max FROM dialogs WHERE did = " + dialog_id ) ;
} else {
cursor = database . queryFinalized ( " SELECT inbox_max FROM dialogs WHERE did = " + dialog_id ) ;
}
2015-11-26 22:04:02 +01:00
if ( cursor . next ( ) ) {
max [ 0 ] = cursor . intValue ( 0 ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-11-26 22:04:02 +01:00
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
}
semaphore . release ( ) ;
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-11-26 22:04:02 +01:00
}
return max [ 0 ] ;
}
2015-09-24 22:52:02 +02:00
public int getChannelPtsSync ( final int channelId ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
2016-06-24 12:27:15 +02:00
final Integer [ ] pts = new Integer [ ] { 0 } ;
2015-09-24 22:52:02 +02:00
MessagesStorage . getInstance ( ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
SQLiteCursor cursor = null ;
try {
cursor = database . queryFinalized ( " SELECT pts FROM dialogs WHERE did = " + ( - channelId ) ) ;
if ( cursor . next ( ) ) {
pts [ 0 ] = cursor . intValue ( 0 ) ;
}
2013-10-25 17:19:00 +02:00
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
} finally {
if ( cursor ! = null ) {
cursor . dispose ( ) ;
}
2013-10-25 17:19:00 +02:00
}
2016-01-11 18:19:48 +01:00
try {
if ( semaphore ! = null ) {
semaphore . release ( ) ;
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2016-01-11 18:19:48 +01:00
}
2013-10-25 17:19:00 +02:00
}
} ) ;
2015-09-24 22:52:02 +02:00
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-09-24 22:52:02 +02:00
}
return pts [ 0 ] ;
2013-10-25 17:19:00 +02:00
}
2014-03-26 21:16:28 +01:00
2015-04-09 20:00:14 +02:00
public TLRPC . User getUserSync ( final int user_id ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
final TLRPC . User [ ] user = new TLRPC . User [ 1 ] ;
MessagesStorage . getInstance ( ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
user [ 0 ] = getUser ( user_id ) ;
semaphore . release ( ) ;
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-04-09 20:00:14 +02:00
}
return user [ 0 ] ;
}
public TLRPC . Chat getChatSync ( final int user_id ) {
final Semaphore semaphore = new Semaphore ( 0 ) ;
final TLRPC . Chat [ ] chat = new TLRPC . Chat [ 1 ] ;
MessagesStorage . getInstance ( ) . getStorageQueue ( ) . postRunnable ( new Runnable ( ) {
@Override
public void run ( ) {
chat [ 0 ] = getChat ( user_id ) ;
semaphore . release ( ) ;
}
} ) ;
try {
semaphore . acquire ( ) ;
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2015-04-09 20:00:14 +02:00
}
return chat [ 0 ] ;
}
2014-03-26 21:16:28 +01:00
public TLRPC . User getUser ( final int user_id ) {
TLRPC . User user = null ;
try {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getUsersInternal ( " " + user_id , users ) ;
if ( ! users . isEmpty ( ) ) {
user = users . get ( 0 ) ;
2014-03-26 21:16:28 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-03-26 21:16:28 +01:00
}
return user ;
}
2014-10-23 17:30:35 +02:00
public ArrayList < TLRPC . User > getUsers ( final ArrayList < Integer > uids ) {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . User > users = new ArrayList < > ( ) ;
2014-03-26 21:16:28 +01:00
try {
2014-10-23 17:30:35 +02:00
getUsersInternal ( TextUtils . join ( " , " , uids ) , users ) ;
2014-03-26 21:16:28 +01:00
} catch ( Exception e ) {
2014-10-23 17:30:35 +02:00
users . clear ( ) ;
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-03-26 21:16:28 +01:00
}
return users ;
}
public TLRPC . Chat getChat ( final int chat_id ) {
TLRPC . Chat chat = null ;
try {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . Chat > chats = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getChatsInternal ( " " + chat_id , chats ) ;
if ( ! chats . isEmpty ( ) ) {
chat = chats . get ( 0 ) ;
2014-03-26 21:16:28 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-03-26 21:16:28 +01:00
}
return chat ;
}
public TLRPC . EncryptedChat getEncryptedChat ( final int chat_id ) {
TLRPC . EncryptedChat chat = null ;
try {
2015-01-02 23:15:07 +01:00
ArrayList < TLRPC . EncryptedChat > encryptedChats = new ArrayList < > ( ) ;
2014-10-23 17:30:35 +02:00
getEncryptedChatsInternal ( " " + chat_id , encryptedChats , null ) ;
if ( ! encryptedChats . isEmpty ( ) ) {
chat = encryptedChats . get ( 0 ) ;
2014-03-26 21:16:28 +01:00
}
} catch ( Exception e ) {
2017-03-31 01:58:05 +02:00
FileLog . e ( e ) ;
2014-03-26 21:16:28 +01:00
}
return chat ;
}
2013-10-25 17:19:00 +02:00
}